本文介绍了具有基于装饰器的方法注册表的类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个类,其中包含几种方法,每种方法都具有某些属性(就质量而言)。我希望这些方法在类内的列表中可用,以便可以立即执行。请注意,这些属性可以互换,因此无法通过使用其他继承自原始类的类来解决。在理想的世界中,它看起来像这样:

I have a class that has several methods which each have certain properties (in the sense of quality). I'd like these methods to be available in a list inside the class so they can be executed at once. Note that the properties can be interchangeable so this can't be solved by using further classes that would inherit from the original one. In an ideal world it would look something like this:

class MyClass:
    def __init__():
        red_rules = set()
        blue_rules = set()
        hard_rules = set()
        soft_rules = set()

    @red
    def rule_one(self):
        return 1

    @blue
    @hard
    def rule_two(self):
        return 2

    @hard
    def rule_three(self):
        return 3

    @blue
    @soft
    def rule_four(self):
        return 4

实例化该类时,通过组合集合简单地执行所有红色规则和软性规则应该很容易并执行这些方法。由于常规的注册装饰器可以填写全局对象,但不能填充class属性,因此装饰器很棘手:

When the class is instantiated, it should be easy to simply execute all red and soft rules by combining the sets and executing the methods. The decorators for this are tricky though since a regular registering decorator can fill out a global object but not the class attribute:

def red(fn):
    red_rules.add(fn)
    return fn

如何我该去实现这样的东西吗?

How do I go about implementing something like this?

推荐答案

您可以将 set 子类化>并给它一个装饰器方法:

You can subclass set and give it a decorator method:

class MySet(set):
    def register(self, method):
        self.add(method)
        return method

class MyClass:
    red_rules = MySet()
    blue_rules = MySet()
    hard_rules = MySet()
    soft_rules = MySet()

    @red_rules.register
    def rule_one(self):
        return 1

    @blue_rules.register
    @hard_rules.register
    def rule_two(self):
        return 2

    @hard_rules.register
    def rule_three(self):
        return 3

    @blue_rules.register
    @soft_rules.register
    def rule_four(self):
        return 4

或者如果您发现使用 .register 方法很丑陋,则始终可以定义 __ call __ 方法,将集合本身​​用作装饰器:

Or if you find using the .register method ugly, you can always define the __call__ method to use the set itself as a decorator:

class MySet(set):
    def __call__(self, method):
        """Use set as a decorator to add elements to it."""
        self.add(method)
        return method

class MyClass:
    red_rules = MySet()
    ...

    @red_rules
    def rule_one(self):
        return 1

    ...

这看起来更好,但是不太明确,因此对于其他协作者(

This looks better, but it's less explicit, so for other collaborators (or future yourself) it might be harder to grasp what's happening here.

要调用存储的函数,您只需循环即可超出您想要的集合,并将实例作为 self 传入参数:

To call the stored functions, you can just loop over the set you want and pass in the instance as the self argument:

my_instance = MyClass()
for rule in MyClass.red_rules:
    rule(my_instance)

您还可以创建一个实用程序功能来为您完成此操作,例如,您可以创建 MySet.invoke()方法:

You can also create an utility function to do this for you, for example you can create a MySet.invoke() method:

class MySet(set):
    ...
    def invoke(self, obj):
        for rule in self:
            rule(obj)

现在只需调用:

MyClass.red_rules.invoke(my_instance)

或者您也可以让 MyClass 处理:

class MyClass:
    ...
    def invoke_rules(self, rules):
        for rule in rules:
            rule(self)

然后在实例上调用的 MyClass

my_instance.invoke_rules(MyClass.red_rules)

这篇关于具有基于装饰器的方法注册表的类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-20 14:21