I ran this code:
from collections import defaultdict
my_dict = defaultdict(lambda: 6, a=7)
print(repr(my_dict.get("a")))
print(repr(my_dict.get("b")))
print(repr(my_dict["b"]))
print(repr(my_dict.get("b")))
And the output was:
7
None
6
6
Ran it on: 3.13.1 (tags/v3.13.1:0671451, Dec 3 2024, 19:06:28) [MSC v.1942 64 bit (AMD64)]
.
As you can see, when I called my_dict.get("b")
before calling my_dict["b"]
, it returned None
. But after I called my_dict.get("b")
, it returned None
.
According to the docs, it should return the default computed by the factory only at the my_dict["b"]
call (__getitem__()
method), so why at the second call of: my_dict.get("b")
, it returned the computed value? Is it an expected value, or a bug?
I ran this code:
from collections import defaultdict
my_dict = defaultdict(lambda: 6, a=7)
print(repr(my_dict.get("a")))
print(repr(my_dict.get("b")))
print(repr(my_dict["b"]))
print(repr(my_dict.get("b")))
And the output was:
7
None
6
6
Ran it on: 3.13.1 (tags/v3.13.1:0671451, Dec 3 2024, 19:06:28) [MSC v.1942 64 bit (AMD64)]
.
As you can see, when I called my_dict.get("b")
before calling my_dict["b"]
, it returned None
. But after I called my_dict.get("b")
, it returned None
.
According to the docs, it should return the default computed by the factory only at the my_dict["b"]
call (__getitem__()
method), so why at the second call of: my_dict.get("b")
, it returned the computed value? Is it an expected value, or a bug?
1 Answer
Reset to default 6You are misunderstanding the API, this is explicitly addressed here the docs:
If
default_factory
is notNone
, it is called without arguments to provide a default value for the given key, this value is inserted in the dictionary for the key, and returned.
Emphasis added. So whenever you use mydict[x]
, and the default factory is used, it is internally set to that value. So therefore, if you use .get
, it simply retrieves the value that was set. This is how it's supposed to work.
IOW, for defaultdict
objects, __getitem__
is potentially a mutator method.
Another way of thinking about it is that it works like dict.setdefault
:
>>> mydict = {'a':1}
>>> mydict.setdefault('a', 42)
1
>>> mydict
{'a': 1}
>>> mydict.setdefault('b', 42)
42
>>> mydict
{'a': 1, 'b': 42}