如何在Python中创建变量的引用?

问题描述 投票:0回答:5

代码中:

y = 7
x = y
x = 8

现在,

y
将是7,x将是8。但实际上我想改变
y
。我可以指定
y
的参考并执行此操作吗?

例如,在 C++ 中可以实现相同的效果:

int y = 8;
int &x = y;
x = 9;

现在

y
x
都将为 9

python reference
5个回答
78
投票

不,你不能。正如其他答案指出的那样,您可以(ab?)使用可变对象的别名来实现类似的效果。然而,这与 C++ 引用不同,我想解释一下实际发生的情况以避免任何误解。

你看,在C++(和其他语言)中,变量(以及对象字段、集合中的条目等)是一个存储位置,你写入一个值(例如,整数、对象或指针)到那个位置。在此模型中,引用是(任何类型)存储位置的别名 - 当您分配给非引用变量时,您将一个值(即使它只是一个指针,它仍然是一个值)复制到存储位置;当您分配给引用时,您会复制到其他位置的存储位置。请注意,您无法更改引用本身 - 一旦它被绑定(并且必须在创建引用后立即更改),对它的所有分配都不会更改引用,而是更改所引用的内容。

在Python(和其他语言)中,变量(以及对象字段、集合中的条目等)只是一个名称。值位于“某处”(例如散布在整个堆上),并且变量引用(不是 C++ 引用的意义上的,更像是指针减去指针算术)。多个名称可以引用相同的值(这通常是一件好事)。 Python(和其他语言)将引用值所需的任何内容称为引用,尽管与 C++ 引用和引用传递等内容完全无关。分配给变量(或对象字段,或...)只是使其引用另一个值。整个存储位置模型不适用于 Python,程序员从不处理值的存储位置。他存储和洗牌的都是 Python 引用,而这些不是 Python 中的值,因此它们不能成为其他 Python 引用的目标。 所有这些都与值的可变性无关——例如,对于整数和列表来说是相同的。您不能使用引用其中任何一个的变量来覆盖它所指向的对象。您只能告诉对象修改其自身的一部分 - 例如,更改它包含的某些引用。

这是一个限制性更强的模型吗?也许吧,但大多数时候它已经足够强大了。如果不是,您可以解决它,可以使用像下面给出的自定义类,或者(等效的,但不太明显)单元素集合。

class Reference: def __init__(self, val): self._value = val # just refers to val, no copy def get(self): return self._value def set(self, val): self._value = val

这仍然不允许您为“常规”变量或对象字段添加别名,但您可以有多个变量引用同一个 
Reference

对象(可变单例集合替代方案也是如此)。您只需小心地始终使用

.get()
/
.set()
(或
[0]
)。
    


21
投票

如果您有一个列表(或任何其他可变对象),您可以通过改变 x 和 y 绑定到的对象来完成您想要的操作:

>>> x = [7] >>> y = x >>> y[0] = 8 >>> print x [8]

查看它在线运行:
ideone


8
投票

class Value(object): def __init__(self, value): self.value = value y = Value(7) x = y x.value = 8 print y.value

ideone


7
投票

在 python 中

x

y
只是对象的引用 所以
y = 7
表示 y 指向对象
7
x=y
意味着
x
也指向
7
,但由于
7
是不可变的,所以改变x的值只会改变对象
7
,而
y
仍然指向
7

>>> y = [7] >>> x = y >>> x[0] = 8 # here you're changing [7] not x or y, x & y are just references to [7] >>> y [8]



0
投票
weakref

模块。

对对象的弱引用不足以使对象保持活动状态:当对所指对象的唯一剩余引用是弱引用时,垃圾收集可以自由地销毁所指对象并将其内存重新用于其他用途。但是,在对象实际被销毁之前,即使没有强引用,弱引用也可能会返回该对象。

弱引用的主要用途是实现保存大对象的缓存或映射,其中不希望大对象仅仅因为它出现在缓存或映射中而保持活动状态。

© www.soinside.com 2019 - 2024. All rights reserved.