Python 在函数中创建类并访问包含函数中定义的函数';s范围
编辑: 请看我在这个问题底部的完整答案 tl;dr answer:Python具有静态嵌套的作用域。静态 方面可以和隐式变量声明交互,产生不明显的结果 (这可能特别令人惊讶,因为这种语言通常是动态的) 我原以为我能很好地处理Python的作用域规则,但这个问题让我彻底陷入困境,我的google fu让我失望(我并不感到惊讶——看看问题标题;) 我将从一些预期效果的示例开始,但请随意跳到示例4以了解有趣的部分 示例1。Python 在函数中创建类并访问包含函数中定义的函数';s范围,python,namespaces,scope,Python,Namespaces,Scope,编辑: 请看我在这个问题底部的完整答案 tl;dr answer:Python具有静态嵌套的作用域。静态 方面可以和隐式变量声明交互,产生不明显的结果 (这可能特别令人惊讶,因为这种语言通常是动态的) 我原以为我能很好地处理Python的作用域规则,但这个问题让我彻底陷入困境,我的google fu让我失望(我并不感到惊讶——看看问题标题;) 我将从一些预期效果的示例开始,但请随意跳到示例4以了解有趣的部分 示例1。 >>> x = 3 >>> class M
>>> x = 3
>>> class MyClass(object):
... x = x
...
>>> MyClass.x
3
>>> def mymethod(self):
... return self.x
...
>>> x = 3
>>> class MyClass(object):
... x = x
... mymethod = mymethod
...
>>> MyClass().mymethod()
3
>>> def myfunc():
... x = 3
... class MyClass(object):
... x = x
... return MyClass
...
>>> myfunc().x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in myfunc
File "<stdin>", line 4, in MyClass
NameError: name 'x' is not defined
>>> def my_defining_func():
... def mymethod(self):
... return self.y
... class MyClass(object):
... mymethod = mymethod
... y = 3
... return MyClass
...
>>> my_defining_func()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in my_defining_func
File "<stdin>", line 5, in MyClass
NameError: name 'mymethod' is not defined
>>> def fun1():
... x = 3
... def fun2():
... print x
... return fun2
...
>>> fun1()()
3
非常简单:在类定义期间,我们能够访问外部(在本例中为全局)范围中定义的变量
示例2。
>>> x = 3
>>> class MyClass(object):
... x = x
...
>>> MyClass.x
3
>>> def mymethod(self):
... return self.x
...
>>> x = 3
>>> class MyClass(object):
... x = x
... mymethod = mymethod
...
>>> MyClass().mymethod()
3
>>> def myfunc():
... x = 3
... class MyClass(object):
... x = x
... return MyClass
...
>>> myfunc().x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in myfunc
File "<stdin>", line 4, in MyClass
NameError: name 'x' is not defined
>>> def my_defining_func():
... def mymethod(self):
... return self.y
... class MyClass(object):
... mymethod = mymethod
... y = 3
... return MyClass
...
>>> my_defining_func()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in my_defining_func
File "<stdin>", line 5, in MyClass
NameError: name 'mymethod' is not defined
>>> def fun1():
... x = 3
... def fun2():
... print x
... return fun2
...
>>> fun1()()
3
再次强调(暂时忽略为什么要这样做),这里没有什么意外:我们可以访问外部作用域中的函数
注意:正如弗里德里克在下面指出的,这个函数似乎不起作用。请参见示例5(及以上)
示例3。
>>> x = 3
>>> class MyClass(object):
... x = x
...
>>> MyClass.x
3
>>> def mymethod(self):
... return self.x
...
>>> x = 3
>>> class MyClass(object):
... x = x
... mymethod = mymethod
...
>>> MyClass().mymethod()
3
>>> def myfunc():
... x = 3
... class MyClass(object):
... x = x
... return MyClass
...
>>> myfunc().x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in myfunc
File "<stdin>", line 4, in MyClass
NameError: name 'x' is not defined
>>> def my_defining_func():
... def mymethod(self):
... return self.y
... class MyClass(object):
... mymethod = mymethod
... y = 3
... return MyClass
...
>>> my_defining_func()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in my_defining_func
File "<stdin>", line 5, in MyClass
NameError: name 'mymethod' is not defined
>>> def fun1():
... x = 3
... def fun2():
... print x
... return fun2
...
>>> fun1()()
3
嗯…打扰一下
这与示例2有什么不同
我完全糊涂了。请帮我整理一下。
谢谢
顺便说一下,这可能不仅仅是我理解上的问题,我已经在Python2.5.2和Python2.6.2上试过了。不幸的是,目前我只能接触到这些,但它们都表现出相同的行为
编辑
根据:在执行过程中的任何时候,至少有三个嵌套作用域的名称空间可以直接访问:
- 最内部的作用域,即 首先搜索,包含本地 名字
- 任何封闭函数的作用域 已搜索的函数 从最近的封闭 范围,包含非本地,但也包含 非全局名称
- 倒数第二个作用域包含 当前模块的全局名称
- 最外层范围(最后搜索) 名称空间包含内置的 名字
>>> x = 3
>>> class MyClass(object):
... x = x
...
>>> MyClass.x
3
>>> def mymethod(self):
... return self.x
...
>>> x = 3
>>> class MyClass(object):
... x = x
... mymethod = mymethod
...
>>> MyClass().mymethod()
3
>>> def myfunc():
... x = 3
... class MyClass(object):
... x = x
... return MyClass
...
>>> myfunc().x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in myfunc
File "<stdin>", line 4, in MyClass
NameError: name 'x' is not defined
>>> def my_defining_func():
... def mymethod(self):
... return self.y
... class MyClass(object):
... mymethod = mymethod
... y = 3
... return MyClass
...
>>> my_defining_func()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in my_defining_func
File "<stdin>", line 5, in MyClass
NameError: name 'mymethod' is not defined
>>> def fun1():
... x = 3
... def fun2():
... print x
... return fun2
...
>>> fun1()()
3
编辑3
正如@Frédéric所指出的,将的赋值给一个与外部作用域同名的变量似乎“掩盖”了外部变量,从而阻止了赋值的运行
因此,示例4的这个修改版本可以工作:
def my_defining_func():
def mymethod_outer(self):
return self.y
class MyClass(object):
mymethod = mymethod_outer
y = 3
return MyClass
my_defining_func()
但是,这并不是:
def my_defining_func():
def mymethod(self):
return self.y
class MyClass(object):
mymethod_temp = mymethod
mymethod = mymethod_temp
y = 3
return MyClass
my_defining_func()
我仍然不完全理解为什么会发生这种掩蔽:当赋值发生时,名称绑定不应该发生吗
此示例至少提供了一些提示(以及更有用的错误消息):
对g()的调用将引用由for绑定到f()中的变量
环如果在执行循环之前调用g(),则会出现NameError
被抚养
让我们运行Tim示例的两个简单版本:
>>> i = 6
>>> def f(x):
... def g():
... print i
... # ...
... # later
... # ...
... i = x
... g()
...
>>> f(3)
3
当g()
在其内部作用域中没有找到i
时,它会动态地向外搜索,在f
的作用域中找到i
,该作用域已通过i=x
赋值绑定到3
但是更改f
中最后两条语句的顺序会导致错误:
>>> i = 6
>>> def f(x):
... def g():
... print i
... # ...
... # later
... # ...
... g()
... i = x # Note: I've swapped places
...
>>> f(3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 7, in f
File "<stdin>", line 3, in g
NameError: free variable 'i' referenced before assignment in enclosing scope
因此,尽管C很乐意使用一个未绑定的变量(使用之前存储在那里的任何东西:在本例中为134520820),Python(谢天谢地)拒绝了
有趣的是,静态嵌套的作用域实现了“Python编译器所做的最重要的优化:函数的局部变量不保存在dict中,它们位于紧密的值向量中,每个局部变量访问都使用该向量中的索引,而不是名称查找。”这是Python名称解析规则的产物:您只能访问全局范围和局部范围,但不能访问介于两者之间的范围,例如,不能访问直接外部范围 EDIT:上述内容措词不当,您确实可以访问外部作用域中定义的变量,但通过从非全局命名空间执行
x=x
或mymethod=mymethod
操作,您实际上是在用本地定义的变量屏蔽外部变量
在示例2中,您的直接外部作用域是全局作用域,因此MyClass
可以看到mymethod
,但在示例4中,您的直接外部作用域是myu defining_func()
,因此它不能,因为mymethod
的外部定义已经被其局部定义屏蔽
有关非本地名称解析的详细信息,请参阅
还请注意,出于上述原因,我无法让示例3在Python 2.6.5或3.1.2下运行:
>>> def myfunc():
... x = 3
... class MyClass(object):
... x = x
... return MyClass
...
>>> myfunc().x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in myfunc
File "<stdin>", line 4, in MyClass
NameError: name 'x' is not defined
这是Python名称解析规则的产物:您只能访问全局和局部作用域,但不能访问介于两者之间的作用域,例如,不能访问直接外部作用域 EDIT:上述内容措词不当,您确实可以访问外部作用域中定义的变量,但通过从非全局命名空间执行
x=x
或mymethod=mymethod
操作,您实际上是在用本地定义的变量屏蔽外部变量
在示例2中,您的直接外部作用域是全局作用域,因此MyClass
可以看到mymethod
,但在示例4中,您的直接外部作用域是myu defining_func()
,因此它不能,因为mymethod
的外部定义已经被其局部定义屏蔽
有关非本地名称解析的详细信息,请参阅
还请注意,出于上述原因,我无法让示例3在Python 2.6.5或3.1.2下运行:
>>> def myfunc():
... x = 3
... class MyClass(object):
... x = x
... return MyClass
...
>>> myfunc().x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in myfunc
File "<stdin>", line 4, in MyClass
NameError: name 'x' is not defined
这篇文章已经有几年的历史了,但它属于