ah sorry. i did
import dis
dis.dis("a = foo.bar(b)")
which gave 1 0 LOAD_NAME 0 (foo)
2 LOAD_ATTR 1 (bar)
4 LOAD_NAME 2 (b)
6 CALL_FUNCTION 1
8 STORE_NAME 3 (a)
10 LOAD_CONST 0 (None)
12 RETURN_VALUE
Re:Python’s Weak Performance Matters
by tom_mellior on Thursday February 08, 2018 @04:17PM
(#16335674)
Ah, OK. Yes, those LOAD_NAMEs are slower than LOAD_FAST. If you put the code into a function, you get this:
>>> def f(foo, b):
... a = foo.bar(b)
...
>>> dis.dis(f)
2 0 LOAD_FAST 0 (foo)
3 LOAD_ATTR 0 (bar)
6 LOAD_FAST 1 (b)
9 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
12 STORE_FAST 2 (a)
15 LOAD_CONST 0 (None)
18 RETURN_VALUE
LOAD_FAST is the normal case for locals inside a function. Not sure off the top of my head where LOAD_NAME would be generated in normal usage (i.e. where you don't evaluate code from a string).Edit: Also, I'm talking about Python 3. Maybe you aren't.
So your code should be more like:
But this isn't a very good rendering of the thing because it doesn't show the many redundant reference count increment/decrement pairs every time you touch a variable.(Also, interpreter dispatch uses computed GOTOs instead of the plain switch on C compilers that support it.)