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

Mar*_*rco 115 python list

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

a=b=c=[0,3,5]
a[0]=1
print(a)
print(b)
print(c)
Run Code Online (Sandbox Code Playgroud)

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

那是对的吗?我应该用什么来进行多项任务?有什么不同?

d=e=f=3
e=4
print('f:',f)
print('e:',e)
Run Code Online (Sandbox Code Playgroud)

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

aba*_*ert 252

如果你是从C/Java /等语言来到Python.家庭,它可以帮助你停止思考a作为一个"变量",并开始将其视为"名称".

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

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

如果你给Notorious B.I.G.一个热狗,*Biggie SmallsChris Wallace有一个热狗.如果将第一个元素更改a为1,则b和的第一个元素为c1.

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

>>> a=b=c=[0,3,5]
>>> a is b
True
Run Code Online (Sandbox Code Playgroud)

然后你问:

有什么不同?

d=e=f=3
e=4
print('f:',f)
print('e:',e)
Run Code Online (Sandbox Code Playgroud)

在这里,您将名称重新绑定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
Run Code Online (Sandbox Code Playgroud)

请注意,a[0]已从4297261120更改为4297261216 - 现在它是不同值的名称.而b[0]现在也是相同的新值的名称.那是因为a并且b仍在命名同一个对象.


在封面下,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]:您有三个相同值的名称.

但在这种情况下,值是a int,ints是不可变的.在这两种情况下,你可以重新绑定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岁(至少直到她被克尔斯滕·邓斯特取代).


*警告:不要给Notorious BIG一个热狗.午夜之后,不应该给Gangsta说唱僵尸喂食.

  • @user570826:“10”是不可变的——这意味着无法更新该值,所以你的问题没有意义。您可以将“b”指向不同的值,但这样做对“a”和“c”没有影响,它们仍然指向原始值。列表的区别在于它们是可变的,例如,您可以“追加”到列表,或“lst[0] = 3”,这将更新值,该值通过该值的所有名称可见。 (3认同)

Jim*_*ane 53

咳嗽

>>> 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'}
>>> 
Run Code Online (Sandbox Code Playgroud)

  • 恕我直言,这实际上回答了我应该用于多项任务的OP的第一个关键问题,而上面提到的更高评分和更大脑的答案却没有. (7认同)
  • 或者,如果你真的想要额外的可读性,那么不带括号的 `a,b,c = 1,2,3` 在 Python 2 或 3 中也可以工作。 (6认同)

Pet*_*per 14

是的,这是预期的行为.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
Run Code Online (Sandbox Code Playgroud)

Python中的赋值语句不复制对象 - 它们将名称绑定到对象,并且对象可以包含您设置的标签.在第一次编辑中,更改[0],您将更新a,b和c都引用的单个列表中的一个元素.在你的第二个,改变e,你将e切换为另一个对象的标签(4而不是3).


Ori*_*eri 12

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

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

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

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

a = b =  5 
Run Code Online (Sandbox Code Playgroud)

这意味着a和b指向内存中包含值5的相同地址,但是当你这样做时:

a = 6
Run Code Online (Sandbox Code Playgroud)

它不会影响b,因为a现在指向包含6的另一个内存位置,b仍然指向包含5的内存地址.

但是,当你这样做时:

a = b = [1,2,3]
Run Code Online (Sandbox Code Playgroud)

a和b再次指向同一位置,但不同之处在于,如果更改其中一个列表值:

a[0] = 2
Run Code Online (Sandbox Code Playgroud)

它改变了a所指向的内存值,但a仍然指向与b相同的地址,因此b也会发生变化.

  • 这极具误导性.指针在Python级别肯定不可见,并且四个主要实现中至少有两个(PyPy和Jython)甚至在实现中也不使用它们. (6认同)
  • 不.在Python的一个实现中(CPython),每个变量都是一个指向`PyObject`的指针.在PyPy或Jython等其他实现中并非如此.(事实上​​,它甚至不清楚它是如何真实的,因为这些实现的语言甚至没有指针.) (4认同)

jur*_*eza 9

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

>>> a = b = c = [0, 3, 5]
>>> print(id(a), id(b), id(c))
46268488 46268488 46268488
Run Code Online (Sandbox Code Playgroud)

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

>>> 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]
Run Code Online (Sandbox Code Playgroud)

如果你指定一个新的列表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]
Run Code Online (Sandbox Code Playgroud)

整数是不可变的,因此您无法在不创建新对象的情况下更改值:

>>> 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
Run Code Online (Sandbox Code Playgroud)


Nic*_*rns 6

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

 'a' is the same as 'b', is the same as 'c' and they are all [1, 2, 3]
Run Code Online (Sandbox Code Playgroud)

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

a, b, c = [1, 2, 3]

print(a)
--> 1
print(b)
--> 2
print(c)
--> 3
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助!