5

次のように、Pythonモジュールにオブジェクトの階層があります。

class BaseObject(object):
    initialized = False

    def __init__(self):
        self._initialize()

    @classmethod
    def _initialize(cls):
        print "cls.initialized = "+str(cls.initialized)
        if not cls.initialized:
            cls.x = 1
            cls.initialized = True

class ObjectOne(BaseObject):
    @classmethod
    def double_x(cls):
        cls.x = cls.x * 2
        print cls.x

class ObjectTwo(BaseObject):
    @classmethod
    def triple_x(cls):
        cls.x = cls.x * 3
        print cls.x

if __name__ == '__main__':
    obj_1 = ObjectOne()
    obj_1.double_x()
    obj_2 = ObjectTwo()
    obj_2.triple_x()

このモジュールを実行すると、出力は次のようになります。

cls.initialized = False
2
cls.initialized = True
6

しかし、私が得るものは次のとおりです。

cls.initialized = False
2
cls.initialized = False
3

何がわからないの?

4

2 に答える 2

7

クラス変数を設定するには、完全なクラス名を使用する必要があります。clsindouble_xtripple_xはサブクラス (それぞれObjectOneと) を参照し、これらのサブクラスに属性を設定すると、クラス変数は変更されず、新しい変数ObjectTwoが格納されます。基本クラスの変数は、直接アクセスすることによってのみ変更できます。BaseObject.x

コードを使用すると、次のようになります。

>>> obj_1 = ObjectOne()
cls.initialized = False
>>> obj_1.double_x()
2
>>> obj_2 = ObjectTwo()
cls.initialized = False
>>> obj_2.triple_x()
3
>>> BaseObject.x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: type object 'BaseObject' has no attribute 'x'
>>> BaseObject.initialized, ObjectOne.initialized, ObjectOne.x, ObjectTwo.initialized, ObjectTwo.x
(False, True, 2, True, 3)

何が起こったかというと、作成したインスタンスに応じて in_initialize()がor に設定され、各サブクラスは変数clsandの独自のコピーを取得ました。ObjectOneObjectTwoinitializedx

(サブクラスではなく、BaseObject._initialize()確実に初期化するため)を使用すると、次のようになります。BaseObject

>>> obj_1 = ObjectOne()
cls.initialized = False
>>> obj_1.double_x()
2
>>> obj_2 = ObjectTwo()
cls.initialized = True
>>> obj_2.triple_x()
3
>>> BaseObject.x, ObjectOne.x, ObjectTwo.x
(1, 2, 3)
>>> BaseObject.initialized
True
>>> 'x' in ObjectOne.__dict__
True
>>> 'initialized' in ObjectOne.__dict__
False
>>> 'initialized' in ObjectTwo.__dict__
False

そのため、設定するターゲットと の初期値として_initialize()使用されますが、独自のサブクラスを使用して の新しい値を設定し、を介してその値を共有していません。BaseObjectinitializedxdouble_xtriple_xxBaseObject

特定の基本クラスにクラス変数を設定するために必要な唯一のオプションは、すべてのクラス メソッドで直接参照することです。

class BaseObject(object):
    initialized = False
    def __init__(self):
        BaseObject._initialize()

    @classmethod
    def _initialize(cls):
        print "cls.initialized = "+str(cls.initialized)
        if not cls.initialized:
            cls.x = 1
            cls.initialized = True
class ObjectOne(BaseObject):
    @classmethod
    def double_x(cls):
        BaseObject.x = BaseObject.x * 2
        print cls.x

class ObjectTwo(BaseObject):
    @classmethod
    def triple_x(cls):
        BaseObject.x = BaseObject.x * 3
        print cls.x

これは次のようになります:

>>> obj_1 = ObjectOne()
cls.initialized = False
>>> obj_1.double_x()
2
>>> obj_2 = ObjectTwo()
cls.initialized = True
>>> obj_2.triple_x()
6

それがサブクラスであり、サブクラスではないBaseObject._initialize()ことを確認するために呼び出したことに注意してください。次に、およびメソッドを設定するときに、 を直接参照して、変数が基本クラスに直接設定されるようにします。上記の例の値を読み取るときは、ローカルに設定されていない場合、クラス MRO を使用して基本クラスを検索します。clsBasObject xdouble_xtriple_xBaseObjectxclsx

于 2012-12-30T17:44:28.423 に答える