How to learn OO of python?
Steven Bethard
steven.bethard at gmail.com
Thu May 19 03:03:12 EDT 2005
could ildg wrote:
> I think decorator is a function which return a function, is this right?
> e.g. The decorator below if from http://www.python.org/peps/pep-0318.html#id1.
>
> def accepts(*types):
> def check_accepts(f):
> assert len(types) == f.func_code.co_argcount
> def new_f(*args, **kwds):
> for (a, t) in zip(args, types):
> assert isinstance(a, t), \
> "arg %r does not match %s" % (a,t)
> return f(*args, **kwds)
> new_f.func_name = f.func_name
> return new_f
> return check_accepts
>
> After I saw all the examples, I concluded that every decorator must
> define an inner function which takes only one argument, the
> function to decorate. Is this right?
It's close, but not quite right. (I will use the word "function" for
the moment, but see below for why this is inaccurate.) Every
*decorator* must take only one argument, the function to decorate. It is
not at all necessary that a decorator define an inner function.
Consider (from [1]):
def onexit(f):
import atexit
atexit.register(f)
return f
onexit is a decorator because it takes a function and returns a
function. In this case, it happens to be that the same function is
accepted and returned.
Note that in the 'accepts' example above, *check_accepts* is the
decorator, not accepts. The accepts function is actually a function
that *returns* decorators.
Now about that word "function". Decorators are actually *callables*
that accept a single *callable* and return a *callable*. Why does the
terminology matter? Because I can construct decorators from classes too
(from [2]):
class memoized(object):
def __init__(self, func):
self.func = func
self.cache = {}
def __call__(self, *args):
try:
return self.cache[args]
except KeyError:
self.cache[args] = value = self.func(*args)
return value
except TypeError:
return self.func(*args)
Now the memoized decorator can be used just like any other decorator, e.g.:
@memoized
def fibonacci(n):
if n in (0, 1):
return n
return fibonacci(n-1) + fibonacci(n-2)
Note however that memoized is a *callable*, not a *function*.
STeVe
[1] http://www.python.org/peps/pep-0318.html
[2] http://wiki.python.org/moin/PythonDecoratorLibrary
More information about the Python-list
mailing list