python中的可变对象,副本和引用:如何检测麻烦?

时间:2013-11-15 18:26:33

标签: python reference pylint

请告诉我,如果我写的是正确的,如果你能在最后回答我的问题,我很高兴:

在python中分配给列表的变量是“引用”是否正确?同样适用于其他可变对象(如dict但不是元组)?

 a = [1,2,3]
 b = a
 def app(l,e):
     l += [ e ]

 app(a,5)
 print b

给出

 [1,2,3,5]

按值而不是按引用进行分配我必须使用deepcopy(来自副本)?

对我来说,问题是很容易引入错误而不关注这个!所以我说下面的

问题:是否有任何静态分析工具(如pylint或类似内容)可以为b = aapp(a,5)这样的行发出警告,告诉我我有潜力改变我的可变对象(列表,词典)?

谢谢

1 个答案:

答案 0 :(得分:0)

我在标题为"How do I pass a variable by reference?"和一些documentation的注释中阅读了该问题的链接。我相信普通的Python赋值和参数传递在技术上是按值传递的。但是,Python中的每个分配都会自动触发对对象的引用的创建。将import time import itertools char = "abc" counter = 0 x = [] for i in itertools.product(char, repeat=3): if ''.join(i)in x: break print(''.join(i)) counter += 1 char = char[::-1] x.append(''.join(i)) print('[+] Printed ' + str(counter)+ ' charecters.') print(char) 分配给a并将b作为参数传递给函数时,两行代码均触发了对对象a的引用的创建。然后将引用作为值传递给您的函数和a

不幸的是,我不知道有任何静态分析工具来警告您这些规则。我承认它们令人困惑,但是我知道的唯一解决方案是阅读文档并尝试使用简单的代码片段测试概念。您的代码是一个很好的示例,从中可以推断出Python的“规则”和潜在的问题。

Python文档中的一节指出:

  

“ ...参数是在Python中通过赋值传递的。由于赋值只是创建对对象的引用...”

进一步,根据对"How do I pass a variable by reference?"的回答,

  

如果将可变对象传递给方法,则该方法将获取对该对象的引用,并且可以对其进行更改,但如果您在该方法中重新绑定该引用,则外部范围对此一无所知,完成后,外部参考仍将指向原始对象。

在您的代码中,b看起来像方法中的“重新绑定”,不应修改l += e。但是,可以推断出Python对a的处理类似于+= [e]。 有人说,将“范围外”参数传递给的功能变量“重新绑定”不应影响传递的对象。尽管如此,.append(e)a修改了。因此可以推断出Python并未将l += [e]视为重新绑定。如果有新信息或更正,我鼓励其他人也通过评论添加链接。


注意: 在变量上使用Python += []函数可能会有所帮助。它显示了Python分配的整数,以在对象的“生命周期”中标识该对象。不幸的是,我不知道“终身”的确切定义。您最好问问别人或阅读文档:Python id() built-in function