41

親のクラス名を具体的に示さないと、サブクラスのクラス変数が親のクラス変数にアクセスできないことを知って驚きました。

>>> class A(object):
...     x = 0
... 
>>> class B(A):
...     y = x+1
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in B
NameError: name 'x' is not defined
>>> class B(A):
...     y = A.x + 1
... 
>>> B.x
0
>>> B.y
1

By を定義する際に、x だけでなく Ax を参照する必要があるのはなぜですか? これは、インスタンス変数からの私の直感に反するものであり、B が定義された後に Bx を参照できるためです。

4

2 に答える 2

51

ベアネームに対する Python のスコープ ルールは非常に単純明快です。最初にローカル名前空間、次に現在の名前がネストされている外部関数 (存在する場合)、次にグローバル、最後に組み込み関数です。ベアネームが検索されたときに起こるのはこれだけであり、複雑な規則を記憶したり適用したりする必要はありません (さらに複雑な規則を強制するために Python コンパイラを使用する必要もありません)。

別のルックアップが必要な場合はいつでも、そのままの名前はなく修飾名を使用します。属性を要求できるオブジェクトにルックアップを常に委任でき、それらのオブジェクトは必要なルックアップ ルールを実装できるため、修飾名は非常に強力です。特に、クラス内のインスタンス メソッドでは、オブジェクトに属性名を検索するように依頼する方法があります。その検索では、継承の概念の実装 (および多重継承、メソッド解決) を含むクラスに委任できます。注文など)。self.xself'x'

クラスの本体(クラスで定義されたメソッドの本体とは対照的に) は、クラス オブジェクトが作成される前、またはその名前がバインドされる前 (特に、ベースのいずれかが次のように定義される前) に、classステートメントの一部として実行されます。とにかく、この最新の詳細はベアネームを参照するときは決して重要ではありません!-)。

したがって、あなたの例では、クラスではB、ベアネームxが普遍的なルールで検索されます-ローカルにバインドされた名前ですか? いいえの場合、このスコープがネストされている外部関数にバインドされていますか? いいえの場合、それはグローバルまたはビルトインとしてバインドされていますか? 上記のいずれでもない場合、問題のベアネームを使用すると、もちろん名前エラー例外が発生します。

ベアネーム ルックアップ ルールが普遍的に強制するものとは異なるルックアップ シーケンスが必要なため、ベアネームではなく修飾名を使用する必要があることは明らかです。少し考えれば、目的に使用する修飾名の「1つの明白な選択肢」が必要であることが明確に示されますA.x-それは、検索したい場所だからです(ベースはまだどこにも記録されていません)ポイント、結局のところ...通常、クラス本体の実行が完了したtypeに呼び出されると、そのジョブの一部としてベースバインディングを実行するのはメタクラスになります!-)。

一部の人々は、ベアネームのルックアップのための他の「魔法の」ルールに非常に強く執着しているため、Python のこの側面に耐えられません (もともとは、理論家の間で非常によく検討されているあまり知られていない言語である Modula-3 に触発されたものだと思います)。 ' circles;-) --たとえば、普遍的な裸の名前のルールを使用するのではなく、検索する必要があるself.xことを指定する方法を記述しxなければならないため、そのような人々は気が狂います。self

私は、ベアネーム ルックアップ ルールのシンプルさと普遍性が大好きで、他の形式のルックアップが必要なときはいつでも、ベアネームの代わりに修飾名を使用するのが大好きです Python (私は自分自身の不平を言っています。たとえば、global xステートメントは常に私の肌をクロールさせます。ここでは、むしろ「現在実行中のモジュール」の組み込み名であるglobal.x必要があります...私大好きです修飾名!-)、そうですか?-)global

于 2010-09-06T02:28:09.340 に答える
31

Python では、クラスが作成される前に、クラスの本体が独自の名前空間で実行されます (その後、その名前空間のメンバーがクラスのメンバーになります)。したがって、インタプリタが y = x+1 に到達したとき、クラス B はその時点ではまだ存在していないため、親がありません。

詳細については、http://docs.python.org/reference/compound_stmts.html#class-definitionsを参照してください。

于 2010-09-06T02:09:07.450 に答える