Python将多个variables分配给相同的值? 列表行为

我试图使用多个赋值,如下所示初始化variables,但我被行为混淆了,我期望重新分配值列表,我的意思是b [0]和c [0]等于0。

a=b=c=[0,3,5] a[0]=1 print(a) print(b) print(c) 

结果是:[1,3,5] [1,3,5] [1,3,5]

那是对的吗? 我应该使用多重任务? 有什么不同呢?

 d=e=f=3 e=4 print('f:',f) print('e:',e) 

结果:('f:',3)('e:',4)

如果你是来自C / Java /等语言的Python。 家庭,它可能会帮助你停止把一个“variables”看作一个“variables”,并开始把它想象成一个“名字”。

abc不是具有相同值的不同variables; 他们是不同的名称为相同的相同的价值。 variables有types,身份,地址和类似的东西。

名称没有任何的。 ,当然,你可以有很多相同的值的名称。

如果你给Notorious BIG一个热狗, Biggie SmallsChris Wallace有一个热狗。 如果将a的第一个元素更改为1,则bc的第一个元素为1。

如果您想知道两个名称是否命名同一个对象,请使用is运算符:

 >>> a=b=c=[0,3,5] >>> a is b True 

然后你问:

有什么不同呢?

 d=e=f=3 e=4 print('f:',f) print('e:',e) 

在这里,你重新命名为4的名字e 。 这不会以任何方式影响名称df

在以前的版本中,您分配给a[0] ,而不是分配给。 所以,从a[0]的angular度来看,你正在重新设定a[0] ,但是从a的angular度来看,你正在改变它。

你可以使用id函数,这个函数给你一些代表对象身份的唯一数字,来确切地知道哪个对象是什么,哪怕is不能帮助:

 >>> a=b=c=[0,3,5] >>> id(a) 4473392520 >>> id(b) 4473392520 >>> id(a[0]) 4297261120 >>> id(b[0]) 4297261120 >>> a[0] = 1 >>> id(a) 4473392520 >>> id(b) 4473392520 >>> id(a[0]) 4297261216 >>> id(b[0]) 4297261216 

请注意, a[0]已经从4297261120更改为4297261216,现在它是一个不同值的名称。 而b[0]现在也是同样的新值的名字。 那是因为ab仍然命名同一个对象。


