为什么值/指针分配在Python中的行为如此?

时间:2019-10-06 12:24:51

标签: python python-3.x object pointers

在红黑树上编写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

2 个答案:

答案 0 :(得分:1)

很好的旧名称和值混淆,这里带有一些复杂的代码。让我们倒退吧。

首先,您正在使用==进行比较。这些都是RedBlackTreeNode类型的对象,它们不会覆盖equality behaviour.类型,因此实际上是身份测试。

第二,我们追溯两个操作数c.leftb的来源。我们发现在{em> c.left更改为引用a之前,已为a分配了b的值。因此,c.left指的是最初绑定为a的节点,但不再以该名称知道。

在C风格的指针语言中,每个变量实际上都是一个指针(引用),并且指针总是按值复制;没有指向指针的指针类型,因此即使它们可以指向相同的数据,它们也不能彼此改变。

Python的对象本身就是实体,变量只是引用对象的名称。因此,重新分配a仅意味着找到以前引用的对象的方法更少。每个名称(无论是您的本地名称,模块的全局名称还是c之类的对象)仅引用某个对象,它们彼此之间一无所知(尽管可能有引用计数来跟踪它们的存在)。

Ned Batchelder's article on Python Names and Values可能会清除一点。

看起来也可能像这些名称,但重定向到更复杂的行为。 custom attribute accessproperties就是这样做的,尤其是对于像ctypes结构这样翻译的事物。

答案 1 :(得分:0)

a只是一个名称,而不是C语言中的指针。您甚至可以执行a = 1,它不会将RedBlackTreeNode中的c.left更改为{{ 1}}。

int的值为c.left(在a中已分配)。要更改它,您需要再次分配a = RedBlackTreeNode()

*在某些IDE中,您甚至可以在c.left =上看到警告:a = b