python - 为什么python列表在使用=运算符时会这样
问题描述
下面的代码怎么来的:
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]?? 这似乎不一致。如果第一个代码为真,那么第二个代码不应该打印 [0,0,0][0,0,0] 吗?有人可以为此提供解释吗?
解决方案
在 python 中有两种类型的数据... mutable和immutable。数字、字符串、布尔值、元组和其他简单类型是不可变的。字典、列表、集合、对象、类和其他复杂类型是可变的。
当你说:
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]
推荐阅读
- mysql - 如何计算数据库列结果并将它们分组以实现可管理的输出
- r - 使用 tidyquant 库中的 tq_get 函数创建 for 循环以在 R 中按州获取失业申请?[包括图像和代码]
- c++ - 如何用子类对象初始化超类类型的指针?
- flutter - 在 FadeInImage 中加载图像时如何获得通知?
- node.js - docker 容器中的服务器无法连接到另一个 docker 容器中的 postgres 数据库
- mongodb - Mongo Aggregation:计算具有和不具有值匹配的嵌套数组的不同帐户
- c# - 是否可以在不限制最大速度的情况下限制给定的 addForce?
- flutter - 如何更改列表视图中的背景颜色
- python - Django 模板。有什么方法可以将 {{ }} 嵌套在 {% %} 中?
- android - 如何从特定 Firebase 字段中检索数据?