A classmate asked a question about overwriting the built-in class dict, and after some poking around I became even more uncertain.
Take the built-in dict. I can assign this variable:
>>> dict=5
>>> dict
5
Now I've lost access to dict (would this be shadowing like in C++ or is it different?) but I still have access to the class via builtins.dict. But I can overwrite that as well:
>>> __builtins__.dict = 6
>>> __builtins__.dict
6
But even doing this doesn't break the class itself:
>>> stillDict = {'key': 'value'}
>>> stillDict
{'key': 'value'}
So why does the class still "work" after I've shadowed it? How does the interpreter know I'm making a dictionary with this assignment, and how is the dictionary constructed since it obviously doesn't actually require __builtins__.dict
?
edit Taking this a bit further, from simeon's answer which says it's because I'm creating a dictionary literal ...
before overwriting, I can do this:
>>> a = dict()
>>> a.items
<built-in method items of dict object at 0x0000000002C97C08>
after overwriting dict and __builtins__.dict
, I can do this:
>>> b = {}
>>> b.items
<built-in method items of dict object at 0x000000000288FC88>
Which leads to a follow-on ... Both of these are still "dict objects", is the dict class just using a constructor to make a dict object? Why do I still have access to the built-in methods once I've shadowed the class?
{'key': 'value'}
is a dictionary literal so that continues to have the behaviour of producing a dictionary. Python doesn't need to look up what dict
means - it skips this step and directly generates byte code to construct a dictionary:
>>> def f(): {'a': 3}
>>> import dis
>>> dis.dis(f)
1 0 BUILD_MAP 1
3 LOAD_CONST 1 (3)
6 LOAD_CONST 2 ('a')
9 STORE_MAP
10 POP_TOP
11 LOAD_CONST 0 (None)
14 RETURN_VALUE
In the byte code it continues to use BUILD_MAP
as before (i.e., it builds a map / dictionary based on the code you've written).
The meaning of dict
has changed as you mentioned.
Regarding the follow-up question: you haven't shadowed the dictionary class / type - you've only changed the meaning of what dict
means. You cannot take the dictionary type away and Python produces it when using a dictionary literal (e.g., {}
).
Once you have an object of type dict
you have access to its methods (like items()
) - it's just that you've constructed it using syntax (which you can't influence) rather than a call to dict()
(which you can influence).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With