这个消息有点长,有很多例子,但我希望
会帮助我和其他人更好地理解变数的全部故事
以及Python 2.7中的属性查找。
我用的是PEP 227的条款
(http://www.python.org/dev/peps/pep-0227/)用于代码块(例如
模块、类定义、函数定义等)和
变量绑定(如赋值、参数声明、类
以及函数声明、for循环等)
我使用变量这个术语来表示不需要
点和需要用对象限定的名称的属性
名称(例如对象obj的属性x的obj.x)。
在Python中,所有代码块都有三个作用域,但是函数:本地的
全球
内置
Python中有四个块仅用于函数(根据
政治公众人物227):本地的
封闭函数
全球
内置
变量绑定到块并在块中找到它的规则是
很简单:变量与块中对象的任何绑定都会生成此变量
此块的本地变量,除非变量声明为全局变量(在
变量属于全局范围的情况)
使用规则LGB(local,
全局,内置)用于所有块,但函数
使用规则LEGB(local,
仅用于函数。
让我知道,举个例子来验证这个规则,并展示许多
特殊情况。对于每一个例子,我都会给出我的理解。拜托
如果我错了就纠正我。最后一个例子,我不明白
结果。
例1:x = "x in module"
class A():
print "A: " + x #x in module
x = "x in class A"
print locals()
class B():
print "B: " + x #x in module
x = "x in class B"
print locals()
def f(self):
print "f: " + x #x in module
self.x = "self.x in f"
print x, self.x
print locals()
>>>A.B().f()
A: x in module
{'x': 'x in class A', '__module__': '__main__'}
B: x in module
{'x': 'x in class B', '__module__': '__main__'}
f: x in module
x in module self.x in f
{'self': <__main__.b instance at>}
类(规则LGB)和中的函数没有嵌套作用域
如果不使用
限定名(本例中为self.x)。这在
第227页。
例2:z = "z in module"
def f():
z = "z in f()"
class C():
z = "z in C"
def g(self):
print z
print C.z
C().g()
f()
>>>
z in f()
z in C
这里使用LEGB规则查找函数中的变量,但是如果
类在路径中,将跳过类参数。又来了,
这就是PEP 227所解释的。
例3:var = 0
def func():
print var
var = 1
>>> func()
Traceback (most recent call last):
File "", line 1, in
func()
File "C:/Users/aa/Desktop/test2.py", line 25, in func
print var
UnboundLocalError: local variable 'var' referenced before assignment
我们期望使用python这样的动态语言
动态解析。但这不是函数的情况。本地的
变量在编译时确定。政治公众人物227和
http://docs.python.org/2.7/reference/executionmodel.html描述一下
这样做
“如果在代码块中的任何位置发生名称绑定操作,则所有
块中名称的使用被视为对
当前块。”
例4:x = "x in module"
class A():
print "A: " + x
x = "x in A"
print "A: " + x
print locals()
del x
print locals()
print "A: " + x
>>>
A: x in module
A: x in A
{'x': 'x in A', '__module__': '__main__'}
{'__module__': '__main__'}
A: x in module
但我们在这里看到,PEP227中的语句“如果一个名称绑定
操作发生在代码块中的任何位置,所有名称的使用
在块内被视为对当前块的引用
当代码块是类时出错。而且,对于班级来说
本地名称绑定不是在编译时进行的,而是在
使用类命名空间执行。在这方面,
PEP227和Python文档中的执行模型具有误导性
有些地方错了。
例5:x = 'x in module'
def f2():
x = 'x in f2'
def myfunc():
x = 'x in myfunc'
class MyClass(object):
x = x
print x
return MyClass
myfunc()
f2()
>>>
x in module
我对这段代码的理解如下。指令x=x
首先查找表达式的右手x所指的对象
到。在这种情况下,对象在类中本地查找,然后
遵循规则LGB,它在全局范围内查找,即
字符串“x in module”。那么MyClass的本地属性x是
在类字典中创建并指向字符串对象。
例6:
下面是一个我无法解释的例子。
它非常接近示例5,我正在更改本地MyClass
从x到y的属性x = 'x in module'
def f2():
x = 'x in f2'
def myfunc():
x = 'x in myfunc'
class MyClass(object):
y = x
print y
return MyClass
myfunc()
f2()
>>>
x in myfunc
为什么在这种情况下,MyClass中的x引用在
最里面的功能?