3

我正在为一个教育 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)

我的问题来自最后一行。根据这个问题的最高答案,Python独特的链式赋值实现是罪魁祸首。

在其他语言中,最后一行与它上面的两行具有相同的效果,但 PythonElement(element, None)先计算表达式,然后从左到右分配结果,因此self.tail在之前赋值self.tail.next。这导致前一个尾元素不引用新的尾元素,而新的尾元素引用自身。

我的问题是:有没有办法用一条语句来执行这两个任务?

我完全满足于使用更明确的两行赋值;这只是出于好奇。

4

1 回答 1

5

分配永远不会被链接。

赋值首先计算右侧表达式,然后将结果从左到右一个接一个地分配给左侧目标。

请参阅分配声明文档

赋值语句计算表达式列表(请记住,这可以是单个表达式或逗号分隔的列表,后者产生一个元组)并将单个结果对象从左到右分配给每个目标列表。

所以你的代码:

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
于 2013-04-16T19:24:05.397 回答