他の答えはほとんど正しいですが、1つの重要なことを見逃しています。
このようなクラスを定義する場合:
class Foo(object):
a = 5
およびインスタンス:
myinstance = Foo()
次にFoo.a
、とmyinstance.a
はまったく同じ変数です。一方を変更するともう一方も変更され、のインスタンスを複数作成するとFoo
、それぞれの.a
プロパティは同じ変数になります。これは、Pythonが属性アクセスを解決する方法によるものです。最初にオブジェクトのdictを調べ、そこで見つからない場合は、クラスのdictを調べます。
これは、変数の共有の性質を考えると、割り当てが期待どおりに機能しない理由を説明するのにも役立ちます。
>>> bar = Foo()
>>> baz = Foo()
>>> Foo.a = 6
>>> bar.a = 7
>>> bar.a
7
>>> baz.a
6
ここで起こったことは、に割り当てたときに、要求したときFoo.a
にすべてのインスタンスがFoo
通常解決する変数を変更したことですinstance.a
。しかし、に割り当てたときbar.a
、Pythonはそのインスタンスに、という新しい変数を作成しましたa
。これにより、クラス変数がマスクされます。これ以降、その特定のインスタンスには常に独自のローカル値が表示されます。
クラスの各インスタンスに個別の変数を5に初期化させたい場合、通常の方法は次のようになります。
class Foo(object);
def __init__(self):
self.a = 5
つまりa
、新しいインスタンスの変数を5に設定するコンストラクターを使用してクラスを定義します。
最後に、App Engineが行っているのは、記述子と呼ばれるまったく異なる種類の黒魔術です。つまり、Pythonではオブジェクトが特別なメソッド__get__
と__set__
メソッドを定義できます。これらの特別なメソッドを定義するクラスのインスタンスがクラスにアタッチされ、そのクラスのインスタンスを作成すると、属性にアクセスしようとすると、インスタンスまたはクラス変数を設定または返す代わりに、特別なメソッド__get__
と__set__
メソッドが呼び出されます。 。記述子のより包括的な紹介はここにありますが、ここに簡単なデモがあります:
class MultiplyDescriptor(object):
def __init__(self, multiplicand, initial=0):
self.multiplicand = multiplicand
self.value = initial
def __get__(self, obj, objtype):
if obj is None:
return self
return self.multiplicand * self.value
def __set__(self, obj, value):
self.value = value
今、あなたはこのようなことをすることができます:
class Foo(object):
a = MultiplyDescriptor(2)
bar = Foo()
bar.a = 10
print bar.a # Prints 20!
記述子は、驚くべき量のPython言語の背後にある秘密のソースです。たとえば、property
メソッド、静的メソッド、クラスメソッド、およびその他の多くのものと同様に、記述子を使用して実装されます。