我正在为教育Python库编写链接列表。以下是代码的重要摘要:
class Element(object):
def __init__(self, value, next):
self.value = value
self.next = next
class LinkedList(object):
def __init__(self):
self.head = None
self.tail = None
def insert_back(self, element):
if self.empty():
self.insert_front(element)
else:
self.tail.next = Element(element, None)
self.tail = self.tail.next
# I'd like to replace the above two lines with this
# self.tail = self.tail.next = Element(element, None)
我的问题来自最后一行。根据{{3}},Python对链式赋值的独特实现是罪魁祸首。
在其他语言中,最后一行与其上面的两行具有相同的效果,但Python首先计算表达式Element(element, None)
,然后从左到右分配结果,因此{{1} }在self.tail
之前分配。这导致前一个tail元素没有引用新的tail元素,而新的tail元素引用它自己。
我的问题是:有没有办法用一个语句执行这两个作业?
我完全满足于使用更明确的两行分配;这只是为了好奇。
答案 0 :(得分:5)
分配从不链接。
分配首先评估右手表达式,然后将结果从左到右依次分配给左手目标。
请参阅assigment statement documentation:
赋值语句计算表达式列表(请记住,这可以是单个表达式或以逗号分隔的列表,后者产生元组)并将单个结果对象从左到右分配给每个目标列表。
所以你的代码:
self.tail = self.tail.next = Element(element, None)
实际上意味着:
result = Element(element, None)
self.tail = result
self.tail.next = result
您可以使用此功能,只需撤消分配顺序:
self.tail.next = self.tail = Element(element, None)
分配正确的顺序:
result = Element(element, None)
self.tail.next = result
self.tail = result
这会导致链接列表的正确行为:
>>> head = tail = Element(0, None)
>>> tail.next = tail = Element(1, None)
>>> head.value
0
>>> head.next
<__main__.Element object at 0x10262e510>
>>> head.next.value
1
>>> tail is head.next
True
>>> tail.next = tail = Element(2, None)
>>> tail is head.next.next
True