ベアネームに対する Python のスコープ ルールは非常に単純明快です。最初にローカル名前空間、次に現在の名前がネストされている外部関数 (存在する場合)、次にグローバル、最後に組み込み関数です。ベアネームが検索されたときに起こるのはこれだけであり、複雑な規則を記憶したり適用したりする必要はありません (さらに複雑な規則を強制するために Python コンパイラを使用する必要もありません)。
別のルックアップが必要な場合はいつでも、そのままの名前ではなく修飾名を使用します。属性を要求できるオブジェクトにルックアップを常に委任でき、それらのオブジェクトは必要なルックアップ ルールを実装できるため、修飾名は非常に強力です。特に、クラス内のインスタンス メソッドでは、オブジェクトに属性名を検索するように依頼する方法があります。その検索では、継承の概念の実装 (および多重継承、メソッド解決) を含むクラスに委任できます。注文など)。self.x
self
'x'
クラスの本体(クラスで定義されたメソッドの本体とは対照的に) は、クラス オブジェクトが作成される前、またはその名前がバインドされる前 (特に、ベースのいずれかが次のように定義される前) に、class
ステートメントの一部として実行されます。とにかく、この最新の詳細はベアネームを参照するときは決して重要ではありません!-)。
したがって、あなたの例では、クラスではB
、ベアネームx
が普遍的なルールで検索されます-ローカルにバインドされた名前ですか? いいえの場合、このスコープがネストされている外部関数にバインドされていますか? いいえの場合、それはグローバルまたはビルトインとしてバインドされていますか? 上記のいずれでもない場合、問題のベアネームを使用すると、もちろん名前エラー例外が発生します。
ベアネーム ルックアップ ルールが普遍的に強制するものとは異なるルックアップ シーケンスが必要なため、ベアネームではなく修飾名を使用する必要があることは明らかです。少し考えれば、目的に使用する修飾名の「1つの明白な選択肢」が必要であることが明確に示されますA.x
-それは、検索したい場所だからです(ベースはまだどこにも記録されていません)ポイント、結局のところ...通常、クラス本体の実行が完了した後type
に呼び出されると、そのジョブの一部としてベースバインディングを実行するのはメタクラスになります!-)。
一部の人々は、ベアネームのルックアップのための他の「魔法の」ルールに非常に強く執着しているため、Python のこの側面に耐えられません (もともとは、理論家の間で非常によく検討されているあまり知られていない言語である Modula-3 に触発されたものだと思います)。 ' circles;-) --たとえば、普遍的な裸の名前のルールを使用するのではなく、検索する必要があるself.x
ことを指定する方法を記述しx
なければならないため、そのような人々は気が狂います。self
私は、ベアネーム ルックアップ ルールのシンプルさと普遍性が大好きで、他の形式のルックアップが必要なときはいつでも、ベアネームの代わりに修飾名を使用するのが大好きです。 Python (私は自分自身の不平を言っています。たとえば、global x
ステートメントは常に私の肌をクロールさせます。ここでは、むしろ「現在実行中のモジュール」の組み込み名であるglobal.x
必要があります...私は大好きです修飾名!-)、そうですか?-)global