首页 > 解决方案 > 如何自动将python类中的方法“注册”为列表类变量?

问题描述

在定义 Python 类时,我想使用装饰器将它的一些方法注册到类变量列表中。这是一个不正确的python示例,概述了我正在寻找的内容:

class MyClass:

    dangerous_methods = []

    @classmethod
    def dangerous_method(cls, func):
        cls.dangerous_methods.append(func)
        return func

    @MyClass.dangerous_method
    def incinerate(self):
        pass

    def watch_tv(self):
        pass

    @MyClass.dangerous_method
    def stab(self):
        pass

    def print_dangerous_methods(self):
        print(self.dangerous_methods)


obj = MyClass()
obj.print_dangerous_methods()

预期输出为

[<function MyClass.incinerate at 0x000001A42A629280>, <function MyClass.stab at 0x000001A42A629281>]

是否可以在不过多折磨 Python 的情况下做到这一点?

标签: pythonclassdecorator

解决方案


这是实现它的一种方法:

class MyClass:
    def __init__(self):
        self.dangerous_methods = []

    def dangerous_method(func):
        def inner(self):
            self.dangerous_methods.append(func)
            return func(self)
        return inner

    @dangerous_method
    def incinerate(self):
        print('Incinerate called!')
        pass

    def watch_tv(self):
        print('Watch_tv called!')
        pass

    @dangerous_method
    def stab(self):
        print('Stab called!')
        pass

    def print_dangerous_methods(self):
        print(self.dangerous_methods)


obj = MyClass()
obj.incinerate()
# Incinerate called!
obj.watch_tv()
# Watch_tv called!
obj.stab()
# Stab called!
obj.incinerate()
# Incinerate called!
obj.print_dangerous_methods()
# [<function MyClass.incinerate at 0x0000029C11666EE8>, <function MyClass.stab at 0x0000029C11666B88>, <function MyClass.incinerate at 0x0000029C11666EE8>]

请注意,以这种方式,函数仅在调用后才被添加到列表中,并且存在将函数多次添加到列表中的风险。但是,如果您知道要添加到列表中的某些函数并且它们是常量,则可以在构造对象时简单地添加它们:

class MyClass:
    def __init__(self):
        self.dangerous_methods = [self.incinerate, self.stab]

    def incinerate(self):
        print('Incinerate called!')
        pass

    def watch_tv(self):
        print('Watch_tv called!')
        pass

    def stab(self):
        print('Stab called!')
        pass

    def print_dangerous_methods(self):
        print(self.dangerous_methods)


obj = MyClass()
obj.print_dangerous_methods()
# [<bound method MyClass.incinerate of <__main__.MyClass object at 0x0000029C11388F08>>, <bound method MyClass.stab of <__main__.MyClass object at 0x0000029C11388F08>>]

推荐阅读