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

时间:2013-05-02 22:31:19

标签: python list

我尝试使用多个赋值如下所示初始化变量,但我对行为感到困惑,我希望单独重新分配值列表,我的意思是b [0]和c [0]等于0。< / p>

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)

9 个答案:

答案 0 :(得分:227)

如果你是从C / Java /等语言来到Python。家人,它可以帮助你不再把a视为“变量”,并开始将其视为“名称”。

abc不是具有相同值的不同变量;对于相同的相同值,它们是不同的名称。变量有类型,身份,地址和各种类似的东西。

名称中没有任何名称。 当然可以,并且您可以为同一个值设置许多名称。

如果您给Notorious B.I.G.热狗,* 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)

在这里,您将名称e重新绑定到值4。这不会以任何方式影响名称df

在您之前的版本中,您分配的是a[0],而不是a。因此,从a[0]的角度来看,您正在重新定位a[0],但从a的角度来看,您就是在原地进行更改。

您可以使用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]的情况完全相同:您有三个相同值的名称。

但在这种情况下,值为intint是不可变的。在任何一种情况下,您都可以将a重新绑定到其他值(例如a = "Now I'm a string!"),但这不会影响原始值,bc仍会是...的名字。不同之处在于,对于列表,您可以通过执行[1, 2, 3]来将值[1, 2, 3, 4]更改为a.append(4);由于这实际上正在更改bc为其名称的值,b现在将为b [1, 2, 3, 4]。无法将值10更改为其他任何内容。 10永远是10,就像克劳迪娅一样,吸血鬼永远是5岁(至少直到她被克尔斯滕·邓斯特取代)。


*警告:不要给臭名昭着的B.I.G.一个热狗。匪徒说唱僵尸绝不应该在午夜后喂食。

答案 1 :(得分:42)

咳嗽咳嗽

>>> 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'}
>>> 

答案 2 :(得分:13)

是的,这是预期的行为。 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)。

答案 3 :(得分:11)

在python中,一切都是对象,也是“简单”变量类型(int,float等)。

当您更改变量值时,实际上会更改它的指针,如果您在两个变量之间进行比较,则会比较它们的指针。 (要清楚,指针是物理计算机内存中存储变量的地址)。

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

对于您的示例,当您这样做时:

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也会发生变化。

答案 4 :(得分:9)

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

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

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

>>> 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]

整数是不可变的,因此如果不创建新对象,则无法更改值:

>>> 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

答案 5 :(得分:5)

在您的第一个例子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

希望这有帮助!

答案 6 :(得分: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)

答案 7 :(得分:3)

简单地说,在第一种情况下,您要为list分配多个名称。在内存中只创建一个列表副本,所有名称都引用该位置。因此,使用任何名称更改列表实际上会修改内存中的列表。

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

答案 8 :(得分:2)

感谢大家的澄清。

执行我需要的代码可能是这样的:

#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])

此致