这是一个简单的文件,描述了一些不一致的Python(3.6)行为。为什么Case 1
和Case 2
可能会运行但Case 3
失败,即使Case 3
只是前两种情况的合并?
我提供了前两种情况的dis
输出。
import dis # Python bytecode disassembler
class A(object):
def __init__(self):
self.x # In case 2, getting x results in a function call.
# CASE 1: Legal
def x(self):
y
pass
'''
# CASE 2: Legal
@property
def x(self):
pass
'''
'''
# CASE 3: Illegal:
@property
def x(self):
y
pass
'''
if __name__ == '__main__':
a = A()
dis.dis(A)
案例1字节码:
Disassembly of __init__:
5 0 LOAD_FAST 0 (self)
2 LOAD_ATTR 0 (x)
4 POP_TOP
6 LOAD_CONST 0 (None)
8 RETURN_VALUE
Disassembly of x:
9 0 LOAD_GLOBAL 0 (y)
2 POP_TOP
10 4 LOAD_CONST 0 (None)
6 RETURN_VALUE
案例2字节码:
Disassembly of __init__:
5 0 LOAD_FAST 0 (self)
2 LOAD_ATTR 0 (x)
4 POP_TOP
6 LOAD_CONST 0 (None)
8 RETURN_VALUE
答案 0 :(得分:1)
这里没有矛盾。
当您实例化a = A()
时,会调用__init__
,调用self.x
,它将执行x
的正文。那时,没有y
内窥镜,所以你得到一个例外。
答案 1 :(得分:1)
感谢@ chepner的评论:
在案例1中,你没有打电话; self.x是一个函数引用 那是没用过的。在案例3中,self.x实际上调用了已定义的getter for x,大概是试图访问未定义的全局 名。
案例3中由行self.x
引起的行为与案例1根本不同,因为案例1不会调用任何内容 - 它只是评估对函数的引用。
另一方面,案例3中的self.x
执行x
方法的正文,导致未定义的y
错误。
为了确认@Chepner的评论,我用案例1运行了a.x()并得到了与案例3相同的错误。