如何在python中使变量不可变

Egy*_*din 5 python list

我的python脚本:

N = 2  # 2*2 matrix

a = N * [0]
b = a

print(b)  # prints [0, 0]

for i in range(N):
    a[i] = N * [0]

for i in range(N):
    for j in range(N):
        a[i][j] = 0

print(a)  # prints [[0, 0], [0, 0]]

print(b)  # prints [[0, 0], [0, 0]]
Run Code Online (Sandbox Code Playgroud)

为什么我的第二次print(b)改变?如何使它不变?我希望我b仍然包含[0, 0].

Nou*_*him 22

您对Python和变量赋值中的"对象"的理解是有缺陷的.

在像C这样的语言中,当你定义一个变量(比如说int a)时,会为这个变量分配和保留一小块内存,a现在就是这个内存区域.你可以进入这个区域,改变它,然后发现a"有一个"不同的价值.像a = 2(或其他变量a = b在哪里b)的语句获取右侧的值并将其写入为保留的内存位置a.现在您可以b根据需要进行修改,但a仍保留原始值.这就是为什么你可以做a++C之类的事情,这意味着"获取所a引用的值,添加一个并将其写回到同一位置".

在Python中,当您说x = [],创建一个新的列表对象并x使其"指向"该列表.现在,您所做的任何更改x都会影响此对象.假设您说y = x,您将获得对同一对象的另一个引用.改变y(或者x就此而言)将改变现在由x和指向的对象y.这就是你对B = A作业所做的.A当您访问此对象时,所有操作都将显示,B因为它们都指向同一个对象.从这个意义上讲,Python中的所有变量都像C中的指针一样.您也可以理解为什么我们++在Python中没有运算符,因为修改内存位置的内容就像在C中一样没有意义.

到目前为止,其他人建议的解决方案是建议您使用与指向的列表完全相同的内容创建一个新对象,AB指向此副本.这样,如果你修改A(或A指向什么),B(或B指向什么)将保持不变.

然而,这不会使B"不可变"(即不能在适当位置修改的对象).但是,我认为你只是错误地使用了这个词,并且意味着你不希望发生别名.

  • 所以没有办法使变量在python中不可变吗? (2认同)
  • 如果您在程序的生命周期中要求常量(我的意思是将值绑定到不能更改的符号),则没有,没有。有解决方法,但仅此而已。 (2认同)

hyn*_*nek 11

在python中分配对象时,可以分配引用(类似于C中的指针).

有几种方法可以绕过这个,但恕我直言最常用的是使用副本:

import copy
B = copy.copy(A)
Run Code Online (Sandbox Code Playgroud)

在某些情况下,您甚至可能想要使用deepcopy(),请查看文档以获取详细信息.


eum*_*iro 6

问题是:

B=A
Run Code Online (Sandbox Code Playgroud)

现在两者都指向同一个对象.

尝试:

B = [i for i in A]
Run Code Online (Sandbox Code Playgroud)

现在B是一个包含A中所有元素的新列表.或者简单地说:

B = A[:]
Run Code Online (Sandbox Code Playgroud)