类装饰器与函数装饰器

2024-09-28 17:20:23 发布

您现在位置:Python中文网/ 问答频道 /正文

在python中,有两种方法可以声明decorators:

基于类

class mydecorator(object):
    def __init__(self, f):
        self.f = f

    def __call__(self, *k, **kw):
        # before f actions
        self.f(*k, **kw)
        # after f actions

基于功能的

def mydecorator(f):
    def decorator(*k, **kw):
        # before f actions
        f(*k, **kw)
        # after f actions

    return decorator          

这些声明之间有什么区别吗? 在哪些情况下,每种方法都应该使用?


Tags: 方法selfdecoratorsactions声明objectinitdef
3条回答

如果你想在decorator中保持state,你应该使用一个类。

例如,这不起作用

def mydecorator(f):
    x = 0 
    def decorator():
        x += 1 # x is a nonlocal name and cant be modified
        return f(x)
    return decorator 

有很多解决方法,但最简单的方法是使用类

class mydecorator(object):
    def __init__(self, f):
        self.f = f
        self.x = 0

    def __call__(self, *k, **kw):
        self.x += 1
        return f(self.x)

当您创建一个可调用的返回另一个可调用的时,函数方法更简单、更便宜。主要有两个区别:

  1. 函数方法自动与方法一起工作,而如果使用类方法,则必须读取描述符并定义__get__方法。
  2. 类方法使状态保持更容易。您可以使用闭包,特别是在Python 3中,但通常首选类方法来保持状态。

此外,函数方法允许您在修改或存储后返回原始函数。

然而,decorator可以返回可调用的以外的内容,或者返回比可调用的更多的内容。有了一个类,您可以:

  1. 向修饰的可调用对象添加方法和属性,或对其实现操作(uh-oh)。
  2. 创建在类中以特殊方式工作的描述符(例如classmethodproperty
  3. 使用继承实现相似但不同的装饰器。

如果您有任何疑问,请扪心自问:您是否希望您的装饰器返回一个函数,该函数的行为与该函数的行为完全相同?使用返回函数的函数。您希望您的装饰器返回一个自定义对象,该对象执行的操作比函数执行的操作更多还是不同?创建一个类并将其用作装饰器。

事实上,没有“两条路”。只有一种方法(定义一个可调用的对象)或尽可能多的方法来创建一个可调用的对象(它可以是其他对象的方法、lambda表达式的结果、“部分”对象、任何可调用的对象)。

函数定义是创建可调用对象的最简单方法,而且作为最简单的方法,在大多数情况下可能是最好的。使用类可以让您更容易地编写更复杂的情况(即使在最简单的情况下,它看起来也很优雅),但它的作用并不是那么明显。

相关问题 更多 >