Python类与函数中全局、局部变量作用域差异及代码疑问解析
为什么类C中x和y的表现差异?类与函数作用域规则的区别
这问题真的问到点子上了,刚好涉及Python中类定义和函数作用域的核心差异,咱们一步步拆解分析:
一、先看类C中x和y的表现差异原因
首先要明确:类定义的代码块是在一个特殊的命名空间中执行的,它的变量查找规则和普通函数完全不一样。
关于x的表现(输出xlocal)
在func函数里定义了x = "xlocal",而类C内部没有任何对x的赋值语句(没有x = ...)。当类C执行print x时,Python的查找顺序是:
- 先检查类C自己的命名空间(此时还没定义任何x,所以找不到);
- 接着向上查找封闭的函数作用域(也就是
func的作用域),这里刚好有x = "xlocal",所以直接用这个值,符合预期。
关于y的表现(先输出ytop,再输出1)
类C内部有一行y = 1的赋值语句——这是关键!Python在处理类定义代码时,只要类内部存在对某个名字的赋值(不管赋值语句在引用的前面还是后面),就会把这个名字标记为类的属性(属于类C自己的命名空间)。
当执行print y时,Python的查找逻辑变成了:
- 先检查类C的命名空间(此时y还没被赋值,不存在);
- 因为类内部有y的赋值,所以Python不会去封闭的func作用域查找(也就是跳过了
func里的y = "ylocal"); - 直接跳到全局作用域,找到全局的
y = "ytop",所以输出ytop; - 执行
y = 1后,类C的命名空间里有了y属性,所以第三个print y输出1。
你可以做个小验证:如果把类C里的y = 1删掉,再运行代码,print y就会输出ylocal——因为此时类内部没有对y的赋值,Python就会向上找func作用域的y了。
二、类与函数作用域规则的核心区别
如果把类C换成函数,比如这样:
x = "xtop" y = "ytop" def func(): x = "xlocal" y = "ylocal" def inner(): print x print y # 这里会触发UnboundLocalError y = 1 print y inner() func()
运行后会抛出UnboundLocalError: local variable 'y' referenced before assignment,这和类的表现完全不同,核心差异在于:
函数作用域的规则
- 只要函数内部存在对某个变量的赋值操作(不管赋值语句在代码的哪个位置),Python在编译函数时就会把这个变量标记为局部变量;
- 当引用这个局部变量时,如果它还没被赋值,就会直接抛出错误,不会去外部作用域查找。
类定义作用域的规则
- 类定义块是一个特殊的命名空间,当类内部存在对某个变量的赋值时,该变量会被视为类属性;
- 在赋值前引用这个变量时,Python不会去封闭的函数作用域查找,而是直接跳转到全局作用域(如果全局也没有才会报错);
- 如果类内部没有对该变量的赋值,才会向上查找封闭的函数作用域。
简单来说:函数是"先标记局部,找不到就报错",类是"有赋值就归为类属性,赋值前引用就找全局,没赋值才找外部函数"。
内容的提问来源于stack exchange,提问作者Abirdcfly
相关产品推荐
相关产品推荐

