Python变量引用赋值

vij*_*iji 42 python reference

在代码中

y = 7
x = y    
x = 8
Run Code Online (Sandbox Code Playgroud)

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

例如,在C++中可以实现同样的目的,

int y = 8;
int &x = y;
x = 9;
Run Code Online (Sandbox Code Playgroud)

现在y&x都是9

小智 56

你不能.正如其他答案所指出的,你可以(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
Run Code Online (Sandbox Code Playgroud)

这仍然不允许您为"常规"变量或对象字段添加别名,但是您可以使用多个变量来引用同一个Reference对象(对于mutable-singleton-collection备选方案也是如此).你必须要小心,始终使用.get()/ .set()(或[0]).

  • 很好的解释,+1澄清它与可变性无关. (3认同)
  • @FadyHany我认为你可以将“你可以(ab?)使用别名”部分读作“你可以使用别名”或“你可以滥用别名”,这表明这种解决方法可能被一些开发人员认为是hacky 。 (3认同)

Mar*_*ers 17

不,Python没有此功能.

如果你有一个列表(或任何其他可变对象),你可以通过改变x和y绑定的对象来做你想要的事情:

>>> x = [7]
>>> y = x
>>> y[0] = 8
>>> print x
[8]
Run Code Online (Sandbox Code Playgroud)

看到它在线工作:ideone


glg*_*lgl 7

或者,您可以使用自制的容器。

class Value(object):
    def __init__(self, value): self.value = value

y = Value(7)
x = y
x.value = 8
print y.value
Run Code Online (Sandbox Code Playgroud)

ideone


Ash*_*ary 6

你应该使用一个可变对象.

在python中x,y它只是对象的引用,因此y = 7意味着y指向对象7. x=y意味着x也指向7,但是因为它7是不可变的,所以改变x的值只是改变了对象7y仍然指向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]
Run Code Online (Sandbox Code Playgroud)