我对Python引用感到困惑。请考虑以下示例:
我的任务:编辑列表中的每个元素
d = { 'm': [1,2,3] }
m = d['m']
m = m[1:] # m changes its reference to the new sliced list, edits m but not d (I wanted to change d)
类似地:
d = { 'm': [1,2,3] }
m = d['m']
m = m[0] # As per python referencing, m should be pointing to d['m'] and should have edited d
在python中,一切都是通过引用,然后什么时候创建一个新对象?
我们是否始终需要来自copy
模块的deepcopy
和copy
来制作对象副本?
请澄清。
答案 0 :(得分:12)
在Python中,变量不是包含东西的框,而是指向对象的名称。在您的代码中:
d = { 'm': [1,2,3] }
- >将名称d
绑定到字典m = d['m']
- >将名称m
绑定到列表m = m[1:]
- >将名称m
绑定到另一个列表您的第三行不会更改m
本身,而是m
指向的内容。
要编辑列表中的元素,您可以执行以下操作:
m = d['m']
for i, item in enumerate(m):
result = do_something_with(item)
m[i] = result
答案 1 :(得分:5)
Ethan Furman在解释Python内部工作方式方面表现出色,我不再重复了。
由于m
确实代表字典中的列表,因此您可以对其进行修改。你无法将它重新分配给新的东西,当你使用=
将它等同于一个新的切片时会发生这种情况。
要切掉列表的第一个元素,例如:
>>> m[0:1] = []
>>> d
{'m': [2, 3]}
答案 2 :(得分:4)
在python中,一切都通过引用
在Python中,所有 都是引用,引用会按值传递。
如果您想使用这些条款。但这些条款使事情变得更难理解。
更简单:在Python中,变量是对象的名称。 =
用于更改名称所指的对象。左侧可以指现有对象的一部分,在这种情况下,通过替换该部分来改变整个对象。这是因为对象反过来并不真正包含它的部分,而是包含更多的名称,这可能会导致开始引用不同的东西。
然后什么时候创建了一个新对象?
对象是在创建时创建的(通过使用类构造函数,或者在具有文字表示的内置类型的情况下,通过键入文字)。我不明白这与你的其他问题有什么关系。
m = m[1:] # m changes its reference to the new sliced list
是的,当然。现在m
指的是评估m[1:]
的结果。
edits m but not d (I wanted to change d)
是的,当然。为什么会更改d
?这不是某种魔术,只是评估d['m']
的结果。两条线上完全相同。
让我们看一个更简单的例子。
m = 1
m = 2
这会导致1
成为2
吗?不,当然不。整数是不可变的。但是同样的事情正在发生:m
被命名为一件事,然后命名另一件事。
或者,另一种方式:如果“引用”按照您期望的方式工作,那么行m = m[1:]
将是递归的。您希望它表示“在您看到m
的任何地方,将其视为m[1:]
”。那么,在这种情况下,m[1:]
实际上意味着m[1:][1:]
,这意味着m[1:][1:][1:]
等等。