Two O(1) operations can take very different times. Both instance attribute lookup (self.printMethod
) and local variables are O(1), but local variable access is optimized so that no dictionary lookup is required, so it's quicker. Look at the bytecode for access to a local variable vs an instance variable in CPython:
>>> import dis
>>> class MyClass:
... def printMethod(self):
... pass
... def code(self):
... pm = self.printMethod
... self.printMethod()
... pm()
...
>>> dis.dis(MyClass.code)
5 0 LOAD_FAST 0 (self)
3 LOAD_ATTR 0 (printMethod)
6 STORE_FAST 1 (pm)
6 9 LOAD_FAST 0 (self)
12 LOAD_ATTR 0 (printMethod)
15 CALL_FUNCTION 0
18 POP_TOP
7 19 LOAD_FAST 1 (pm)
22 CALL_FUNCTION 0
25 POP_TOP
26 LOAD_CONST 0 (None)
29 RETURN_VALUE
>>>
You can see that accessing pm
takes a simple LOAD_FAST
operation, which loads a value from a fixed numerical offest in the local stack frame, while accessing self.printMethod
requires an additional LOAD_ATTR
operation.
Of course it does take time to establish the value of the local variable, so it has to be used multiple times (as it is in your code sample) to see any performance benefit.
As @user5402 points out, your mileage may vary depending on the implementation you use due to optimizations on the part of the compiler.