微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何使用装饰器标记 Python 方法?

如何解决如何使用装饰器标记 Python 方法?

我有一个形式为 python 的类

class MyClass:
    
    def __init__(self,*args,**kwargs):
        self.lst = [MyClass.method1]

    def method1(self):
        pass

    def method2(self):
        pass

我将这个类扩展为派生类:

class MyDerivedClass(MyClass):
    
    def __init__(self,**kwargs):
        self.lst = [MyDerivedClass.method1,MyDerivedClass.method3]

    def method3(self):
        pass

    def method4(self):
        pass

列表lst包含特定的方法选择:在基类中,它应该只包含method1,而在派生类中只包含method1和method3。我想自动创建 lst ,而不必覆盖 __init__ (原因是,在我的情况下,覆盖 __init__ 非常复杂,并且有很多方法)。有没有办法用这样的装饰器来做到这一点?

@might_have_to_use_class_decorator?
class MyClass:
    
    def __init__(self,**kwargs):
        lst = #automatically compile marked methods -> [method1]

    @mark_this_method
    def method1(self):
        pass

    def method2(self):
        pass

@might_have_to_use_class_decorator?
class MyDerivedClass(MyClass):
    
    def __init__(self,**kwargs):
        lst = # automatically compiled,[method1,method3]

    @mark_this_method
    def method3(self):
        pass

    def method4(self):
        pass

有没有办法使用装饰器来做到这一点,也许是通过装饰我们的类?

解决方法

正如@juanpa.arrivillaga 建议的那样,简单的方法是在类变量中保留方法名称列表,但如果这不适合您,您确实可以使用装饰器来实现。

诀窍是使用方法装饰器在方法对象上动态分配一个属性,然后使用类装饰器枚举所有方法。

def mark_method(method):
    method.is_marked = True
    return method

def class_with_marked_methods(cls):
    parent_marked_methods = getattr(cls,"marked_methods",())
    marked_methods = list(parent_marked_methods)
    for method in cls.__dict__.values():
        if getattr(method,"is_marked",False):
            marked_methods.append(method)
    cls.marked_methods = tuple(marked_methods)
    return cls

@class_with_marked_methods
class MyClass:
    @mark_method
    def method1(self):
        pass

    def method2(self):
        pass

@class_with_marked_methods
class MyDerivedClass(MyClass):
    @mark_method
    def method3(self):
        pass

    def method4(self):
        pass

print([method.__name__ for method in MyDerivedClass.marked_methods])
# prints ["method1","method3"]

我已将 marked_methods 属性设为元组,以便在创建后无法更改,但它也可以轻松成为列表。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。