我想知道 Python 的类中到底有没有建立作用域?

2017-11-06 00:58:56 +08:00
 SimbaPeng
以下是 py3 的代码:

class A:
....a = 3
....def test():
........print(a)


A.test()

输出:name 'a' is not defined

这个结果来看类中貌似是没有作用域的。

class A:
....a = 3
....print(a)

输出:3
但是这个例子又能正常打印出本地变量 3,说明类中还是有局部作用域的?
4157 次点击
所在节点    Python
29 条回复
hcnhcn012
2017-11-06 12:40:46 +08:00
@zhengxiaowai 那为什么类里面不弄个只关于当前类内部的 global,nonlocal 和 local 的作用域呢,这样感觉更加清楚了啊,比如调用类属性就不用 classmethod 或 staticmethod 了,这样不是更像一个模块了嘛,一直不懂这个设计。。。
ifkite
2017-11-06 14:57:56 +08:00
@SimbaPeng
额,测了下确实会报 a 变量不存在的 error。
改成这样呢?
class A(object):
....a = 3
....def func():
........print 'i am in test:', locals()
........print A.a
....print 'i am in A:', locals()
....func()
....print 'i am in A:', locals()
focusheart
2017-11-06 16:58:40 +08:00
@ipwx 支持。
Gesamtkunstwerk
2017-11-06 19:22:53 +08:00
楼上大牛们扯一堆表示萌新并看不懂,难道不是实例化的问题?
先把 A 实例化,实例化对象再调用 test (),而且你函数写的也不对,应该 def test ( self ):print ( self.a )
luckins
2017-11-06 19:53:24 +08:00
既没有实例化,也没用正确的方式调用全局变量
ob
2017-11-06 19:59:35 +08:00
萌新表示看不懂这个 test 是类方法吗?如果不是怎么可以直接调用呢?不是应该先实例化后才能调?
laqow
2017-11-06 20:48:13 +08:00
个人认为 python 类的变量不是楼主这样定义和赋值的,应该是在__init__(self)里面定义,这样在形式上能让人理解变量是干嘛用的,也不会让编译器误解。python 类本身也是一个对象,和数组,函数,字符串甚至它自己的实例都没有区别,不按规范写你把它当个对象用也可以。
l1093178
2017-11-07 01:03:41 +08:00
TL; DR 类在定义的时候是有作用域的,这个作用域内的变量只能在 class 块内访问,而不能在类的方法(函数)中访问。

这种问题当然应该是去看 Language Reference 啦

Python 3: https://docs.python.org/3/reference/executionmodel.html#naming-and-binding

> The following constructs bind names: formal parameters to functions, import statements, class and function definitions (these bind the class or function name in the defining block) ...

然后

> Class definition blocks and arguments to exec() and eval() are special in the context of name resolution. A class definition is an executable statement that may use and define names. These references follow the normal rules for name resolution with an exception that unbound local variables are looked up in the global namespace. The namespace of the class definition becomes the attribute dictionary of the class. The scope of names defined in a class block is limited to the class block; it does not extend to the code blocks of methods – this includes comprehensions and generator expressions since they are implemented using a function scope.
l1093178
2017-11-07 01:11:27 +08:00
至于为什么要这么设计,估计就是一些非常奇怪的历史性问题了,@zhy0216 提到的 PEP-227 也许值得一读

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://tanronggui.xyz/t/403797

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX