Here's a simple file depicting some inconsistent Python (3.6) behavior. Why is it possible that Case 1
and Case 2
run but Case 3
fails, even though Case 3
is just a merger of the first two cases?
I have provided the dis
output of the first two cases.
import dis # Python bytecode disassembler
class A(object):
def __init__(self):
self.x # In case 2 (and 3), getting x results in a function call (because they are @properties), which fails when instantiating A because y is undefined. Case 1 evaluates the reference to a function without calling it and so it does not raise an exception.
# 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)
Case 1 bytecode:
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
Case 2 bytecode:
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
There is no inconsistency here.
When you instantiate a = A()
, __init__
is called, which calls self.x
, which will execute the body of x
. At that point, there is no y
inscope, so you get an exception.
Thanks to @chepner's comment:
In case 1, you aren't calling anything; self.x is a function reference that isn't used. In case 3, self.x actually calls the defined getter for x, which presumably is then trying to access an undefined global name.
The behavior caused by the line self.x
in case 3 is fundamentally different from case 1 because case 1 doesn't call anything -- it just evaluates a reference to a function.
On the other hand, self.x
in case 3 executes the body of the x
method, resulting in the undefined y
error.
In order to confirm @chepner's comment, I ran ax() with case 1 and got the same error as in case 3.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.