【问题标题】:Python: list of objects vs list of integers behaviorPython:对象列表与整数列表行为
【发布时间】:2018-09-01 22:08:46
【问题描述】:

我是这门语言的新手,对 Python 中的引用有点困惑。

考虑这段代码:

class A:
  def __init__(self, x):
    self.x = x

a = A(3)
v=[a]
print(f'obj before: v[0].x={v[0].x}')
a.x = a.x + 1
print(f'obj after:  v[0].x={v[0].x}')

b = 3
w=[b]
print(f'int before: w[0]={w[0]}')
b = b + 1
print(f'int after:  w[0]={w[0]}')

====================== 输出:

obj before: v[0].x=3
obj after:  v[0].x=4
int before: w[0]=3
int after:  w[0]=3

为什么 obj 和 int 版本的代码工作方式不同?

【问题讨论】:

    标签: python list reference


    【解决方案1】:

    a = A(3)

    变量a指向一个对象。

    v=[a]

    v的第一个元素指向同一个对象。

    a.x = a.x + 1

    更改对象的属性“x”。

    v 仍然包含相同的对象,但其属性已更改。

    b = 3

    变量b指向对象3。

    w=[b]

    w的第一个元素也指向对象3。

    b = b + 1

    b 现在指向当您对对象 3 和对象 1(即对象 4)执行加法时得到的结果。

    w 仍然包含对象 3。您从未更改此对象的任何属性,也从未更改 w 的第一个元素指向的位置。

    【讨论】:

    • 谢谢,所以如果我希望 v 的元素不受影响,那么我想我应该像这样在 v 中放置一个 a 的克隆:v=[copy.deepcopy(a)]。但对我来说它看起来不是很整洁。
    • 是的,或者只是以相同的方式(A(3))构造相同的对象并将其放入其中。调用一个类会创建一个不同的新对象。
    【解决方案2】:

    当你这样做时,你正在修改对象a

    a.x = a.x + 1
    

    当您这样做时,您正在更改 b 所指的变量:

    b = b + 1
    

    也就是说,上面代码中bx有很大的区别:b是一个变量,xa的一个属性。

    给变量赋值不会修改任何对象,因此只会影响赋值给的变量*,而设置属性的值会修改对象,可见在任何引用该对象的变量中。


    * 影响垃圾收集器的引用计数也有变化,但现在不相关。

    【讨论】:

    • 感谢您的帮助,您实际上说的和 Denziloe 一样
    猜你喜欢
    • 2019-08-04
    • 2017-03-27
    • 1970-01-01
    • 2020-10-06
    • 1970-01-01
    • 1970-01-01
    • 2021-10-12
    • 2013-04-05
    • 1970-01-01
    相关资源
    最近更新 更多