【发布时间】:2021-06-20 06:54:18
【问题描述】:
这是(简化的)案例:
我有一个包含子类的类:
>>> inst = Foo()
>>> inst.sub.bar()
它从子类的 bar() 方法返回了一些很棒的东西。
这是这样写的:
class Sub() :
def __init__(inst) :
self.inst = inst
def bar(self) :
'''does something magnificent with the Foo instance (self.inst)'''
return smtg
class Foo() :
def __init__(self, *args, **kwargs):
self.sub = Sub(self)
当在第三类中使用 Foo 来处理特定的东西时:
class superFoo(Foo) :
def specific(self,*a,**kw) :
...
我还想使用@decorator 将特定方法包装在子类中,就像我为 Foo 所做的那样:
from functools import wraps
def add_method(cls):
def decorator(func):
@wraps(func)
def wrapper(self, *args, **kwargs):
return func(self, *args, **kwargs)
setattr(cls, func.__name__, wrapper)
return decorator
@add_method(superFoo)
def spam(self, *args, **kwargs) :
return self.specific() + ...
>>> inst = superFoo()
>>> inst.spam() # yep
但我想要的是这个:
>>> inst.sub.spam()
所以我尝试了:
@add_method(superFoo)
def spam(self, *args, **kwargs) :
return self.inst.specific() + ...
在 add_method 函数中:
setattr(cls.sub, func.__name__, wrapper) # ouch, sub not instantiated
失败。
我可以继承 Sub(实际上我现在已经这样做了)来满足需求:
class superSub(Sub) :
def spam(self, *args, **kwargs) :
return self.inst.specific() + ...
class superFoo(Foo) :
def __init__(self, *args, **kwargs):
super().__init__(*args,**kwargs) # there is actualy other inheritances
self.sub = superSub(self) # replaces Sub() by its subclass
但我想知道我是否可以使用装饰器,如果可能的话,这样做:add_method 将在需要时导入到模块中,并且模块的具体内容会一见钟情查看代码时:
from abyssal import add_method
class superFoo(Foo) : # folded in my editor
@add_method(superFoo) :
def spam(self) : # folded
非常感谢
【问题讨论】:
-
你对装饰器的使用不是他们应该使用的方式(不是说它是错误的,它只是违反直觉)。它应该改变它所装饰的函数,而不是函数的参数。您能否提供更多详细信息,说明您为什么这样做。看来应该有更好的办法。
-
Sub() 类在 django 项目中的数十个 Foo() 子类中使用,并满足了大多数的需求。对于一种极端情况,我需要添加和覆盖一些 Sub() 方法,并且希望找到除继承/__init__/setattr 之外的其他方法。
标签: python class wrapper python-decorators functools