2016-03-26 20 views
3
class MyClass(object): 
    next_number = 0 

    def __init__(self): 
     self.number = self.next_number 
     MyClass.next_number += 1 

class MyClassA(MyClass): 
    pass 

書き込み以来、6行目のクラス変数を更新するとき、私は打ちにクラス名を強制しています表示されます:すべての派生クラスで新しいクラス変数でPythonのクラス変数の更新

self.__class__.next_number += 1 

結果を。クラス名をハードコーディングする方法はありますか?

はまた、5行目に私の代わりに書く必要があります:

self.number = self.__class__.next_number 

をnext_numberがクラス変数であることが明らかにします。

+0

なぜこれをやっていますか?代わりに 'self .__ class__'を比較できますか?代わりに 'Enum'を使用できますか? –

+0

あなたはdjangoがそのモデル/フィールドにあるように__new__を使ってそれを扱うことができます –

+0

私はあなたが得ているdownvotesを理解していません。あなたの質問は合法です。私からupvoteを持ってください。 – timgeb

答えて

4

クラス変数を再バインドするという問題を回避する1つの方法は、不変の整数値をその内部の数値を含む可変オブジェクトに置き換えることです。次に、オブジェクトを所定の場所に変更することができます。作品

class MyClass(object): 
    next_number = [0] 

    def __init__(self): 
     self.number = self.next_number[0] 
     self.next_number[0] += 1 

が、それは非常にエレガントではありません。

本のシンプルなバージョンは、1要素のリストで番号を置くことです。

整数クラス変数をitertools.count関数で返されたイテレータに置き換えると、nextを呼び出すたびに連続してより高い整数が返されます(永遠に無限イテレータです)。高レベルでは、これはリストコードのように機能しますが、nextはイテレータを変更しますが、正確な詳細はイテレータプロトコル(およびitertools.countの実装)の背後に隠されています。あなたはitertoolsは正確に正しい順序を提供しなかったようなもう少し複雑なものを、必要に応じて

class MyClass(object): 
    number_iter = itertools.count() 

    def __init__(self): 
     self.number = next(self.number_iter) # this mutates number_iter by consuming a value 

、独自のジェネレータ関数を記述し、クラス変数にその戻り値を割り当てることができます。例えば、ここではフィボナッチ数列のための発電機です:

def fib(): 
    a, b = 0, 1 
    while True: 
     a, b = b, a+b 
     yield a 
2

self.__class__.next_numberは、__init__を呼び出すオブジェクトをインスタンス化する各クラスの変数を作成することが間違いありません。

2つの選択肢があります。クラス名をハードコードするか、派生クラスからsuper().__init__を呼び出しないでください。 私は前者に行くでしょう。

私の意見では、ここでクラス名をハードコードすることについて不必要に心配しています。結局のところ、あなたがclass MyClass(object):をやると、このモジュールのクラス名はすでに "ハードコーディング"されています。

2番目のコメントについては、考慮する必要があります。私は行くだろう:self.__class__.next_number += 1。これは読者にとってより明白なだけでなく、後でself.next_numberを間違って定義しておけば、適切な振る舞いを保つことが保証されます。

0
class MyClass(object): 
    next_number = 0 

    def __init__(self): 
     self.number = self.__class__.next_number 
     self.__class__.next_number += 1 

class MyClassA(MyClass): 
    pass 

a = MyClassA() 
print a.next_number 
b = MyClassA() 
print a.next_number, b.next_number 
print a.number, b.number 

出力は

1 
    2, 2 
    0, 1 

が、これは何が必要ですか?

+0

このアプローチの問題は、next_numberがMyClassAクラスにアタッチされるようになったことです。別の派生クラスMyClassB(MyClass)を追加すると、next_number属性が完全に別のシーケンスに従うことがわかります。新しいMyClassまたはサブクラスに対してnext_numberをインクリメントする必要があります。 – user3235250

+0

私はそれをキャッチしなかったが、@Blckknghtは持っているようだ –

0
class Test(object): 
    next_number = 0 

    def __new__(cls, *args, **kwargs): 
     cls.next_number += 1 
     instance = super(Test, cls).__new__(cls) 
     instance.next_number = cls.next_number 
     return instance 

各テスト()呼び出しメソッド呼び出しクラスのコンストラクタの戻りオブジェクトのインスタンスとして、我々は、フィールドnext_numberを追加する新しい方法は(と増加クラス呼び出しのたびに)、クラスメソッドで利用できます。

関連する問題