在封面下, a[0]=1实际上是在列表对象上调用一个方法。 (这相当于a.__setitem__(0, 1) 。所以,这根本就不是重新绑定的东西。 这就像调用my_object.set_something(1) 。 当然,为了实现这个方法,对象可能重新绑定一个实例属性,但这不是什么重要的事情; 重要的是你不分配任何东西,你只是改变对象。 而且a[0]=1


user570826问:

如果我们有, a = b = c = 10

这与a = b = c = [1, 2, 3]情况完全相同:对于相同的值,您有三个名称。

但在这种情况下,该值是一个int ,而int s是不可变的。 在这两种情况下,你都可以重新绑定a不同的值(例如, a = "Now I'm a string!" ),但是不会影响原来的值, bc仍然是名字。 不同之处在于,通过执行例如a.append(4) ,可以将值[1, 2, 3]更改为[1, 2, 3, 4] 。 因为这实际上改变了bc的名字, b现在变成b [1, 2, 3, 4] 。 没有办法将价值10变成其他任何东西。 10永远是10,就像克劳迪亚一样,吸血鬼永远是5(至less在她被克尔斯滕·邓斯特(Kirsten Dunst)取代之前)。


*警告:不要给臭名昭着的大热狗。 匪帮说唱僵尸绝不应该在午夜后喂食。

咳嗽

 >>> a,b,c = (1,2,3) >>> a 1 >>> b 2 >>> c 3 >>> a,b,c = ({'test':'a'},{'test':'b'},{'test':'c'}) >>> a {'test': 'a'} >>> b {'test': 'b'} >>> c {'test': 'c'} >>> 

是的,这是预期的行为。 a,b和c都被设置为相同列表的标签。 如果你想要三个不同的列表,你需要分别分配它们。 您可以重复显式列表,也可以使用多种方法之一来复制列表:

 b = a[:] # this does a shallow copy, which is good enough for this case import copy c = copy.deepcopy(a) # this does a deep copy, which matters if the list contains mutable objects 

Python中的赋值语句不会复制对象 – 它们将名称绑定到对象,并且对象可以具有与您设置的一样多的标签。 在你的第一个编辑中,改变一个[0],你正在更新a,b和c全部引用的单个列表中的一个元素。 在你的第二,改变e,你切换e是一个不同的对象(4而不是3)的标签。

在python中,一切都是一个对象,也是“简单”的variablestypes(int,float等)。

当你改变一个variables值时,你实际上改变了它的指针 ,如果你比较两个variables,它会比较它们的指针 。 (要清楚的是,指针是存储variables的物理计算机内存中的地址)。

因此,当您更改内部variables值时,您将更改其内存中的值,并且会影响指向此地址的所有variables。

举个例子,当你这样做的时候:

 a = b = 5 

这意味着a和b指向内存中包含值5的相同地址,但是当您执行以下操作时:

 a = 6 

这不会影响b,因为a现在指向包含6的另一个存储器位置,而b仍然指向包含5的存储器地址。

但是,当你这样做:

 a = b = [1,2,3] 

a和b再次指向相同的位置,但区别在于,如果更改列表值之一:

 a[0] = 2 

它改变了a指向的内存的值,但是a仍指向与b相同的地址,因此b也改变了。

您可以使用id(name)来检查两个名称是否代表同一个对象:

 >>> a = b = c = [0, 3, 5] >>> print(id(a), id(b), id(c)) 46268488 46268488 46268488 

列表是可变的; 这意味着您可以在不创build新对象的情况下更改该值。 但是,这取决于您如何更改值:

 >>> a[0] = 1 >>> print(id(a), id(b), id(c)) 46268488 46268488 46268488 >>> print(a, b, c) [1, 3, 5] [1, 3, 5] [1, 3, 5] 

如果你给a分配一个新的列表,那么它的id将会改变,所以它不会影响bc的值:

 >>> a = [1, 8, 5] >>> print(id(a), id(b), id(c)) 139423880 46268488 46268488 >>> print(a, b, c) [1, 8, 5] [1, 3, 5] [1, 3, 5] 

整数是不可变的,所以不能在不创build新对象的情况下更改值:

 >>> x = y = z = 1 >>> print(id(x), id(y), id(z)) 507081216 507081216 507081216 >>> x = 2 >>> print(id(x), id(y), id(z)) 507081248 507081216 507081216 >>> print(x, y, z) 2 1 1 

在你的第一个例子中, a = b = c = [1, 2, 3]你真的在说:

  'a' is the same as 'b', is the same as 'c' and they are all [1, 2, 3] 

如果你想设置'a'等于1,'b'等于'2'和'c'等于3,试试这个:

 a, b, c = [1, 2, 3] print(a) --> 1 print(b) --> 2 print(c) --> 3 

希望这可以帮助!

你需要的是这样的:

 a, b, c = [0,3,5] # Unpack the list, now a, b, and c are ints a = 1 # `a` did equal 0, not [0,3,5] print(a) print(b) print(c) 

谢谢你的澄清。

那些我需要的代码可以是这样的:

 #test aux=[[0 for n in range(3)] for i in range(4)] print('aux:',aux) #initialization a,b,c,d=[[0 for n in range(3)] for i in range(4)] #changing values a[0]=1 d[2]=5 print('a:',a) print('b:',b) print('c:',c) print('d:',d) 

结果:('aux:',[[0,0,0],[0,0,0],[0,0,0],[0,0,0]])('a:',[1 ,0,0])('b:',[0,0,0])('c:',[0,0,0])('d:',[0,0,5])

问候

简而言之,在第一种情况下,您将多个名称分配给一个list 。 内存中只创build一个列表副本,所有名称都指向该位置。 所以使用任何名称来更改列表实际上都会修改内存中的列表。

在第二种情况下,将在内存中创build多个相同值的副本。 所以每个副本是相互独立的。