Size: 5639
Comment:
|
Size: 5646
Comment: Added 'return' in dumpArgs decorator when calling the decorated function
|
Deletions are marked like this. | Additions are marked like this. |
Line 225: | Line 225: |
func(*args,**kwargs) | return func(*args,**kwargs) |
This page is meant to be a central repository of decorator code pieces, whether useful or not <wink>. It is NOT a page to discuss decorator syntax!
Feel free to add your suggestions (please use the current decorator syntax @dec)!
Memoize
Here's a memoizing class.
inline:memoize.py
Pseudo-currying
Toggle line numbers
1 class curried(object):
2 """
3 Decorator that returns a function that keeps returning functions
4 until all arguments are supplied; then the original function is
5 evaluated.
6 """
7
8 def __init__(self, func, *a):
9 self.func = func
10 self.args = a
11 def __call__(self, *a):
12 args = self.args + a
13 if len(args) < self.func.func_code.co_argcount:
14 return curried(self.func, *args)
15 else:
16 return self.func(*args)
17
18
19 @curried
20 def add(a, b):
21 return a+b
22
23 add1 = add(1)
24
25 print add1(2)
Controllable DIY debug
(Other hooks could be similarly added. Docstrings and exceptions are left out for simplicity of demonstration.)
Toggle line numbers
1 import sys, sets
2
3 WHAT_TO_DEBUG = sets.Set(['io', 'core']) # change to what you need
4
5 class deBug:
6 """ Decorator which helps to control what aspects of a program to debug
7 on per-function basis. Aspects are provided as list of arguments.
8 It DOESN'T slowdown functions which aren't supposed to be debugged.
9 """
10 def __init__(self, aspects=None):
11 self.aspects = sets.Set(aspects)
12
13 def __call__(self, f):
14 if self.aspects & WHAT_TO_DEBUG:
15 def newf(*args, **kwds):
16 print >> sys.stderr, f.func_name, args, kwds
17 f_result = f(*args, **kwds)
18 print >> sys.stderr, f.func_name, "returned", f_result
19 return f_result
20 newf.__doc__ = f.__doc__
21 return newf
22 else:
23 return f
24
25 @deBug(['io'])
26 def prn(x):
27 print x
28
29 @deBug(['core'])
30 def mult(x, y):
31 return x * y
32
33 prn(mult(2,2))
Easy adding methods to a class instance
Credits to John Roth.
Toggle line numbers
1 class Foo:
2 def __init__(self):
3 self.x = 42
4
5 foo = Foo()
6
7 def addto(instance):
8 def decorator(f):
9 import new
10 f = new.instancemethod(f, instance, instance.__class__)
11 setattr(instance, f.func_name, f)
12 return f
13 return decorator
14
15 @addto(foo)
16 def print_x(self):
17 print self.x
18
19 # foo.print_x() would print "42"
Counting function calls
Toggle line numbers
1 class countcalls(object):
2 "Decorator that keeps track of the number of times a function is called."
3
4 __instances = {}
5
6 def __init__(self, f):
7 self.__f = f
8 self.__numCalls = 0
9 countcalls.__instances[f] = self
10
11 def __call__(self, *args, **kwargs):
12 self.__numCalls += 1
13 return self.__f(*args, **kwargs)
14
15 @staticmethod
16 def count(f):
17 "Return the number of times the function f was called."
18 return countcalls.__instances[f].__numCalls
19
20 @staticmethod
21 def counts():
22 "Return a dict of {function: # of calls} for all registered functions."
23 return dict([(f, countcalls.count(f)) for f in countcalls.__instances])
Creating Well-Behaved Decorators
Toggle line numbers
1 def simple_decorator(decorator):
2 """This decorator can be used to turn simple functions
3 into well-behaved decorators, so long as the decorators
4 are fairly simple. If a decorator expects a function and
5 returns a function (no descriptors), and if it doesn't
6 modify function attributes or docstring, then it is
7 eligible to use this. Simply apply @simple_decorator to
8 your decorator and it will automatically preserve the
9 docstring and function attributes of functions to which
10 it is applied."""
11 def new_decorator(f):
12 g = decorator(f)
13 g.__name__ = f.__name__
14 g.__doc__ = f.__doc__
15 g.__dict__.update(f.__dict__)
16 return g
17 # Now a few lines needed to make simple_decorator itself
18 # be a well-behaved decorator.
19 new_decorator.__name__ = decorator.__name__
20 new_decorator.__doc__ = decorator.__doc__
21 new_decorator.__dict__.update(decorator.__dict__)
22 return new_decorator
23
24 #
25 # Sample Use:
26 #
27 @simple_decorator
28 def mySimpleLoggingDecorator(f):
29 print 'calling %s' % f.__name__
30
31 @mySimpleLoggingDecorator
32 def double(x):
33 "Doubles a number"
34 return 2*x
35
36 assert(double.__name__ == 'double')
37 assert(double.__doc__ == 'Doubles a number')
Enable/Disable Decorators
Toggle line numbers
1 def unchanged(func):
2 "This decorator doesn't add any behavior"
3 return func
4
5 def disabled(func):
6 "This decorator disables the provided function, and does nothing"
7 def emptyFunc(*args,**kargs):
8 pass
9 return emptyFunc
10
11 # define this as equivalent to unchanged, for nice symmetry with disabled
12 enabled = unchanged
13
14 #
15 # Sample use
16 #
17
18 globalEnableFlag = int(True)
19
20 @(disabled, enabled)[globalEnableFlag]
21 def specialFunctionFoo():
22 print "function was enabled"
Easy Dump of Function Arguments
Toggle line numbers
1 def dumpArgs(func):
2 "This decorator dumps out the arguments passed to a function before calling it"
3 argnames = func.func_code.co_varnames[:func.func_code.co_argcount]
4 fname = func.func_name
5 def echoFunc(*args,**kwargs):
6 print fname,":", zip(argnames,args)
7 return func(*args,**kwargs)
8 return echoFunc
9
10 @dumpArgs
11 def f1(a,b,c):
12 print a+b+c
13
14 f1(1,2,3)