
On Tue, Apr 26, 2011 at 8:08 PM, Steven D'Aprano <steve@pearwood.info> wrote:
I would suggest you also publish this decorator-builder recipe on ActiveState's Python cookbook, and see if you get much interest there. It might also help to post a link to your recipe to python-list@python.org. You certainly should do those things before going to python-dev.
OK, I'm going to try that. Thanks.
* Are there some pitfalls involved with the use of NSD that I haven't seen? Or are there additional desirable elements that could be easily included?
Have you timed the decorated function using new and old style? If you decorator a function with (say) 5 arguments, is there any performance hit to your NSD?
Intuitively I would say the the only performance hit would comme from the fact that the decorator arguments are accessed via self.__dict__ in NSD, while there are available as locals with OSD. I've made some quick 'timeit' tests. I don't know if this is the kind of timing you thought about: #--- from timeit import Timer from decorator import decorator # OSD def old_add_args(a=1, b=2, c=3, d=4, e=5): def dummy1(func): def dummy2(*args, **keys): return a + b + c + d + e + func(*args, **keys) return dummy2 return dummy1 # NSD @decorator(a=1, b=2, c=3, d=4, e=5) def new_add_args(self, *args, **keys): return self.a + self.b + self.c + self.d + self.e + self.func(*args, **keys) # Apply OSD @old_add_args() def old_test(*args, **keys): return sum(*args) # Apply NSD @new_add_args() def new_test(*args, **keys): return sum(*args) # Gentle case: the evaluation of the function is rather long compared to the time # needed to fetch the 5 decorator args old_time = Timer('old_test(range(999))', 'from __main__ import old_test').timeit() new_time = Timer('new_test(range(999))', 'from __main__ import new_test').timeit() print "Gentle: old = %.3f new = %.3f" % (old_time, new_time) # Worst case: the evaluation of the function is negligible compared to the time # needed to get the 5 decorators args. old_time = Timer('old_test(range(1))', 'from __main__ import old_test').timeit() new_time = Timer('new_test(range(1))', 'from __main__ import new_test').timeit() print "Worst: old = %.3f new = %.3f" % (old_time, new_time) #--- Here are the timings obtained on my notebook: Gentle: old = 45.983 new = 46.377 Worst: old = 4.043 new = 5.127 which seems to confirm that the overhead mainly comes from the 'self.xxx' fetch, and it pretty negligible when heavy computation is performed. CS