2012-10-12 82 views
0
>>> import Queue 
>>> q = Queue.PriorityQueue() 
>>> a = (1, {'item': 'value'}) 
>>> q.put(a) 
>>> q.queue 
[(1, {'item': 'value'})] 
>>> a[1]['count'] = 1 
>>> q.queue 
[(1, {'count': 1, 'item': 'value'})] 
>>> q.get() 
(1, {'count': 1, 'item': 'value'}) 

为什么当'a'的值在添加后改变时,队列中的值会发生变化?这个元组本身是不可变的,但是里面的字典是可变的。但我不明白为什么队列应该改变?优先级队列和易变性

+0

检查'q.get(是了',你会发现它们都* *点到同一个元组。 – satoru

+0

这是对保存在'Queue'中的元组的引用,而不是它的副本。 – satoru

+0

运行'q.put(a)'时,通过引用将'a'传递给'q','a'是可变的。 – iMom0

回答

2

在Python中,对象通过引用传递。有些对象可能会作为值(如字符串和整数)传递,但这是因为这些对象是不可变的(例如,您无法更改整数对象1的值)。

因此,当你在队列中放置一个字典时,它会弹出另一个端点而不是副本的实际字典。

如果您想要一个副本,您可以使用字典的copy()方法,但请注意,它只会给您一个字典的浅表副本:副本中的键和值将是相同的对象,并且它们本身可以是可变的。

1

在Python中,对象既不是'通过引用'也不是'按值'传递。

在您的示例中,名称a绑定到对象(1, {'item': 'value'})

名称q绑定到队列对象。

当调用q.put(a),这个名字a势必是对象“放”,这个名字q结合了,所以这些名称aq[0]指向同一个对象的对象。因此,当您修改该对象时,您正在修改绑定两个对象(因为它们绑定到同一个对象)。其次,虽然一个元组是不可变的,但这并不意味着它不能改变。尽管作为一个'容器'它是不可变的,不能自己改变,但它可以包含可变对象,因此其内容可以改变。这里

非常有用的,清晰的文章:) https://jeffknupp.com/blog/2012/11/13/is-python-callbyvalue-or-callbyreference-neither/