为什么按common来切换设置变量的顺序,结果会不一样?
Why is the result different if I switch the sequence in setting variables by common?
为了更好的解释,我写了一个小classnode
,并设置了a
和b
:
class node(object):
def __init__(self,x,y):
self.val = x
self.next = y
a = node(5,6)
b = None
然后我发现结果不一样:
a, a.next, b = a.next, b, a
print(a,b) #it returns AttributeError: 'int' object has no attribute 'next'
和:
a.next, a, b = b, a.next, a
print(a,b) #it returns 6 <__main__.node object at 0x1021a0400>
我们都知道,当a, b = b, a+b
时,它同时给a,b取值,代码变成b, a = a+b, b
.
时结果不变
那么,有人可以帮我吗?为什么会这样?
仅当 LHS 元素独立时"simultaneously" 才会发生元组解包。由于您已经造成了它们 不 独立的情况,因此实施中的次要细节现在很重要。
在这种情况下,重要的细节是 LHS 元素是从左到右分配的。由于 a
在查看 a.next
时包含 int
,因此抛出异常。
import dis
def f1():
a, a.next, b = a.next, b, a
def f2():
a.next, a, b = b, a.next, a
print('f1:')
dis.dis(f1)
print()
print('f2:')
dis.dis(f2)
...
f1:
4 0 LOAD_FAST 0 (a)
3 LOAD_ATTR 0 (next)
6 LOAD_FAST 1 (b)
9 LOAD_FAST 0 (a)
12 ROT_THREE
13 ROT_TWO
14 STORE_FAST 0 (a)
17 LOAD_FAST 0 (a)
20 STORE_ATTR 0 (next)
23 STORE_FAST 1 (b)
26 LOAD_CONST 0 (None)
29 RETURN_VALUE
f2:
7 0 LOAD_FAST 0 (b)
3 LOAD_FAST 1 (a)
6 LOAD_ATTR 0 (next)
9 LOAD_FAST 1 (a)
12 ROT_THREE
13 ROT_TWO
14 LOAD_FAST 1 (a)
17 STORE_ATTR 0 (next)
20 STORE_FAST 1 (a)
23 STORE_FAST 0 (b)
26 LOAD_CONST 0 (None)
29 RETURN_VALUE
解包不是同时进行的。只是右侧是 "constructed",然后 "unpacked" 进入左侧。但是每边都是从左到右计算的!
所以发生的事情大致是这样的(它实际上并没有构建元组,但这只是一个实现细节):
tmp = (a.next, b, a)
a = tmp[0]
a.next = tmp[1] # fails because "a" is now an integer
b = tmp[2]
在第二种情况下它有效,因为 "re-assigned" 在 "re-assigning" a.next
:
之后
tmp = (b, a.next, a)
a.next = tmp[0] # a still has the next attribute
a = tmp[1]
b = tmp[2]
为了更好的解释,我写了一个小classnode
,并设置了a
和b
:
class node(object):
def __init__(self,x,y):
self.val = x
self.next = y
a = node(5,6)
b = None
然后我发现结果不一样:
a, a.next, b = a.next, b, a
print(a,b) #it returns AttributeError: 'int' object has no attribute 'next'
和:
a.next, a, b = b, a.next, a
print(a,b) #it returns 6 <__main__.node object at 0x1021a0400>
我们都知道,当a, b = b, a+b
时,它同时给a,b取值,代码变成b, a = a+b, b
.
那么,有人可以帮我吗?为什么会这样?
仅当 LHS 元素独立时"simultaneously" 才会发生元组解包。由于您已经造成了它们 不 独立的情况,因此实施中的次要细节现在很重要。
在这种情况下,重要的细节是 LHS 元素是从左到右分配的。由于 a
在查看 a.next
时包含 int
,因此抛出异常。
import dis
def f1():
a, a.next, b = a.next, b, a
def f2():
a.next, a, b = b, a.next, a
print('f1:')
dis.dis(f1)
print()
print('f2:')
dis.dis(f2)
...
f1:
4 0 LOAD_FAST 0 (a)
3 LOAD_ATTR 0 (next)
6 LOAD_FAST 1 (b)
9 LOAD_FAST 0 (a)
12 ROT_THREE
13 ROT_TWO
14 STORE_FAST 0 (a)
17 LOAD_FAST 0 (a)
20 STORE_ATTR 0 (next)
23 STORE_FAST 1 (b)
26 LOAD_CONST 0 (None)
29 RETURN_VALUE
f2:
7 0 LOAD_FAST 0 (b)
3 LOAD_FAST 1 (a)
6 LOAD_ATTR 0 (next)
9 LOAD_FAST 1 (a)
12 ROT_THREE
13 ROT_TWO
14 LOAD_FAST 1 (a)
17 STORE_ATTR 0 (next)
20 STORE_FAST 1 (a)
23 STORE_FAST 0 (b)
26 LOAD_CONST 0 (None)
29 RETURN_VALUE
解包不是同时进行的。只是右侧是 "constructed",然后 "unpacked" 进入左侧。但是每边都是从左到右计算的!
所以发生的事情大致是这样的(它实际上并没有构建元组,但这只是一个实现细节):
tmp = (a.next, b, a)
a = tmp[0]
a.next = tmp[1] # fails because "a" is now an integer
b = tmp[2]
在第二种情况下它有效,因为 "re-assigned" 在 "re-assigning" a.next
:
tmp = (b, a.next, a)
a.next = tmp[0] # a still has the next attribute
a = tmp[1]
b = tmp[2]