【问题标题】:Passing by assignment: Python通过赋值传递:Python
【发布时间】:2020-12-04 14:53:17
【问题描述】:

我想了解以下代码变体:

a = [1, 2, 3]
b = a
b.append(4)
b = ['a', 'b']
print(a, b)

我的理解是变量a 指的是一个对象,该对象在内存中的某个位置包含列表[1,2,3],而b 现在指的是a 所指的同一个对象,并且通过我们在技术上附加在非 b 中的那个链接。

输出:[1, 2, 3, 4] ['a', 'b']

我稍微更新了代码:

a = [1, 2, 3]
b = ['a', 'b']
b = a
b.append(4)
print(a, b)

我的理解:b 现在指的是两个对象,第一个列表['a','b'] 和第二个列表(a 最初指的是)[1,2,3] 通过第三行b = a

输出:[1, 2, 3, 4] [1, 2, 3, 4]

最后一个代码变体:

a = [1, 2, 3]
b = ['a', 'b']
b = a
b.append(4)
a.append(10)
print(a, b)

根据我目前的理解,我认为第 3 行 b = a 上的链接仅提供 b 引用多个对象(它是自己的和 a 的)和 a 的能力应该已经只引用一个对象[1,2,3],所以预期的输出应该是:[1,2,3,4,10] [1,2,3,4]

实际输出:[1, 2, 3, 4, 10] [1, 2, 3, 4, 10]

那么第 3 行 b = a 上的分配是否像双向链接? a 还创建了对b 对象的引用?

如果我错了,我希望有人可以为我消除这种困惑并纠正我的想法。 谢谢。

【问题讨论】:

  • 变量 a 和变量 b 引用同一个列表。如果您更改其中一个,另一个也会收到这些更改。如果要复制列表,请使用 new_list = list.copy() 这也可能有帮助:programiz.com/python-programming/methods/list/copy
  • 你为什么把事情搞得这么复杂?在b = aab 之后是同一个对象,仅此而已。
  • “我们在技术上附加了 a 而非 b。”不。变量指的是对象。两个变量都指向同一个对象,您将 附加到该对象。您不会附加到变量。 “我的理解:b 现在指的是两个对象”好吧,不是同时。它一开始指的是一个对象,后来指的是另一个对象。阅读以下内容:nedbatchelder.com/text/names.html
  • 注意,这与“通过赋值传递”无关,它指的是一种评估策略,它与如何以及何时评估函数参数有关,而不是像这样的简单分配。
  • "根据我目前的理解,我认为第 3 行 b = a 上的链接只给了 b 引用多个对象(它自己的和 a 的)和“不”的能力。 变量一次只能引用一个对象。我认为这让你感到困惑。

标签: python pass-by-reference variable-assignment


【解决方案1】:

我的理解: b 现在指的是两个对象, . . .

这是不正确的。一个名称不能同时与给定范围内的多个对象关联。

b = aba 关联的对象相关联。在该行执行后,将不会引用 ['a', 'b'],并且该列表应该可以进行垃圾回收,因为它不能再被使用。

【讨论】:

    【解决方案2】:

    不要把对象想象成指针,我认为这是你困惑的根源。不是“b 指向 a”或“a 指向 b”,而是与 绑定 到一个对象有关。我认为查看id 会很有用

    >>> a = [1, 2, 3]
    >>> id(a)
    1833964774216
    >>> b = a
    >>> id(b)
    1833964774216
    

    在这种情况下,ab 都绑定到该列表。因此,列出1833964774216 的任何突变都将反映在两个对象中。但我可以重新分配(或重新绑定)到一个完全不同的对象

    >>> b = [4, 5, 6]
    >>> id(b)
    1833965089992
    >>> b
    [4, 5, 6]
    

    这对a 没有任何影响,因为它仍然绑定到原始列表

    >>> a
    [1, 2, 3]
    >>> id(a)
    1833964774216
    

    【讨论】:

      【解决方案3】:

      让我们了解名称和对象之间的区别。在您的情况下,a 和 b 是名称,分配给 a 和 b 的列表“[1,2,3]”是对象。最初 a = [1,2,3] 并且在将 a 分配给 b 之后,即 b=a,在这种情况下,a 和 b 都绑定到同一个列表对象。这意味着您可以使用名称 a 或 b 更改该列表对象的值。

      这可以通过将分配给 a 的列表复制到 b 来解决,

      b = a.copy()

      这将创建分配给 b 的同一对象的副本

      【讨论】:

        猜你喜欢
        • 2018-01-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-30
        • 1970-01-01
        相关资源
        最近更新 更多