1

Pythonのインスタンスで使用されるクラス変数を通常宣言する方法は、次のとおりです。

class MyClass(object):
  def __init__(self):
    self.a_member = 0

my_object = MyClass()
my_object.a_member    # evaluates to 0

ただし、以下も機能します。それは悪い習慣ですか?もしそうなら、なぜですか?

class MyClass(object):
  a_member = 0

my_object = MyClass()
my_object.a_member    # also evaluates to 0

2番目の方法はZope全体で使用されていますが、他の場所では見たことがありません。何故ですか?

編集:sr2222の回答への応答として。私は、この2つが本質的に異なることを理解しています。ただし、クラスがオブジェクトのインスタンス化にのみ使用される場合、2つは同じように機能します。では、クラス変数をインスタンス変数として使用するのは悪いことですか?そんな感じですが、理由は説明できません。

4

4 に答える 4

7

問題は、これがクラス自体の属性なのか、特定のオブジェクトの属性なのかということです。クラス全体に特定の属性がある場合(おそらくマイナーな例外を除いて)、必ず、クラスに属性を割り当ててください。一部の奇妙なオブジェクトまたはサブクラスがこの属性で異なる場合、必要に応じてオーバーライドできます。また、これは、すべてのオブジェクトに本質的に一定の属性を割り当てるよりもメモリ効率が高くなります。クラスののみが__dict__その属性の単一のエントリを持ち、__dict__各オブジェクトのは(少なくともその特定の属性については)空のままである可​​能性があります。

要するに、両方の例は非常に慣用的なコードですが、マシンレベルと人間のセマンティックレベルの両方で、多少異なる意味を持っています。


これを説明させてください:

>>> class MyClass(object):
...       a_member = 'a'
...
>>> o = MyClass()
>>> p = MyClass()
>>> o.a_member
'a'
>>> p.a_member
'a'
>>> o.a_member = 'b'
>>> p.a_member
'a'

2行目では、「クラス属性」を設定しています。これは文字通り「MyClass」という名前のオブジェクトの属性です。として保存されMyClass.__dict__['a_member'] = 'a'ます。後の行では、オブジェクト属性o.a_memberをに設定しています。これは完全にと同等o.__dict__['a_member'] = 'b'です。これは、の別の辞書とは何の関係もないことがわかりますp.__dict__。pにアクセスするa_memberと、オブジェクトディクショナリに見つからず、クラスディクショナリまで延期されますMyClass.a_member。これが、の属性にo影響を与えないため、の属性を変更してもの属性に影響を与えpない理由ですMyClass

于 2012-08-20T03:12:35.273 に答える
4

1つ目はインスタンス属性で、2つ目はクラス属性です。それらはまったく同じではありません。インスタンス属性はそのタイプの実際に作成されたオブジェクトにアタッチされますが、クラス変数はクラス(タイプ)自体にアタッチされます。

>>> class A(object):
...     cls_attr = 'a'
...     def __init__(self, x):
...         self.ins_attr = x
...
>>> a1 = A(1)
>>> a2 = A(2)
>>> a1.cls_attr
'a'
>>> a2.cls_attr
'a'
>>> a1.ins_attr
1
>>> a2.ins_attr
2
>>> a1.__class__.cls_attr = 'b'
>>> a2.cls_attr
'b'
>>> a1.ins_attr = 3
>>> a2.ins_attr
2
于 2012-08-20T02:59:37.467 に答える
0

オブジェクトの内容を変更したことがない場合でも、この2つを交換することはできません。私の理解では、クラス属性へのアクセスは、インスタンス属性へのアクセスよりも少し遅くなります。これは、インタープリターがクラス属性を検索するために基本的に追加の手順を実行する必要があるためです。

インスタンス属性

「なにa.thing?」

クラス属性

「なにa.thing?ああ、インスタンス属性がないのでthing、クラスをチェックします...」

于 2012-08-20T03:15:23.330 に答える
0

答えがあります!元の投稿へのコメントにある@mjgpy3の参照のおかげです。クラス変数に割り当てられた値がMUTABLEの場合、違いが生じます。その後、2つは一緒に変更されます。新しい値が古い値を置き換えると、メンバーが分割されます

>>> class MyClass(object):
...   my_str = 'a'
...   my_list = []
... 
>>> a1, a2 = MyClass(), MyClass()
>>> a1.my_str # This is the CLASS variable.
'a'
>>> a2.my_str # This is the exact same class variable.
'a'
>>> a1.my_str = 'b' # This is a completely new instance variable. Strings are not mutable.
>>> a2.my_str # This is still the old, unchanged class variable.
'a'
>>> a1.my_list.append('w') # We're changing the mutable class variable, but not reassigning it.
>>> a2.my_list # This is the same old class variable, but with a new value.
['w']

編集:これはbukzorが書いたものとほとんど同じです。彼らはベストアンサーマークを取得します。

于 2012-08-20T03:28:37.533 に答える