Please note that due to an error previously discovered in my test code, my initial answer was incorrect. Below is a revised version.
I made a small program for measuring runtime and memory consumption. I created the following called class and closure:
class CallMe: def __init__(self, context): self.context = context def __call__(self, *args, **kwargs): return self.context(*args, **kwargs) def call_me(func): return lambda *args, **kwargs: func(*args, **kwargs)
I am confined to simple functions that take a different number of arguments ( math.sqrt() with 1 argument, math.pow() with 2 and max() with 12).
I used CPython 2.7.10 and 3.4.3+ for Linux x64. I could only do memory profiling in Python 2. The source code I used is available here .
My findings:
- Closures are faster than equivalent classes that cause a call: about 3 times faster in Python 2, but only in Python 3 1.5 times faster. The narrowing is due to the fact that closing has become slower and called classes are slower.
- Closures take up less memory than equivalent classes to be called: approximately 2/3 of the memory (tested only in Python 2).
- Although not part of the original question, it is interesting to note that the overhead of execution time for calls made using closure is about the same as calling
math.pow() , while it doubles through the called class.
These are very rough estimates, and they may vary depending on the hardware, operating system, and function that you are comparing. However, this gives you an idea of ββthe effect of using each type of callable.
Therefore, it supports (unlike what I wrote earlier) that the accepted answer given by @RaymondHettinger is correct, and closure should be preferred for indirect calls, at least until it interferes with readability , Also thanks to @AXO for pointing out the error in my source code.
Yuval
source share