Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/285.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 类作用域中的闭包_Python_Class_Scope - Fatal编程技术网

Python 类作用域中的闭包

Python 类作用域中的闭包,python,class,scope,Python,Class,Scope,根据我的理解,函数和类作用域的行为基本相同: >>> def x(): ... a = 123 ... print (locals()) ... >>> x() {'a': 123} >>> class x(): ... a = 123 ... print (locals()) ... {'a': 123, '__module__': '__main__'} 然而,当我定义一个闭包时,行为是不同的。函

根据我的理解,函数和类作用域的行为基本相同:

>>> 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
>>类x():
...     a=123
...     t=lambda self:a
... 
>>>x().t()
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“”,第3行,在
NameError:未定义全局名称“a”
有人能解释这种差异吗?

类范围是一个临时范围,它只在执行类定义主体时存在。生成的
dict
用于创建类名称空间,即类的
\uuu dict\uuu

就类中定义的函数而言,下一个作用域“up”是
类的作用域
定义本身

以下工作很好:

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

类作用域中的名称不可访问。名称在中解析 最里面的封闭函数作用域。如果一个类定义 在嵌套作用域链中发生时,解析过程将跳过 类定义

以及在:

然后,使用新创建的本地名称空间和原始全局名称空间,在新的执行框架中执行该类的套件(请参见第节)。(通常,套件只包含函数定义。)当类的套件完成执行时,其执行帧被丢弃,但其本地名称空间被保存。然后使用基类的继承列表和属性字典保存的本地名称空间创建类对象


重点矿山;执行帧是临时作用域。

在执行类主体后,作用域中的任何内容都将填充到类
\uuuu dict\uuuu
中,然后删除。所以当运行
t
@katrielalex:确切地说,这就是我用来创建类命名空间的
的意思。
@katrielalex:注意,
a
被绑定只意味着一个作用域在它的
locals()
字典中
globals()
只是模块
locals()
,真的。我不知道你所说的“临时”作用域是什么意思(有“永久”作用域吗?),但目前
t=lambda:a
正在执行中,
a
确实存在。所以闭包知道这个绑定,但后来不知何故丢失了它。@CS:我没有说这是技术原因,我只是说类作用域应该被视为临时的。当然,您可以给包含的函数对象闭包来访问类属性,但这会导致很多范围混淆。类命名空间只能通过显式引用访问(通过
类型(self).class\u attr
ClassName.class\u attr
或通过
self.class\u attr
,前提是实例上没有屏蔽名称)。