为什么在使用=运算符时python列表会像这样

时间:2018-11-03 19:57:19

标签: python list

下面的代码为何:

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

更改后的列表b是否会打印?[3,2,3]。 还有为什么这是正确的,但是下面的代码是

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

打印[1、2、3] [0、0、0] ??这似乎不一致。如果第一个代码为true,那么第二个代码是否应该打印[0,0,0] [0,0,0]?有人可以为此提供解释吗?

1 个答案:

答案 0 :(得分:0)

在python中,有两种类型的数据... 可变不可变。数字,字符串,布尔值,元组和其他简单类型是不可变的。字典,列表,集合,对象,类和其他复杂类型是可变的。

当你说:

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

您已经在内存中创建了一个可变列表,分配了a指向它,然后分配了b指向它。内存中是同一件事。

因此,当您对其进行突变(修改)时:

b[0] = 3

它是[0]指向相同存储位置的值的索引b的修改(变异)。

但是,当您更换它时:

b = [0,0,0]

它将在内存中创建一个新的可变列表,并分配b指向它。


签出id()功能。它将告诉您任何变量的“地址”。您可以使用id(varname)查看哪些名称指向相同的存储位置。


奖金::python中的每个值都是通过引用传递的……这意味着,当您将其分配给变量时,它只会导致该变量指向它在内存中的那个值。具有不可变类型可以使python为常见的不可变类型“重用”相同的内存位置。

在解释器启动时考虑一些常见的值:

>>> import sys
>>> sys.getrefcount('abc')
68
>>> sys.getrefcount(100)
110
>>> sys.getrefcount(2)
6471

但是,绝对不存在的值将返回2。这与以下事实有关:在调用sys.getrefcount

时使用了对该值的几个引用
>>> sys.getrefcount('nope not me.  I am definitely not here already.')
2

请注意,空元组有很多引用:

>>> sys.getrefcount(tuple())
34571

但是空白列表没有其他引用:

>>> sys.getrefcount(list())
1

这是为什么?。由于元组是不可变的,因此可以在任意数量的变量中共享该值。但是,列表是可变的,因此绝对不能在任意变量之间共享它们,否则对一个变量的更改将影响其他变量。

顺便说一句,这也是为什么您绝不能使用可变类型作为函数的默认参数值的原因。考虑一下这个无害的小功能:

>>> def foo(value=[]):
...     value.append(1)
...     print(value)
...
...

调用它时,您可能希望打印[1] ...

>>> foo()
[1]

但是,当您再次调用它时,您可能会遇到问题。不会期望得到[1,1]……

>>> foo()
[1, 1]

然后继续...

>>> foo()
[1, 1, 1]

>>> foo()
[1, 1, 1, 1]

这是为什么?因为函数的默认参数在函数定义期间(而不是在函数运行时)评估一次。这样,如果您将可变值用作默认参数值,则该值将被您困住,因为该函数被多次调用,会以意想不到的方式发生变异。

正确的方法是:

>>> def foo(value=None):
...     if value is None:
...         value = []
...     value.append(1)
...     print(value)
...
...
>>>
>>> foo()
[1]
>>> foo()
[1]
>>> foo()
[1]