【问题标题】:Are functions being changed during assignment?分配期间是否更改了功能?
【发布时间】:2021-02-02 10:19:57
【问题描述】:

我认为我对 Python 如何传递对象有很好的了解 (this article seemed enlightening)。

然后我尝试了一些简单的方法,只是将函数分配给变量。

class Thingy:
    def __init__(self):
        self.foo = {"egg": [1], "spam": [2]}
    def calc(self):
        self.foo["egg"][0] = 3
        self.foo["spam"][0] = 4
    def egg(self):
        return self.foo["egg"][0]
    def spam(self):
        return self.foo["spam"]

thingy = Thingy()
x = thingy.egg()
y = thingy.spam()

print(x) # prints 1
print(y[0]) # prints 2
print(thingy.foo)
thingy.calc()
print(x) # prints 1 (???)
print(y[0]) # prints 4
print(thingy.foo)

我不完全确定发生了什么,尤其是字典中的值已更新。我的猜测是当变量x被赋值时,它实际上是指一个返回值已经被评估为“1”的函数。

我的理解正确吗?我希望能清楚地解释为什么 Python 决定区别对待 .egg().spam()

【问题讨论】:

  • 它并没有区别对待它们; egg 返回一个不可变值(整数),spam 返回一个可变值(一个列表)。
  • “然后我尝试了一些简单的方法,只是将函数分配给变量。” - 您没有将函数分配给变量。您正在调用方法并将返回的对象分配给变量。

标签: python variable-assignment


【解决方案1】:

声明

x = thingy.egg()
y = thingy.spam()

x 创建为整数,将y 创建为列表。但是你必须知道的是y = thingy.spam()这行只是一个浅拷贝。 medium 是这样定义浅拷贝的:

浅拷贝是对象的按位拷贝。创建了一个新对象,该对象具有原始对象中值的精确副本。如果对象的任何字段是对其他对象的引用,则仅复制引用地址,即仅复制内存地址。

因此变量y 包含列表元素的地址(或更通俗地说是引用),并且更改列表也会更改它,这与分配新内存位置的x 不同。

【讨论】:

    【解决方案2】:

    当你跑步时

    x = thingy.egg()
    

    thingy.egg() 返回一个 int 女巫,其值与 foo["egg"][0] ans 中的值相同,而不是分配给 x 而

    y = thingy.spam()
    

    thingy.spam() 返回一个包含 4 个女巫的列表,与 foo["spam"] 相同。这与对象的可变性有关。在您的计算函数中,两个整数 foo["egg"][0]foo["spam"][0] 用新对象重新定义。然而,列表 hey 包含在仍然作为同一个对象中。由于 x 指的是整数,它仍然是旧对象,所以 1 和 y 也保持为同一个对象,但是该对象是一个列表,它的第一个元素现在指的是新的 int 对象,女巫是 4

    【讨论】:

    猜你喜欢
    • 2013-02-15
    • 2019-06-16
    • 2020-07-09
    • 1970-01-01
    • 1970-01-01
    • 2016-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多