
On Wednesday 22 October 2003 07:57 pm, Guido van Rossum wrote: ...
def accgen(n): def acc(i): global n in accgen n += i return n return acc
particulary more compelling than:
class accgen: def __init__(self, n): self.n = n
def __call__(self, i): self.n += i return self.n
Some people have "fear of classes". Some people think that a function's scope can be cheaper than an object (someone should time this).
I need to simulate the "rebinding name in outer scope" with some kind of item or attribute, of course, but, given this, here comes: given this b.py: def accgen_attr(n): def acc(i): acc.n += i return acc.n acc.n = n return acc def accgen_item(n): n = [n] def acc(i): n[0] += i return n[0] return acc class accgen_clas(object): def __init__(self, n): self.n = n def __call__(self, i): self.n += i return self.n def looper(accgen, N=1000): acc = accgen(100) x = map(acc, xrange(N)) return x I measure: [alex@lancelot ext]$ timeit.py -c -s'import b' 'b.looper(b.accgen_attr)' 1000 loops, best of 3: 1.86e+03 usec per loop [alex@lancelot ext]$ timeit.py -c -s'import b' 'b.looper(b.accgen_item)' 1000 loops, best of 3: 1.18e+03 usec per loop [alex@lancelot ext]$ timeit.py -c -s'import b' 'b.looper(b.accgen_clas)' 100 loops, best of 3: 2.1e+03 usec per loop So, yes, a function IS slightly faster anyway (accgen_attr vs accgen_clas), AND simulating outer-scope-rebinding with a list item is somewhat faster than doing so with an attr (a class always uses an attr, and most of its not-too-terrible performance handicap presumably comes from that fact). I just don't think such closures would typically be used in bottlenecks SO tight that a 10%, or even a 40%, extra overhead are going to be crucial. So, I find it hard to get excited either way by this performance issue. Alex