这些变量赋值按我的预期工作:
>>> a = 3
>>> b = a
>>> print(a, b)
(3, 3)
>>> b=4
>>> print(a, b)
(3, 4)
但是,这些分配的行为不同:
>>> class number():
... def __init__(self, name, number):
... self.name = name
... self.number = number
...
>>> c = number("one", 1)
>>> d = c
>>> print(c.number, d.number)
(1, 1)
>>> d.number = 2
>>> print(c.number, d.number)
(2, 2)
为什么 c
和 d
一样,不像 (a, b)
例子?如何在 (c, d)
类示例中的 (a, b)
中执行类似操作?即复制对象,然后更改其中的一部分(不会影响我借用属性的对象)?
最佳答案
这些行:
c = number("one", 1)
d = c
...有效:
- 创建
number
的新实例并将其分配给c
- 分配名为
c
的现有引用到一个新变量d
您没有更改或修改任何关于 c
的内容; d
是指向同一个实例的另一个名称。
如果不克隆实例或创建新实例,您将无法执行与原始 int 行为类似的任何操作。
纠正一点信息,上面的解释是rather simplified有点不完整in its nature ,尽管它主要描述了 10,000 英尺处发生的情况。
为了仔细观察,我们必须了解 Python 的变量或“名称”,以及它们如何与该程序交互。
如上所述,you have the notion of "names" and "bindings" ,这很容易理解:
a = 3
b = a
在这种情况下,a
是一个名字,b
绑定(bind)到 a
.我们没有修改或更改关于 a
的任何内容.
如前所述,Python 中有两种类型的数据:可变的和不可变的。指向不可变数据的名称(例如原语和元组)可以重新分配而不会对其上存在的任何其他绑定(bind)产生任何不良影响,因为相对于绑定(bind)没有状态发生变化。
这就是为什么这次重新分配符合我们的预期:
print(a, b)
b = 4
print(a, b)
b = 4
的结果是b
现在指向一个整数的新副本,值 4。
回想一下,我确实提到元组是不可变数据。您不能更改元组中特定实体的绑定(bind)...
t = ('foo', 'bar')
t[0] = 'baz' # illegal
...但是您可以将可变数据结构作为这些绑定(bind)的一部分。
t = ([1, 2, 3], 'bar')
t[0].append([4, 5, 6]) # ([1, 2, 3, [4, 5, 6]], 'bar')
那么我们的例子在哪里呢?
c = number("one", 1)
d = c
number
是一个 可变 类型,被命名为 c
, 并且它的值可以在多个不同的绑定(bind)之间随意更改 c
.
实际上,我们有一个名字和一个名字的绑定(bind):
- 我们有一个
number
的新实例并通过名称c
引用它. - 绑定(bind)引用
c
换个名字d
.
同样,c
没有任何变化, 但可以通过其他名称引用。
与不可变数据不同,当我们重新分配 d.number
的值时,我们正在重新分配与 c
相同的绑定(bind)意识到:
>>> id(d.number)
36696408
>>> id(c.number)
36696408
这就是您需要新实例或副本的原因。您必须引用 number
的另一个实例.使用这种简单的绑定(bind),您将无法做到这一点。
from copy import copy
c = number("one", 1)
d = copy(c)
id(c) # 140539175695784
id(d) # 140539175695856
关于python - 为什么变量 = 对象不像变量 = 数字那样工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29926485/