>"For instance `a = foo.bar.baz` in Python involves 3 hash gets (local scope, foo scope, then bar scope), and a single set operation (local scope)"
Can you explain where exactly and why a set operation is performed? Thanks.
Can you explain where exactly and why a set operation is performed? Thanks.
Basically `a = 1` is syntactic sugar for `locals()['a'] = 1`
>>> a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined
>>> locals()['a'] = 113
>>> a
113
>>>
One interesting side-effect of this is you can assign names that are not valid Python syntax explicitly.For example:
>>> locals()['foo-bar'] = 1
>>> locals()['foo-bar']
1
>>> foo-bar
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'foo' is not defined
>>>
The name `foo-bar` can't be literally referenced, because the interpreter attempts to interpret it as the subtraction operation `foo - bar`.Global variables use a dictionary, however. The disassembly actually looks similar for both.
def f():
a = 5
locals()['a'] = 6
print(a) # 5
Inside a function, accesses/writes of locals use an internal array of local variables, to skip dicts. Same with constants. See:https://github.com/python/cpython/blob/master/Python/ceval.c...
1 0 LOAD_NAME 0 (foo)
2 LOAD_ATTR 1 (bar)
4 LOAD_ATTR 2 (baz)
6 STORE_NAME 3 (a)
8 LOAD_CONST 0 (None)
10 RETURN_VALUE
The CPython implementation is a stack-based virtual machine. The first instruction here, LOAD_NAME, pushes co_names['foo'] (basically, whatever 'foo' is bound to in local scope) to the top of the stack. That's at least one hash table lookup, since the scope is a hash table mapping names to values. Then LOAD_ATTR replaces the top-of-stack value with the value of its 'bar' attribute. That's another hash table lookup, since attributes are a hash table mapping names to values. Then another LOAD_ATTR to get to 'baz', that's another hash table lookup. Then STORE_NAME binds the value at the top of the stack to the name given as an argument ('a'). That's an insert or update of a hash table.So, the expression 'a = foo.bar.baz' involves at least three hash table lookups and one insert or update.
`a = ... ` can be thought of as `locals()["a"] = ...`
(although you can should not actually modify the local variables this way)