Python 多重赋值会抛出错误,但单独赋值不会
Python multiple assignment throws error but separate assignment does not
我正在反转一个链表,但是多重赋值会破坏这个函数,而单独的赋值则不会。有人可以解释这两个代码部分之间的执行差异吗?
我知道表达式的右侧在赋值之前被评估,但据我所知,如果是这种情况,我无处访问 None.next。
class Node:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
def clear():
print("------------------------------------------")
def isPalindrome(A):
if A is None:
return True
# get length
cur, length = A, 1
while cur.next is not None:
cur = cur.next
length += 1
# go to second half
cur, index = A, 0
while index < (length + 1) / 2:
cur = cur.next
index += 1
# start reversing
prev = None
while cur is not None:
# this throws error? what is the difference?
# cur, prev, cur.next = cur.next, cur, prev
temp = cur.next
cur.next = prev
prev = cur
cur = temp
# now prev has reversed second half
secondHalf = prev
firstHalf = A
# traverse both halves, comparing Ll[n] with Ll[length - 1 - n]
while secondHalf is not None and firstHalf is not None:
if firstHalf.val != secondHalf.val:
return False
firstHalf = firstHalf.next
secondHalf = secondHalf.next
return True
# even length simple case
def isPalindromeTest():
A = Node(1, Node(1, Node(1, Node(1))))
clear()
print(isPalindrome(A))
isPalindromeTest()
我期待注释行
# cur, prev, cur.next = cur.next, cur, prev
相当于
temp = cur.next
cur.next = prev
prev = cur
cur = cur.next
如果我使用第一个代码部分的错误消息:
Traceback (most recent call last):
File "linked_lists.py", line 1089, in <module>
isPalindromeTest()
File "linked_lists.py", line 1052, in isPalindromeTest
print(isPalindrome(A))
File "linked_lists.py", line 1027, in isPalindrome
cur, prev, cur.next = cur.next, cur, prev
AttributeError: 'NoneType' object has no attribute 'next'
Implying that I am accessing None.next, which in this context it would have to be prev.next if anything?
第二个代码部分:
------------------------------------------
True
有人可以解释一下这两个代码段之间的执行差异吗?
我也发现这种行为令人惊讶,但一旦您考虑对象属性和执行顺序在这样的实例中如何工作,它就有意义了。
为了自己演示,我做了一个MCVE例子:
class A:
def __init__(self, a):
self.a = a
a = A(1)
a, a.a = a.a, None
这些问题是,虽然右侧是一次求值,但左侧仍然是从左到右求值。这意味着 a
将完美地重新分配给 a.a
,但是当评估左侧的 a.a
时,a
将不再具有 .a
属性,因为它已被重新分配给一个整数。
将最后一行替换为以下内容具有相同的结果,并且可以更清楚地说明问题:
t = a.a, None
a = t[0]
a.a = t[1]
我正在反转一个链表,但是多重赋值会破坏这个函数,而单独的赋值则不会。有人可以解释这两个代码部分之间的执行差异吗?
我知道表达式的右侧在赋值之前被评估,但据我所知,如果是这种情况,我无处访问 None.next。
class Node:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
def clear():
print("------------------------------------------")
def isPalindrome(A):
if A is None:
return True
# get length
cur, length = A, 1
while cur.next is not None:
cur = cur.next
length += 1
# go to second half
cur, index = A, 0
while index < (length + 1) / 2:
cur = cur.next
index += 1
# start reversing
prev = None
while cur is not None:
# this throws error? what is the difference?
# cur, prev, cur.next = cur.next, cur, prev
temp = cur.next
cur.next = prev
prev = cur
cur = temp
# now prev has reversed second half
secondHalf = prev
firstHalf = A
# traverse both halves, comparing Ll[n] with Ll[length - 1 - n]
while secondHalf is not None and firstHalf is not None:
if firstHalf.val != secondHalf.val:
return False
firstHalf = firstHalf.next
secondHalf = secondHalf.next
return True
# even length simple case
def isPalindromeTest():
A = Node(1, Node(1, Node(1, Node(1))))
clear()
print(isPalindrome(A))
isPalindromeTest()
我期待注释行
# cur, prev, cur.next = cur.next, cur, prev
相当于
temp = cur.next
cur.next = prev
prev = cur
cur = cur.next
如果我使用第一个代码部分的错误消息:
Traceback (most recent call last):
File "linked_lists.py", line 1089, in <module>
isPalindromeTest()
File "linked_lists.py", line 1052, in isPalindromeTest
print(isPalindrome(A))
File "linked_lists.py", line 1027, in isPalindrome
cur, prev, cur.next = cur.next, cur, prev
AttributeError: 'NoneType' object has no attribute 'next'
Implying that I am accessing None.next, which in this context it would have to be prev.next if anything?
第二个代码部分:
------------------------------------------
True
有人可以解释一下这两个代码段之间的执行差异吗?
我也发现这种行为令人惊讶,但一旦您考虑对象属性和执行顺序在这样的实例中如何工作,它就有意义了。
为了自己演示,我做了一个MCVE例子:
class A:
def __init__(self, a):
self.a = a
a = A(1)
a, a.a = a.a, None
这些问题是,虽然右侧是一次求值,但左侧仍然是从左到右求值。这意味着 a
将完美地重新分配给 a.a
,但是当评估左侧的 a.a
时,a
将不再具有 .a
属性,因为它已被重新分配给一个整数。
将最后一行替换为以下内容具有相同的结果,并且可以更清楚地说明问题:
t = a.a, None
a = t[0]
a.a = t[1]