【发布时间】:2018-03-09 15:31:26
【问题描述】:
背景
我编写了一个装饰器函数来修改给定类的__repr__,这样当一个类实例被调用时,它的所有属性都会打印给用户。在下面示例中的 Container 类中使用时,装饰器 __repr__dec 的行为符合预期。
输入
def __repr__wrapper(self):
"""Show all attributes."""
return "Attributes: "+", ".join(list(self.__dict__.keys()))
def __repr__dec(func):
"""Replaces the __repr__ function of a class with __repr__wrapper"""
def call(*args, **kwargs):
func.__repr__ = __repr__wrapper
result = func(*args, **kwargs)
return result
return call
@__repr__dec
class Container(object):
def __init__(self, *args, **kwargs):
self.metadata = args[0]
for k,v in kwargs.items():
self.__dict__[k] = v
occ = Container(42, how="now")
occ
输出
Attributes: metadata, how
但是,当我尝试继承 Container 时,我收到一条 TypeError 消息:
输入
class Handle(Container):
def __init__(self, *args, **kwargs):
Container.__init__(self, *args, **kwargs)
han = Handle(42)
输出
TypeError Traceback (most recent call last)
<ipython-input-17-b4c252411c1f> in <module>()
----> 1 class Handle(Container):
2 def __init__(self, *args, **kwargs):
3 Container.__init__(self, *args, **kwargs)
4
5 han = Handle(42)
TypeError: function() argument 1 must be code, not str
问题
为什么在使用__repr__dec 函数时,子类化Conatainer 会失败?有可能解决这个问题吗?
【问题讨论】:
-
我不知道装饰器不会被继承。现在这开始有意义了。
-
@IgnacioVergaraKausel 元类在这里太过分了。而“非继承”并不是对正在发生的事情的准确描述。装饰的类对象被
__repr__dec中定义的call函数替换。换句话说,Container实际上是一个函数,而不是一个类。 这就是为什么试图继承它会引发异常。 -
为什么不能在
Container中定义__repr__? -
你的装饰器不过是一个函数。你不能子类化函数。
-
是否可以制作一个返回类而不是函数的装饰器?
标签: python python-3.x decorator subclassing