将函数作为方法包装在python中类的子类中

问题描述

这是(简化的)案例:

我有一个包含子类的类:

>>> 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,**kwargs): 
            return func(self,**kwargs)
        setattr(cls,func.__name__,wrapper)
    return decorator
    
@add_method(superFoo)
def spam(self,**kwargs) :
    return self.specific() + ...
    
>>> inst = superFoo()
>>> inst.spam() # yep

但我想要的是这个:

>>> inst.sub.spam()

所以我试过:

@add_method(superFoo)
def spam(self,**kwargs) :
    return self.inst.specific() + ...

在 add_method 函数中:

setattr(cls.sub,wrapper) # ouch,sub not instantiated

失败。

我可以 sublass Sub(实际上我现在已经这样做了)来满足需求:

class superSub(Sub) :
    def spam(self,**kwargs) :
        return self.inst.specific() + ...

class superFoo(Foo) :
    def __init__(self,**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

非常感谢

解决方法

您的 add_method 装饰器可能是您的 superFoo 类的方法:

class superFoo(Foo):

    def add_method(self):
        def decorator(func):
            setattr(self,func.__name__,func)
            return func
        return decorator

(注意我简化了一点)

然后您将其用作:

sub = Sub()
inst = superFoo(sub)

@inst.add_method(superFoo)
def spam(self,*args,**kwargs) :
    return self.inst.specific() + ...

但又一次。我建议使用继承。只需为 Sub 定义子类会更简单易懂。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...