开发者

Extending a decorated class in Python

Is it possible to extend a class which has a decorator applied to it? For example:

@someDecorator
Class foo(object):
  ...
  ...

Class bar(foo):
  ...
  ...

Ideally bar would not be affected by the decorator, but first I want to find out if this is even possible. Currently I am 开发者_如何学Gogetting a non-runtime error:

"TypeError: Error when calling the metaclass bases function() argument 1 must be code, not str "

Any suggestions?


Yes it is possible, as long as @someDecorator is actually returning a class. A class decorator takes a class as its argument, and should almost always return a class, unless you are doing something very unusual.

foo, in this case, will be bound to whatever @someDecorator returns.

Is this decorator returning something else? A str?


For anyone looking for an alternative to the chosen answer, I found best way for me was to decorate __init__ inside the class decorator. So for example:

def some_decorator(cls):
    def decorate_init(func):
        def decorated(*args, **kwargs):
            func(*args, **kwargs) # Run __init__
            instance = args[0]
            # Do whatever you need with the newly constructed instance
        return decorated
    cls.__init__ = decorated_init(cls.__init__)
    return cls


As Matt put it, your decorator is not working. Whenever you get your decorator to work properly (make some tests, even imediate tests by copying and paste to a console):

What the (valid) decorator returns is your class "foo" - you can't access what it was before the decorator being applied if you use the decorator syntax.

However, decorators in Python are a syntatic sugar to replace the following declared function or class with what is returned by processing that function or class with the decorator. Thus, these are equivalent:

@someDecorator
class foo(object):
   pass

and

class foo(object):
   pass
foo = someDecorator(foo)

Therefore, you can achieve the effect of extending a class before applying the decorator simply by doing:

class foo(object):
   pass
class bar(foo):
   pass

foo = someDecorator(foo)
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