在红黑树上编写Join操作时遇到了一些问题。我发现了造成这种情况的原因,并尝试将其简化为以下代码(因为整个红黑树代码块几乎不可读)。
那么谁能向我解释为什么最后一行的评估结果为False?我认为由于a = b行仅分配指针,因此c.left现在应指向b。
class RedBlackTreeNode:
def __init__(self, key, color):
self.key, self.color, self.left, self.right, self.parent = key, color, None, None, None
a = RedBlackTreeNode(None, False)
b = RedBlackTreeNode(None, False)
c = RedBlackTreeNode(1, False)
c.left = a
a = b
print(c.left == b)
>>> False
答案 0 :(得分:1)
很好的旧名称和值混淆,这里带有一些复杂的代码。让我们倒退吧。
首先,您正在使用==
进行比较。这些都是RedBlackTreeNode
类型的对象,它们不会覆盖equality behaviour.类型,因此实际上是身份测试。
第二,我们追溯两个操作数c.left
和b
的来源。我们发现在{em> c.left
更改为引用a
之前,已为a
分配了b
的值。因此,c.left
指的是最初绑定为a
的节点,但不再以该名称知道。
在C风格的指针语言中,每个变量实际上都是一个指针(引用),并且指针总是按值复制;没有指向指针的指针类型,因此即使它们可以指向相同的数据,它们也不能彼此改变。
Python的对象本身就是实体,变量只是引用对象的名称。因此,重新分配a
仅意味着找到以前引用的对象的方法更少。每个名称(无论是您的本地名称,模块的全局名称还是c
之类的对象)仅引用某个对象,它们彼此之间一无所知(尽管可能有引用计数来跟踪它们的存在)。
Ned Batchelder's article on Python Names and Values可能会清除一点。
看起来也可能像这些名称,但重定向到更复杂的行为。 custom attribute access和properties就是这样做的,尤其是对于像ctypes
结构这样翻译的事物。
答案 1 :(得分:0)
a
只是一个名称,而不是C语言中的指针。您甚至可以执行a = 1
,它不会将RedBlackTreeNode
中的c.left
更改为{{ 1}}。
int
的值为c.left
(在a
中已分配)。要更改它,您需要再次分配a = RedBlackTreeNode()
。
*在某些IDE中,您甚至可以在c.left =
上看到警告:a = b
。