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'})

Why the value in queue changes when the value of 'a' is changed after adding? The tuple by itself is immutable but the dictionary present inside is mutable. But I couldn't understand why the queue should get altered?

Bharathwaaj
  • 2,627
  • 2
  • 22
  • 35

2 Answers2

2

In Python, objects are passed by reference. Some objects may appear to be passed as values (such as strings and integers), but that is because those objects are immutable (e.g. you can't change the value of the integer object 1).

So when you place a dictionary in the queue, it is the actual dictionary that will pop out the other other end rather than a copy.

You can use the dictionary's copy() method if you want a copy, but note that it will only give you a shallow copy of the dictionary: the keys and values in the copy will be the same objects and they may be mutable themselves.

James Henstridge
  • 42,244
  • 6
  • 132
  • 114
1

In Python, objects are neither passed 'by reference' nor 'by value'.

In your example, the name a is bound to the object (1, {'item': 'value'}).

The name q is bound to a queue object.

When q.put(a) is invoked, the object that the name a is bound to is "put in" the object that the name q is bound to, so that the names a and q[0] refer to the same object. So when you modify that object, you are modifying the object that BOTH a and q[0] are bound to (since they are bound to the same object).

Secondly, although a tuple is immutable, that doesn't mean that it cannot change. Although as a 'container' it is immutable and cannot change in itself, it can contain mutable objects, and therefore its contents can change.

Very useful and clear article here: https://jeffknupp.com/blog/2012/11/13/is-python-callbyvalue-or-callbyreference-neither/

andydavies
  • 3,081
  • 4
  • 29
  • 35