web-dev-qa-db-ja.com

pythonクラス属性

pythonのクラス属性について質問があります。

class base :
    def __init__ (self):
        pass
    derived_val = 1

t1 = base()
t2 = base ()

t2.derived_val +=1
t2.__class__.derived_val +=2
print t2.derived_val             # its value is 2
print t2.__class__.derived_val   # its value is 3

結果は異なります。また、id()関数を使用して、t2。派生型valとt2を検索します。クラス。派生型valのメモリアドレスが異なります。私の問題は、derived_valがクラス属性であるということです。上記の例でなぜ違うのですか?クラスのインスタンスがクラス属性の横にある独自のderivated_valをコピーするためですか?

20
chnet

クラス属性とインスタンス属性があります。あなたが言う時

class base :
    derived_val = 1

クラス属性を定義しています。 derived_valbase.__dict__のキーになります。

t2=base()
print(base.__dict__)
# {'derived_val': 1, '__module__': '__main__', '__doc__': None}
print(t2.__dict__)
# {}

t2.derived_val Pythonはt2.__dict__で 'derivated_val'を見つけようとします。そこにないので、'derived_val'キーがあるかどうかを調べます。 t2の基本クラスのいずれか。

print(t2.derived_val)
print(t2.__dict__)
# 1
# {}

ただし、t2.derived_valに値を割り当てると、インスタンス属性がt2に追加されます。 derived_valキーがt2.__dict__に追加されます。

t2.derived_val = t2.derived_val+1
print(t2.derived_val)
print(t2.__dict__)
# 2
# {'derived_val': 2}

この時点で、2つのderived_val属性がありますが、簡単にアクセスできるのはインスタンス属性のみであることに注意してください。クラス属性は、base.derived_valを参照するか、クラスdict base.__dict__に直接アクセスすることによってのみアクセス可能になります。

40
unutbu

それをチェックしてください ここここ

__class__属性は、オブジェクトが属するクラスです。したがって、あなたの例では、状況は静的変数に似ています。 t2.__class__.derived_valは、t2に属する変数ではなく、クラスに属する変数を参照しています。

2
jakecar

これを実証する別の方法(おそらくより簡潔な方法):

class A():
   a1 = []
x = A()
y = A()
x.a1.append("test")
x.a1, y.a1
(['test'], ['test'])

class B():
   b1 = None
   def __init__(self):
      self.b1 = list()
r = B()
s = B()
r.b1.append("test")
r.b1, s.b1
(["test"], [])
1
Greppur