Python中类装饰的实际用途是什么?

时间:2017-04-06 10:10:58

标签: python decorator

在Python 2.6中,PEP 3129向Python中引入了“类装饰器”,并且已经在语言中提供了函数装饰器。我无法看到这样的东西何时或何地可以实际使用,我有兴趣知道是否通过使用类装饰器而不是使用它们来获得相同的结果来改善性能。

2 个答案:

答案 0 :(得分:1)

类装饰器是将类对象作为输入并将绑定到输入类名称的对象更改为函数输出的函数(通常您希望返回相同的类)。它们是继承和元类的替代方法,用于自定义类行为,它们的不同之处在于它们在完全创建类之后起作用,而不是影响类创建过程。另一个区别是类装饰器不是继承的,在某些情况下可能比元类更有优势。

def register_handlers(cls):
    token = 'handle_'
    cls.handler_dict = {k[len(token):] : getattr(cls,k) for k in dir(cls) if k.startswith(token)}
    return cls

@register_handlers
class Handler:
    def handle_input(self):
        pass

    def handle_output(self):
        pass

    def handle_error(self):
        pass

此外,类装饰器根本不需要修改类,它可以只返回它,例如在某处注册:

game_objects = {}

def register_object(cls):
    game_objects[cls.__name__] = cls
    return cls

@register_object
class Chair:
    pass

@register_object
class Car:
    pass

答案 1 :(得分:0)

类装饰器有多种用途。对我来说有意义的一个案例是在发布者 - 订户系统中注册一个类,例如,插件或事件,如:

@register
class MyPlugin(Plugin):
    pass
or

@recieves_notifications
class Console:
    def print(self, text):
        ...

另一种用法可能是例如编写具有@ unittest.skipIf的单元测试时,@ unittest.skipUnless可用于单个方法或整个unittest.TestCase类定义。这使得为​​平台特定问题编写测试变得更加容易。

Example from asyncio/test_selectors

# Some platforms don't define the select.kqueue object for these tests.
# On those platforms, this entire grouping of tests will be skipped.

@unittest.skipUnless(hasattr(selectors, 'KqueueSelector'),
                 "Test needs selectors.KqueueSelector)")
class KqueueSelectorTestCase(BaseSelectorTestCase, ScalableSelectorMixIn):
...