On Mon, 11 May 2015 07:08 am, BartC wrote: > On 10/05/2015 10:58, Steven D'Aprano wrote: >> from timeit import Timer >> >> def func(): >> a = 2 >> b = 3 >> c = 4 >> return (a+b)*(a-b)/(a*c + b*c) >> >> >> code = func.__code__ >> assert func() == eval(code) >> >> t1 = Timer("eval; func()", setup="from __main__ import func") >> t2 = Timer("eval(code)", setup="from __main__ import code") >> >> # Best of 10 trials. >> print (min(t1.repeat(repeat=10))) >> print (min(t2.repeat(repeat=10))) > > Maybe the overheads of using eval() are significant when calling a > simple function such as your example. > > When I made it do a bit more work: [...] > Then the eval() call took only 3% longer rather than 100%.
Well duh :-) If I use: def func(): time.sleep(365*24*60*60) # Sleep for a year. then the overhead of calling it will be immeasurably small, regardless of how we call it. But I don't care about big expensive functions. I actually care about the fastest way to execute a tiny piece of code, and for that, the overhead of eval is significant. But regardless of whether the overhead is 3% or 30%, there is an anomaly here. Conceptually at least, calling a function does more work than eval'ing the function's code object: the function evaluates the code object, plus it has overhead of its own which eval'ing the code object lacks. Here is one possible, minimal, pseudo-code implementation of function __call__: def __call__(self, *args): ns = {} for i, parameter in enumerate(self.parameters): ns[parameter] = args[i] return eval(self.__code__, globals(), ns) If I extract the call to eval, and run that alone, without needing to set up function arguments, I should avoid the overhead of the __call__ method. We should expect that: eval(self.__code__, globals(), ns) should be faster than: do_something() eval(self.__code__, globals(), ns) no matter how small and insignificant do_something() actually is. The anomaly is that, according to my tests, and confirmed by others, this is not the case. However function __call__ works, it doesn't use eval. So what does it do? -- Steven -- https://mail.python.org/mailman/listinfo/python-list