1
wevsty 2017-11-06 01:11:58 +08:00
test 函数里应该使用 print(self.a)。
|
2
Trim21 2017-11-06 01:44:29 +08:00 via Android
http://python.jobbole.com/81367/
有是有,但是我没看懂类定义这里到底是怎么算得… |
3
takanasi 2017-11-06 01:59:18 +08:00 via Android
从来没想过直接访问类属性,又学到了无用的知识
|
5
zhy0216 2017-11-06 02:27:48 +08:00
感觉是个 bug ???
|
6
zhy0216 2017-11-06 02:41:06 +08:00
这里有答案: https://www.python.org/dev/peps/pep-0227/#specification
Names in class scope are not accessible 不过我还没理解为什么这么设计? 可能是这样 如果允许你这样写, 我们假设还有一个 global var: a, 再运行 del A.a, 那这时候 test 的 a 是不是会指向 global 的 a 那就成了 dynamic scope 了... 可能是你这样写, python 无法再编译后就确定其 scope 必须在运行时才知道 |
7
lrxiao 2017-11-06 03:52:57 +08:00
因为
class A: a = 3 print(3) 相当于 def func_A(): a = 3 # 3 in func_A().__code__.co_consts, a in func_A().__code__.co_names print(3) A = builtin.__build_class__(func_A, 'A') # 转移__code__中的 attribute |
8
lrxiao 2017-11-06 03:55:26 +08:00
嘛 缩进全砸了。。这个东西和作用域没啥关系
|
9
binux 2017-11-06 05:07:25 +08:00 via Android
我的理解是,类中的作用域是声明时的作用域,运行时不存在
|
10
greenmoon55 2017-11-06 08:06:55 +08:00
|
11
mec 2017-11-06 09:41:33 +08:00
方法没传入 cls 或者 self 啊
|
12
ifkite 2017-11-06 09:55:23 +08:00 1
有作用域。可以改成这样。
class A: ....a = 3 ....def test(): ........print(a) ....test() 你的代码调方式不对,你的代码调用方式是类的方法的调用,需要函数需要用 staticmethod 或 classmethod 装饰。 类中定义的方法 要么 staticmethod,要么 classmethod,要么定义实例的方法。 |
13
SimbaPeng OP @ifkite 你这样写一样报 a 变量不存在的 error,在 py3 中不需要用 staticmethod 或 classmethod 装饰也能 A.test()这样调用的
|
15
zhengxiaowai 2017-11-06 10:41:55 +08:00
Python 中变量可以分为:局部变量、全局变量、自有变量。
Python 是有作用域 全局的 global() 和 本地的 locals() 可以得到。 你用一个类举例子是不正确的。 class A: ....a = 3 ....def test(): ........print(a) A.test() 这个栗子肯定是有问题的。。。必然报错,我也无法重现这个错误。错也不是你那个错误,而是 TypeError: unbound method test() must be called with A instance as first argument (got nothing instead) 很明显 test() 是一个未绑定方法,具体什么是未绑定,可以参考 Fluent Python 中的相关章节。(具体哪一个忘记了。。) 这个 Class A 中 a 叫做类属性,然而在 Python 类中要获得属性需要用 __new__ 返回的值,也就是 self.a 来获取。 这就是为什么或有方法第一个参数都是 self 了。 class A: ....a = 3 ....print(a) 这个例子能够输出是应为 print() 执行时在构建类时候,也就是在 __new__ 中执行。这时候 a 还是一个普通变量,不是一个属性。 假设你的描述的都是正确的,那么就可以总结来说,第一个和第二个的差别在于执行的时期不同。当类生成以后,a 就变成类属性 需要通过 A.a 或者 self.a 来调用 |
16
ipwx 2017-11-06 10:47:58 +08:00
|
17
lrxiao 2017-11-06 10:57:56 +08:00
|
18
SimbaPeng OP @zhengxiaowai
首先我这个例子在 py3.6 中调用是肯定不会报你说的那个错误,你可以自己去试试。 另外: class A: .... a = 3 ....print(locals()) 输出:{'__module__': '__main__', '__qualname__': 'A', 'a': 3} 说明在 class 定义时候是有局部作用域产生的. 如果说执行时间不同,那么这样写应该可以找到 a 吧: class A: ....a = 3 ....def test(): ........print(a) ....test() 输出: NameError: name 'a' is not defined 一样是找不到 a 变量,我估计是类的作用域和类中的方法不是嵌套关系 |
19
lrxiao 2017-11-06 11:08:59 +08:00
这个 a 只是个 local variable 改下 @ifkite 的类
import builtins import sys old_bc = builtins.__build_class__ def fake_build_class(cls_func, cls_name): ....print("Build class...") ....print(cls_func.__code__.co_consts) ....print(cls_func.__code__.co_names) ....print(cls_name) ....print("Create class...") ....cls = old_bc(cls_func, cls_name) ....print("End of create class...") ....print(cls.__dict__['a']) builtins.__build_class__ = fake_build_class class A: ....a = 3 ....def test(): ........frame = sys._getframe(1) ........print(frame.f_locals['a']) ....test() 嗯 极其丧病 |
20
hcnhcn012 2017-11-06 12:24:26 +08:00 via iPhone
好问题啊。。。我到现在都没搞清楚和模块级作用域的区别
|
21
hcnhcn012 2017-11-06 12:40:46 +08:00 via iPhone
@zhengxiaowai 那为什么类里面不弄个只关于当前类内部的 global,nonlocal 和 local 的作用域呢,这样感觉更加清楚了啊,比如调用类属性就不用 classmethod 或 staticmethod 了,这样不是更像一个模块了嘛,一直不懂这个设计。。。
|
22
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() |
23
focusheart 2017-11-06 16:58:40 +08:00
@ipwx 支持。
|
24
Gesamtkunstwerk 2017-11-06 19:22:53 +08:00
楼上大牛们扯一堆表示萌新并看不懂,难道不是实例化的问题?
先把 A 实例化,实例化对象再调用 test (),而且你函数写的也不对,应该 def test ( self ):print ( self.a ) |
25
luckins 2017-11-06 19:53:24 +08:00
既没有实例化,也没用正确的方式调用全局变量
|
26
ob 2017-11-06 19:59:35 +08:00 via Android
萌新表示看不懂这个 test 是类方法吗?如果不是怎么可以直接调用呢?不是应该先实例化后才能调?
|
27
laqow 2017-11-06 20:48:13 +08:00 via Android
个人认为 python 类的变量不是楼主这样定义和赋值的,应该是在__init__(self)里面定义,这样在形式上能让人理解变量是干嘛用的,也不会让编译器误解。python 类本身也是一个对象,和数组,函数,字符串甚至它自己的实例都没有区别,不按规范写你把它当个对象用也可以。
|
28
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. |
29
l1093178 2017-11-07 01:11:27 +08:00
至于为什么要这么设计,估计就是一些非常奇怪的历史性问题了,@zhy0216 提到的 PEP-227 也许值得一读
|