0

Python でクラス変数が処理される方法は、私には意味がありません。クラス変数のスコープはその型に依存しているようです! プリミティブ型はインスタンス変数のように扱われ、複合型はクラス変数のように扱われます。

>>> class A(object):
...   my_class_primitive = True
...   my_class_object = ['foo']
... 
>>> a = A()
>>> a.my_class_primitive, a.my_class_object
(True, ['foo'])
>>> b = A()
>>> b.my_class_primitive, b.my_class_object
(True, ['foo'])
>>> a.my_class_object.append('bar')
>>> b.my_class_primitive, b.my_class_object
(True, ['foo', 'bar'])
>>> a.my_class_primitive = False
>>> b.my_class_primitive, b.my_class_object
(True, ['foo', 'bar'])
>>> a.my_class_primitive, a.my_class_object
(False, ['foo', 'bar'])

誰かが次のことを説明してもらえますか:

  1. なぜこの機能が存在するのですか? その背後にあるロジックは何ですか?
  2. プリミティブ型 (bool など) をクラス変数として使用したい場合、どうすればよいですか?
4

5 に答える 5

1

あなたが行うべき適切な比較はこれです:

>>> class A(object):
    my_class_primitive = True
    my_class_object = ['foo']


>>> a = A()
>>> b = A()
>>> a.my_class_primitive = False
>>> a.my_class_object = ['bar']
>>> b.my_class_primitive, b.my_class_object
(True, ['foo'])

これは、あなたが見ていると思っていたものではありません。「奇妙な」動作は、可変性の概念によって引き起こされます。つまり、my_class_object別のオブジェクトを に割り当てている間に、プロパティに割り当てられたオブジェクトを変更していますmy_class_primitive。最初のケースでは (これは1 つのオブジェクトであるため) すべてのインスタンスで機能しますが、2 番目のケースでは単一のインスタンス (プロパティを変更する) で機能します。

その混乱の中にいるのはあなただけではありません。可変性がコードに与える影響の別の例を確認するには、これを確認してください: "Least Astonishment" and the Mutable Default Argument

于 2013-06-12T20:34:23.370 に答える
1

この機能は、Python のクラス定義のキャッシュ形式として存在します。

クラス定義自体で定義されたstatic属性は、クラスの属性と見なされます。たとえば、変更しないでください。

静的属性の変更に関するベストプラクティスに従っていると仮定して、決定が下されたと確信しています;)

于 2013-06-12T20:31:00.853 に答える
1
>>> class A(object):
...   my_class_primitive = True
...   my_class_object = ['foo']

クラス属性は次の場所に格納されA.__dict__ます。

>>> A.__dict__
>>> <dictproxy {'__dict__': <attribute '__dict__' of 'A' objects>,
 '__doc__': None,
 '__module__': '__main__',
 '__weakref__': <attribute '__weakref__' of 'A' objects>,
 'my_class_object': ['foo'],
 'my_class_primitive': True}>

>>> a = A()
>>> a.my_class_primitive, a.my_class_object
(True, ['foo'])
>>> b = A()
>>> b.my_class_primitive, b.my_class_object
(True, ['foo'])

このステートメントはリストをa.my_class_object.append('bar') 変更A.my_class_objectします。既存のリストを取得し、そのメソッドa.my_class_objectを呼び出します。append

>>> a.my_class_object.append('bar')

影響b.my_class_objectも受けます:

>>> b.my_class_primitive, b.my_class_object
(True, ['foo', 'bar'])

割り当てa.my_class_primitive = False により、新しいインスタンス アトリビュートが に追加されaます。キーと値のペアを次の場所に配置しますa.__dict__

>>> a.my_class_primitive = False

>>> a.__dict__
>>> {'my_class_primitive': False}

影響bを受けません:

>>> b.my_class_primitive, b.my_class_object
(True, ['foo', 'bar'])

Python の属性ルックアップ ルールにより、 で見つかったキーの値ではなく、 でa.my_class_primitive見つかったキーの値が返されます。a.__dict__A.__dict__

>>> a.my_class_primitive, a.my_class_object
(False, ['foo', 'bar'])
于 2013-06-12T20:34:45.520 に答える