Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

dict.get() method returns a pointer

Let's say I have this code:

my_dict = {}
default_value = {'surname': '', 'age': 0}

# get info about john, or a default dict
item = my_dict.get('john', default_value)

# edit the data
item[surname] = 'smith'
item[age] = 68

my_dict['john'] = item

The problem becomes clear, if we now check the value of default_value:

>>> default_value
{'age': 68, 'surname': 'smith'}

It is obvious, that my_dict.get() did not return the value of default_value, but a pointer (?) to it.

The problem could be worked around by changing the code to:

item = my_dict.get('john', {'surname': '', 'age': 0})

but that doesn't seem to be a nice way to do it. Any ideas, comments?

like image 534
Armandas Avatar asked Aug 22 '11 21:08

Armandas


People also ask

Can you explain the dict get () function?

get() method is used in Python to retrieve a value from a dictionary. dict. get() returns None by default if the key you specify cannot be found. With this method, you can specify a second parameter that will return a custom default value if a key is not found.

What will be returned by dict items () method?

Python Dictionary items() Method The items() method returns a view object. The view object contains the key-value pairs of the dictionary, as tuples in a list. The view object will reflect any changes done to the dictionary, see example below.

Are Python dictionaries pointers?

You can only reference objects in Python. Lists, tuples, dictionaries, and all other data structures contain pointers.

What is dictionary get method in Python?

Python Dictionary get() Method The get() method returns the value of the item with the specified key.


1 Answers

item = my_dict.get('john', default_value.copy())

You're always passing a reference in Python.

This doesn't matter for immutable objects like str, int, tuple, etc. since you can't change them, only point a name at a different object, but it does for mutable objects like list, set, and dict. You need to get used to this and always keep it in mind.

Edit: Zach Bloom and Jonathan Sternberg both point out methods you can use to avoid the call to copy on every lookup. You should use either the defaultdict method, something like Jonathan's first method, or:

def my_dict_get(key):
    try:
        item = my_dict[key]
    except KeyError:
        item = default_value.copy()

This will be faster than if when the key nearly always already exists in my_dict, if the dict is large. You don't have to wrap it in a function but you probably don't want those four lines every time you access my_dict.

See Jonathan's answer for timings with a small dict. The get method performs poorly at all sizes I tested, but the try method does better at large sizes.

like image 106
agf Avatar answered Oct 05 '22 09:10

agf