22

以下は奇妙に思えます。基本的に、somedata属性はから継承したすべてのクラス間で共有されているようですthe_base_class

class the_base_class:
    somedata = {}
    somedata['was_false_in_base'] = False


class subclassthing(the_base_class):
    def __init__(self):
            print self.somedata


first = subclassthing()
{'was_false_in_base': False}
first.somedata['was_false_in_base'] = True
second = subclassthing()
{'was_false_in_base': True}
>>> del first
>>> del second
>>> third = subclassthing()
{'was_false_in_base': True}

関数で定義self.somedataする__init__ことは明らかにこれを回避する正しい方法です(したがって、各クラスには独自のsomedatadictがあります)-しかし、そのような動作が望ましいのはいつですか?

4

3 に答える 3

24

クラス定義somedata時に作成されるため、クラスのすべてのインスタンスとそのサブクラスの間で共有されます。台詞

somedata = {}
somedata['was_false_in_base'] = False

クラスが定義されたとき、つまりインタプリタがclassステートメントに遭遇したときに実行されます-インスタンスが作成されたときではありません(Javaの静的初期化ブロックを考えてください)。クラスインスタンスに属性が存在しない場合は、クラスオブジェクトで属性がチェックされます。

クラス定義時に、次のような任意のコードを実行できます。

 import sys
 class Test(object):
     if sys.platform == "linux2":
         def hello(self):
              print "Hello Linux"
     else:
         def hello(self):
              print "Hello ~Linux"

Linuxシステムでは、Test().hello()が印刷Hello Linuxされ、他のすべてのシステムでは、他の文字列が印刷されます。

対照的に、のオブジェクトはインスタンス化__init__時に作成され、インスタンスにのみ属します(に割り当てられている場合)。self

class Test(object):
    def __init__(self):
        self.inst_var = [1, 2, 3]

多くの場合、インスタンスではなくクラスオブジェクトで定義されたオブジェクトが役立ちます。たとえば、クラスのインスタンスをキャッシュして、同じメンバー値を持つインスタンスを共有できるようにすることができます(それらが不変であると想定されている場合)。

class SomeClass(object):
    __instances__ = {}

    def __new__(cls, v1, v2, v3):
        try:
            return cls.__insts__[(v1, v2, v3)]
        except KeyError:
            return cls.__insts__.setdefault(
               (v1, v2, v3), 
               object.__new__(cls, v1, v2, v3))

ほとんどの場合、メタクラスまたはジェネリックファクトリメソッドと組み合わせてクラス本体のデータを使用します。

于 2008-10-15T22:27:18.713 に答える
12

表示されている動作の一部は、などの単純なデータ型ではなく、 でsomedataあることに注意してください。dictbool

たとえば、動作が異なる次の例を参照してください (ただし、非常に似ています)。

class the_base_class:
    somedata = False

class subclassthing(the_base_class):
    def __init__(self):
        print self.somedata


>>> first = subclassthing()
False
>>> first.somedata = True
>>> print first.somedata
True
>>> second = subclassthing()
False
>>> print first.somedata
True
>>> del first
>>> del second
>>> third = subclassthing()
False

この例が質問で与えられたものと異なる動作をする理由は、最初の例では(および他のサブクラス インスタンスによっても)参照される dict オブジェクトが変更されているのに対し、ここでfirst.somedataは新しい値 ( object ) が与えられているためです。Truefirst.somedata

詳細については、この回答に対する Torsten Marek のコメントを参照してください。

于 2008-10-15T22:40:10.013 に答える
3

(動作を予測できるように)これを理解する最も簡単な方法は、あなたsomedataがそのように定義した場合、クラスのインスタンスではなく、クラスの属性であることを理解することだと思います。

somedataあなたの例では、その名前に割り当てていませんでしたが、それを使用してdictを検索し、アイテム(キー、値)を割り当てたため、実際には常に1つしかありません。これは、Python インタープリターの動作の結果であり、最初は混乱する可能性がある落とし穴です。

于 2008-10-15T22:55:23.133 に答える