Hatena::ブログ(Diary)

北海道苫小牧市出身のPGが書くブログ RSSフィード Twitter

Fork me on GitHub

2009-06-30(火)

間違いやすいPythonのクラス変数とインスタンス変数

すごい昔のエントリですが、コメントできなくなってたんでTBで。

やっぱり、インスタンス変数(クラス変数も!)は先頭で宣言しないと気持ち悪い。だから、初期化の必要がなくても以下のように書いておく。

class Hoge:
  #名前
  name = None

  def __init__(self, name):
    self.name = name

Pythonのインスタンス変数

気持ちはとてもとてもよくわかるんですけど、class宣言の中に変数を置いてもそれはあくまでもclassオブジェクトに紐づく値となってしまい、インスタンスの変数とはなりません。もちろん、わかってて使うなら大丈夫ですけど。

>>> class Hoge(object):
...     foo = 10
>>> hoge1 = Hoge()
>>> Hoge.__dict__.items()
[('__dict__', <attribute '__dict__' of 'Hoge' objects>), ('__module__', '__main__'), ('foo', 10), ('__weakref__', <attribute '__weakref__' of 'Hoge' objects>), ('__doc__', None)]
# ↑ここにfooはあるけど・・・
>>> hoge1.__dict__
{}
# ↑hoge1はfooを持ってない


ドキュメントにも言及されてて、デフォルト値として使ってもいいけどミュータブルな値を使うと予期しない結果になると書かれてます。

Variables defined in the class definition are class variables; they are shared by all instances.

To create instance variables, they can be set in a method with self.name = value.

...中略...

Class variables can be used as defaults for instance variables, but using mutable values there can lead to unexpected results.

7.7. Class definitions

ya_kenya_ken 2009/06/30 12:54 ご指摘ありがとうございます。
コメントはスパムが多くてイラついたので、やめてしまいました。

なるほど、確かにクラス変数になってしまうんですね。
微妙な挙動ですね。確かにダメじゃないけど、言語仕様を知っている人から見ると違和感があるのかもしれませんね。一般的にどうするもんなんでしょう?

hiratarahiratara 2009/06/30 15:01 自分もpython専門ではないのですが、DjangoやSQLAlchemyのソースを見る限りでは __init__ 内で self.field = VALUE の形で全ての属性を宣言しておくのが主流なのではないかと思います。

ousttrueousttrue 2009/07/11 17:21 class Hoge(object):
__slots__=['name']
def __init__(self, name):
self.name=name
#self.not_in_slots=0 # error

とするのがよいのでは。
新スタイルクラス(new style class)というものです。
__slots__にあるものしか使えなくなります。

hiratarahiratara 2009/07/12 16:14 __slots__ は残念ながら推奨されていません(http://pytut.infogami.com/node18.html では 「is best reserved for rare cases」と言う表現。)。

ちなみに、__slots__ を使わなくても、 objectを継承した時点で new style class となります。

hiratarahiratara 2009/07/12 16:18 あ、ousttrueさんはCG系をなさっている方でしたか。であれば、パフォーマンス面で __slots__ 推奨(むしろ必須?)ですね、納得しました!

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証