2017-08-26 27 views
5

を印刷するには次のコードが必要ですが、012012が表示されます。なぜですか?私はincrへの呼び出しが同じクラスから継承されているので同じ変数にアクセスすることを期待しますが、それらは明らかに異なる変数です。pythonクラスのメソッドと継承

class a(object): 
    var = 0 
    @classmethod 
    def incr(cls): 
     print cls.var 
     cls.var+=1 

class b(a): 
    def func(self): 
     super(b,self).incr() 

class c(a): 
    def func(self): 
     super(c,self).incr() 


t = a() 
t1 = b() 
t2 = c() 
t1.func() 
t1.func() 
t1.func() 
t2.func() 
t2.func() 
t2.func() 
+1

それは予期しない動作に影響を与えていないあなたあなたのサブクラスのいずれかで 'super'を使う必要はないことに注意したいと思います。代わりに 'self.incr()'を呼び出すことができます。別のバージョンの関数をスキップするときには(通常は現在のクラスでオーバーライドされているため) 'super'を使うだけです。 – Blckknght

+0

Python 3.6に切り替える必要があります。 https://pythonclock.org/ – wwii

答えて

5
彼らは同じクラスから継承され

が、スーパー経由classmethodに渡さclsは、メソッドが呼び出された現在のクラスです。 superはメソッドの基本クラスバージョンにアクセスしますが、呼び出しのためのclsスーパー呼び出しが行われたクラスです。

これはやっ間微妙違いの一つです:あなたは両方のケースであなたのincr方法で現在clsを印刷することでこれを確認することができます

def func(self): 
    a.incr() 

def func(self): 
    super(c, self).incr() # same as a.__dict__['incr'].__get__(self, type(self))() 

とを

superのすべてが親クラスにバインドされたメソッド呼び出しを行うとは決して決して考えるべきではありません。それはもっとたくさんあります。

最初の拡張割り当て+=を実行すると、varという初期値が(この時点ではサブクラスのdictには存在しないため)基本クラスから読み込まれることに注意してください。ただし、更新された値はサブクラスに書き込まれます。 2番目のサブクラスからsuperを呼び出すと、varの値をaから読み取るのと同じ動作が繰り返されます。

+0

'cls.var + = 1'行が' cls'が違うときに異常に動作するという事実を明示したいかもしれません。最初に実行されたとき、 'var'の継承された値を読み込みます(この例では' 0'ですが、 't.incr()'が呼び出されていれば他の値かもしれません) *を基本クラスではなく特定の 'cls'に書き出します。後続のすべての呼び出しは、基本クラスを見ずにサブクラスの値を使用します。 – Blckknght

+0

@Blckknght私はそれについて短いノートを追加します。 –

0

クラスbとクラスcはそれぞれクラスaから継承し、varは毎回0に設定されます。

一つの方法は、クラスbは、クラスcはそうのようなクラスbから継承することができないように、クラスavarの同じ値を取得するには、クラスcを持っている:

class a(object): 
    var = 0 
    @classmethod 
    def incr(cls): 
     print cls.var 
     cls.var+=1 

class b(a): 
    def func(self): 
     super(b,self).incr() 

class c(b): 
    def func(self): 
     super(c,self).incr() 


t = a() 
t1 = b() 
t2 = c() 
t1.func() 
t1.func() 
t1.func() 
t2.func() 
t2.func() 
t2.func()` 
+1

これは 't2.func()'への最初の呼び出しがすべての 't1.func()'呼び出しの後に来る場合にのみ期待される結果を与えます。あなたがそれらを混ぜれば、あなたが期待する結果を得ることはできません。そして、 "var"が毎回0に設定されていると言っても間違いがあります。ゼロのときは 'var'は1つだけです(' a'のもの)。最初の 'incr'呼び出しの後で、クラスが作成されたときに値' 1'を持つ新しい 'var'属性が得られます。 – Blckknght

関連する問題