Python引用如何工作?

时间:2012-03-15 17:15:49

标签: python reference pass-by-reference pass-by-value

我对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模块的deepcopycopy来制作对象副本?

请澄清。

3 个答案:

答案 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在解释Py​​thon内部工作方式方面表现出色,我不再重复了。

由于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:]等等。