5

私の理解では、関数とクラスのスコープはほとんど同じように動作します。

>>> def x():
...     a = 123
...     print (locals())
... 
>>> x()
{'a': 123}


>>> class x():
...     a = 123
...     print (locals())
... 
{'a': 123, '__module__': '__main__'}

ただし、クロージャーを定義すると、動作が異なります。関数は、予想どおり、単純にローカル バインディングを返します。

>>> def x():
...     a = 123
...     t = lambda: a
...     return t
... 
>>> x()()
123

一方、クラスではバインディングが失われているように見えます:

>>> class x():
...     a = 123
...     t = lambda self: a
... 
>>> x().t()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in <lambda>
NameError: global name 'a' is not defined

誰も矛盾を説明できますか?

4

1 に答える 1

4

クラス スコープは一時的なスコープであり、クラス定義の本体の実行中にのみ存在します。結果dictは、クラスの名前空間であるクラスの作成に使用されます__dict__

クラスで定義された関数に関する限り、次のスコープ 'up' はclass定義自体のスコープです。

以下はうまくいきます:

>>> def foo():
...     spam = 'eggs'
...     class Bar(object):
...         def baz(self): return spam
...     return Bar()
... 
>>> foo().baz()
'eggs'

これはpep 227に記載されています:

クラス スコープ内の名前にはアクセスできません。名前は、最も内側の関数スコープで解決されます。クラス定義がネストされたスコープのチェーンで発生する場合、解決プロセスはクラス定義をスキップします。

およびclass複合ステートメントのドキュメントで:

次に、クラスのスイートは、新しく作成されたローカル名前空間と元のグローバル名前空間を使用して、新しい実行フレーム (セクション命名とバインドを参照) で実行されます。(通常、スイートには関数定義のみが含まれます。) クラスのスイートの実行が終了すると、その実行フレームは破棄されますが、そのローカル名前空間は保存されます。[4]次に、基本クラスの継承リストと属性ディクショナリの保存されたローカル名前空間を使用して、クラス オブジェクトが作成されます。

鉱山を強調します。実行フレームは一時的なスコープです。

于 2012-11-14T15:37:30.270 に答える