#新らしい形式クラス class X(object): pass class Y(): __metaclass__ = type Z = type("Z",(),{}) #古い形式クラス class H(): pass print type(X) #<type 'type'> print type(Y) #<type 'type'> print type(Z) #<type 'type'> print type(H) #<type 'classobj'> >>46のメタクラス決定順の通り、クラスオブジェクトHは旧式のメタクラスが使用されている。
54 :
#「ok]という属性にだけ代入ができるクラスA #ラッパー関数 def rap(func): def t(self, name, value): if name == "ok": func(self, name, value) else: raise AttributeError("代入できません") return t class A(): class __metaclass__(type): __setattr__ = rap(type.__setattr__)
55 :
>>54 こっちの方が解りやすかった class A(): class __metaclass__(type): def __setattr__(self, name, value): if name == "ok": type.__setattr__(self, name, value) else: raise AttributeError("代入できません")
56 :
>>> class A(object): ... __slots__ = ("ok",) ... >>> a = A() >>> a.ok = 0 >>> a.ng = 0 Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'A' object has no attribute 'ng'
>class A(): > class __metaclass__(type): その書き方は、Guido が completely unreadable って言ってた
59 :
>>58 まじ?class定義の中でまたclass定義してるのがイヤなのかな? となると class B(type): def __setattr__(self, name, value): if name == "ok": type.__setattr__(self, name, value) else: raise AttributeError("代入できません") class A(): __metaclass__ = B って感じなのかな〜?
60 :
あるクラスが __getitem__() という名前のメソッドを定義 しており、 x がこのクラスのインスタンスであるとすると、 x[i] は x.__getitem__(i) と等価になります。 特に注釈の ない限り、適切なメソッドが定義されていない場合にこのような演算を行おうと すると例外が送出されます。 #コンテナをエミュレートする class A(object): def __getitem__(self, key): pass x = A() の場合 x[i]とx.__getitem__(i)は等価
__contains__()メソッドはインスタンスオブジェクトoにKey kが存在するかのチェックを if k in o と簡単に書けるようにするためのメソッド
67 :
コンテナへ反復処理を実装する。 そのためには__iter__()メソッドを定義する。 このメソッドはイテレータオブジェクトを返すようにする。 イテレータオブジェクトはイテレータプロトコルをサポートする必要がある。 __iter__()とnext()の2つのメソッドがイテレータプロトコルを成す。 class A(object): data = "abc" def __iter__(self): return iter(self.data) >>> a = A() >>> for c in a: ... c ... 'a' 'b' 'c'
68 :
クラス自体で next() を定義している場合、__iter__() では 単に self を返すようにできる。 class B(object): data = "abc" index = 0 def __iter__(self): print type(self) return self def next(self): print type(self) if self.index == len(self.data): raise StopIteration self.index += 1 return self.data[self.index - 1] selfの中身はインスタンス。 selfという名前は慣習。
69 :
素の list が結構便利に出来てるから、 そこまで手の込んだクラスがどうしても必要になる場面は そんなに多くないよ。まあ、知ってて損はないけど
string モジュールを使ったプレースホルダ import string s = string.Template("$who have $what") #キーワード引数を使用する print s.substitute(who='I', what='apple') #I have apple #テンプレートにないKeyはスルーされる print s.substitute(who='I', what='apple', a="abc") #I have apple #辞書オブジェクトが引数の場合 d = dict(who='I', what="apple") print s.substitute(d) #I have apple #locals()を引数にする。 #locals()は値のある変数をキーとした人工的な辞書 msg = string.Template("the square of $number is $square") for number in range(10): square = number * number print msg.substitute(locals())
マップ型のfromkeysメソッド mapping.fromkeys(seq[, value]) seq からキーを作り、値が value であるような、新しい辞書を作成します >>> d = {"A":1,"B":2} >>> d {'A': 1, 'B': 2} >>> dict.fromkeys([k.lower() for k in d]) {'a': None, 'b': None}