如何自动;登记册;python类中作为列表类变量的方法?

如何自动;登记册;python类中作为列表类变量的方法?,python,class,decorator,Python,Class,Decorator,定义Python类时,我希望使用decorator将它的一些方法注册到类变量列表中。下面是一个不正确的python示例,它概述了我要查找的内容: class MyClass: dangerous_methods = [] @classmethod def dangerous_method(cls, func): cls.dangerous_methods.append(func) return func @MyClass.da

定义Python类时,我希望使用decorator将它的一些方法注册到类变量列表中。下面是一个不正确的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的情况下实现这一点?

这是实现这一点的一种方法:

class-MyClass:
定义初始化(自):
self.u方法=[]
def危险_方法(func):
def内部(自):
self.hazardous_methods.append(func)
返回函数(自身)
返回内部
@危险法
def焚烧(自):
打印('已调用焚化!')
通过
def watch_tv(自动):
打印('Watch_tv called!')
通过
@危险法
def stab(自我):
打印('Stab called!')
通过
def打印方法(自我):
打印(自我危险的打印方法)
obj=MyClass()
焚化
#焚化呼叫!
obj.看电视
#看电视!
obj.stab()
#刺杀呼叫!
焚化
#焚化呼叫!
对象打印方法()
# [, ]
只需注意,通过这种方式,函数只在调用一次后才会添加到列表中,并且存在函数多次添加到列表中的风险。但是,如果您知道要将某些函数添加到列表中,并且它们是常量,则可以在构建对象时简单地添加它们:

class-MyClass:
定义初始化(自):
self.danger_方法=[self.infense,self.stab]
def焚烧(自):
打印('已调用焚化!')
通过
def watch_tv(自动):
打印('Watch_tv called!')
通过
def stab(自我):
打印('Stab called!')
通过
def打印方法(自我):
打印(自我危险的打印方法)
obj=MyClass()
对象打印方法()
# [, ]

您真正想做的就是在方法上设置
危险
。请记住,python函数和方法是一流的对象,您可以对它们设置任意属性

def print_dangerous_methods(cls):
    """ yes, you could also return a list """
    for name in dir(cls):
        f = getattr(cls, name)
        if callable(f) and getattr(f, "dangerous", False):
            print(name)


def dangerous(func):
    setattr(func, "dangerous", True)
    return func

class MyClass:

    @dangerous
    def incinerate(self):
        print("incinerate")

    def watch_tv(self):
        pass

    @dangerous
    def stab(self):
        return "you've been stabbed"

    class_born_dangerous = print_dangerous_methods

print("\non instance")
obj = MyClass()
print_dangerous_methods(obj)

print("\non class")
print_dangerous_methods(MyClass)

print("\nand yes, they work")
obj.incinerate()
print (obj.stab())

print("\nas a classmethod")
obj.class_born_dangerous()
输出: 如果要推广此方法并设置任意属性,则需要设置参数化装饰器:

def annotate_func(**kwds):
    """set arbitrary attributes"""
    def actual_decorator(func):
        for k, v in kwds.items():
            setattr(func, k, v)
        return func
    return actual_decorator
您将按如下方式使用:

    @annotate_func(dangerous=1,range=1000)
    def shoot(self, times):
        for i in range(0, times):
            print("bang!")

下面的代码片段与您描述的完全相同

请注意,
print\u危险的\u方法
被声明为类方法,因为它实际上就是这样的(它应用于类,而不是某个实例)。这意味着即使不创建实例也可以调用它

class-MyClass:
def危险_方法(meth):
冰毒是否危险=正确
返回冰毒
@危险法
def焚烧(自):
通过
def watch_tv(自动):
通过
@危险法
def stab(自我):
通过
@类方法
def打印方法(cls):
印刷品([
用冰毒换冰毒[
目录(cls)中methname的getattr(cls,methname)
]
如果getattr(冰毒,“是否危险”,错误)
])
MyClass.print\u方法()

因此,您现在有了一个方法列表!你想有一个方法名列表吗?我包含的代码实际上不起作用,所以我还没有一个方法列表。我也需要名称,但是如果我有方法列表,那么我也可以使用。_uname_;来获取名称。
    @annotate_func(dangerous=1,range=1000)
    def shoot(self, times):
        for i in range(0, times):
            print("bang!")