クラスのアトリビュートには、通常の class.attribute というアクセス方法以外にも、class.__dict__['attribute'] というアクセス方法もあります。
>>> class Test(object): ... def __init__(self): ... self.test1 = 1 ... >>> t = Test() # 通常のアクセス >>> t.test1 1 # __dict__を介してのアクセス >>> t.__dict__['test1'] 1 # アトリビュートの追加も可能 >>> t.__dict__['test2'] = 2 >>> t.test2 2__dict__ にはクラスの全アトリビュートが dict 形式で格納されています。dict のインターフェースでアトリビュートへアクセスできるというのは、かなり便利な機能です。特に、アトリビュートの追加・削除が多いクラスでは、getattr() / setattr() を使うよりも記述が簡単になることが多いです。
しかし! この __dict__ は原則として使うべきではない機能です。理由は2つあります。
- __slots__ を定義しているクラスでは使えない
- __dict__ は内部情報に直接アクセスし、クラスのインターフェースを無視する
1.の __slots__ についてはこちらを参照下さい。
外部定義のクラスを使う場合には、たとえ今は __slots__ が定義されていなくても、次のバージョンアップで __slots__ が定義されるかもしれません。このリスクを考えると、外部定義のクラスに対しては __dict__ を使えなくなるはずです。
2.についてですが、例えば以下のようなクラスがあったとします。
class FixInt(object): # 固定のint値を保持 def __init__(self, fixed): self.__fixed = int(fixed) # getter @property def fixed(self): return self.__fixedこの FixIntクラスは、Read Only 属性のアトリビュート __fixed を持っています。このクラスの fixed へのアクセスについて、getattr() と __dict__ を比較します。
>>> f = FixInt(10) # getattr()でfixedにアクセス >>> getattr(f, 'fixed') 10 # __dict__でfixedにアクセス >>> f.__dict__['fixed'] Traceback (most recent call last): File "<stdin>", line 1, ingetattr() では 'fixed' にアクセスできたのに、__dict__ では 'fixed' にアクセスできませんでした。KeyError: 'fixed'
これは、getattr() は定義されているクラスのインターフェース(即ち、クラス設計者の意図)に従っているのに対し、__dict__ は内部情報に直接アクセスしようとしている、ということを意味します。当然、getattr() の方が望ましいアクセス方法です。
そんな __dict__にも、一点大きな長所があります。それは、getattr() / setattr() よりも動作速度が速いということです。
よって、満足のいく動作速度が得られない場合には、__dict__ を使うのはありだと思います。
しかし、これは最終手段であり、上で述べた使うべきでない2つの理由を頭に入れた上で、それでも使いたいという場合にのみ使うべきと思います。
0 件のコメント:
コメントを投稿