Python NoneType对象未按预期工作

2024-04-26 22:38:35 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试pass by object一个None值,希望将其重新分配给实际值。有人能解释一下为什么这不起作用吗?我想既然None是一个NoneType,那么它将通过引用传入,当我使用传入变量时,我会改变原来的None对象。这不正确吗?我在下面提供了一个片段来演示我的案例:

class MyClass:
    def __init__(self):
        self.value = None

    def assign(self, object):
        object = OtherClass()

example = MyClass()
example.assign(example.value)

结果是example.value仍然是None。为什么?我读过一些SO posts,但没有一个清楚地解释这一点。在

编辑:不是重复的,因为我想知道为什么当我认为它应该是按引用传递时,它的行为像传递值一样。最后,我得出结论,NoneType对象是不可变的,因此总是按值传递。我需要使用list类型的对象或可变的对象。在

再次编辑:我的示例代码只是一般情况。我试图实现一个BST,我的初始根节点是None,当我将根节点指定为Node对象时,它仍然是NoneType,这让我很困惑,这也是这个问题的原因。在

最后编辑:下面的答案提供了一个非常好的传递对象的tl;dr摘要。我只是通过搜索/阅读论坛无法理解。在


Tags: 对象selfnone编辑by节点objectvalue
2条回答

问题是函数调用传递值,而不是引用。具体地说,传递给函数的引用保持不变,直到它反弹(它的值集),此时在函数的本地创建一个副本。任何形式的other = ...都会导致这种情况发生。如果你想要这种行为,你需要使用一个可变的对象,比如一个列表。例如:

class MyClass:
    def __init__(self):
        self.value = [None]

    def assign(self, object):
        object[0] = OtherClass()

example = MyClass()
example.assign(example.value)

希望这有帮助!在

这正是对象调用(Python规则)不同于引用引用(C++引用语义)的情况。在

不同的是,分配给一个不合格的名称会重新绑定该名称,它对该名称以前可能绑定的任何内容都没有任何影响(除了可能销毁它之外,如果没有其他引用的话)。该名称与可能引用同一对象的任何其他名称没有连接,因此这些其他名称不会更改。在

所以在本例中,object最初被设置为指向example.value指向的同一对象。但是在下一行中,重新绑定object(非限定名称赋值),它指向一个完全不同的对象。在

相比之下,如果你有:

def assign_value(self, object):
    object.value = OtherClass()

并称之为:

^{pr2}$

那么example和{}将引用同一个对象,并且您对限定名的赋值将替换该对象上的value。在

尽管如此,这里的用例不需要任何这样的更改。调用example.assign(example.value)没有任何意义,因为self是隐式传递的,它将自动授予您对value的访问权(限定访问权)。似乎您真正想要的只是在请求时延迟初始化,而没有任何参数:

def assign(self):
    self.value = OtherClass()

称为:

example.assign()

针对您的编辑:Pythondocuments this call behavior explicitly

The actual parameters (arguments) to a function call are introduced in the local symbol table of the called function when it is called; thus, arguments are passed using call by value (where the value is always an object reference, not the value of the object).[1]

其中脚注1阐明:

[1] Actually, call by object reference would be a better description, since if a mutable object is passed, the caller will see any changes the callee makes to it (items inserted into a list).

<>这是有意的;当你没有其他调用语义时,C++引用语义是不可行的,因为没有明显的选择方法,意味着沿着一个巨大的调用链的每个变量都结束引用同一个对象,导致大量的行动距离。在

相关问题 更多 >