且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

dict.get()方法返回一个指针

更新时间:2023-02-20 09:38:35

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

您始终在Python中传递引用



这对于不可变的对象(如 str int tuple 等,因为您无法更改它们,只能在不同的对象上指定一个名称,但它对于可变对象(如 list set dict 。您需要习惯这一点,并始终牢记这一点。



编辑: Zach Bloom和Jonathan Sternberg都指出可以使用的方法以避免在每次查找时调用复制。您应该使用 defaultdict 方法,像Jonathan的第一个方法,或者:

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

如果如果密钥几乎总是存在于 my_dict 如果 dict 很大。您不必将其包装在一个功能中,但是每次访问 my_dict 时,您可能不希望这四行。



请参阅Jonathan的答案,其中有一个小的 dict get 方法在我测试的所有大小上执行得不好,但是 try >

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?

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.