在Python中扩展被装饰的类
有没有办法扩展一个已经应用了装饰器的类呢?比如说:
@someDecorator
Class foo(object):
...
...
Class bar(foo):
...
...
理想情况下,bar 这个类不应该受到装饰器的影响,但我首先想知道这是否可能。目前我遇到了一个非运行时的错误:
“类型错误:调用元类基类时出错,函数的第一个参数必须是代码,而不是字符串。”
有什么建议吗?
3 个回答
1
如果你在寻找一个不同于最佳答案的方法,我发现对我来说最好的办法是在类装饰器里面装饰 __init__
方法。比如说:
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
2
是的,这种情况是可能的,只要@someDecorator
确实返回了一个类。类装饰器的作用是接收一个类作为参数,并且通常应该返回一个类,除非你在做一些非常特别的事情。
在这个例子中,foo
将会和@someDecorator
返回的内容绑定在一起。
这个装饰器是不是返回了其他东西?比如一个str
(字符串)?
0
正如Matt所说,你的装饰器没有正常工作。每当你让装饰器正常工作时(可以做一些测试,甚至直接复制粘贴到控制台进行即时测试):
有效的装饰器返回的就是你的类“foo”——如果你使用装饰器语法,就无法访问装饰器应用之前的内容。
不过,在Python中,装饰器其实是一种语法糖,它可以把你声明的函数或类替换成经过装饰器处理后返回的内容。因此,下面这两种写法是等价的:
@someDecorator
class foo(object):
pass
和
class foo(object):
pass
foo = someDecorator(foo)
所以,你可以通过以下方式在应用装饰器之前扩展一个类:
class foo(object):
pass
class bar(foo):
pass
foo = someDecorator(foo)