Class decorators do not inherit properly
Diez B. Roggisch
deets at nospam.web.de
Fri Jul 13 05:02:44 EDT 2007
Chris Fonnesbeck schrieb:
> I have a class that does MCMC sampling (Python 2.5) that uses decorators
> -- one in particular called _add_to_post that appends the output of the
> decorated method to a class attribute. However, when I
> subclass this base class, the decorator no longer works:
>
> Traceback (most recent call last):
> File "/Users/chris/Projects/CMR/closed.py", line 132, in <module>
> class M0(MetropolisHastings):
> File "/Users/chris/Projects/CMR/closed.py", line 173, in M0
> @_add_to_post
> NameError: name '_add_to_post' is not defined
>
> yet, when I look at the dict of the subclass (here called M0), I see the
> decorator method:
>
> In [5]: dir(M0)
> Out[5]:
> ['__call__',
> '__doc__',
> '__init__',
> '__module__',
> '_add_to_post',
> ...
>
> I dont see what the problem is here -- perhaps someone could shed
> some light. I thought it might be the underscore preceding the name,
> but I tried getting rid of it and that did not help.
Does this simple example show your problem?
class Meta(type):
def __init__(cls, *args):
print "Meta.__init__ called"
return super(Meta, cls).__init__(*args)
class A(object):
__metaclass__ = Meta
def decorator(f):
print "decorator called"
return f
@decorator
def foo(self):
pass
class B(A):
#@decorator
def bar(self):
pass
print dir(A())
print dir(B())
then it explains the problem easily: the class-statement (class
Name(base): <definitions) is evaluated _before_ the actual class is
created. Thus at that moment, there is no decorator known in the
surrounding scope.
Use a function level decorator instead, that delegates it's work to a
classmethod/instancemethod. Something like this (can't be more precise
as you didn't show us code):
def decorator(f):
def _d(self, *args, **kwargs):
self._a_decorator_method()
return f(self, *args, **kwargs)
return _d
Diez
More information about the Python-list
mailing list