类装饰器与函数装饰器

Yos*_*ssi 28 python decorator

在python中有两种声明装饰器的方法:

基于类

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
Run Code Online (Sandbox Code Playgroud)

功能为基础

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

    return decorator          
Run Code Online (Sandbox Code Playgroud)

这些声明之间有什么区别吗?在哪些情况下应该使用它们?

Joc*_*zel 19

如果你想在装饰器中保持状态,你应该使用一个类.

例如,这不起作用

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

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

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)
Run Code Online (Sandbox Code Playgroud)

  • 我认为最简单的方法是说`nonlocal x; x + = 1` 或者这不适用于3以下的Python版本? - 是的,看起来像`nonlocal`是在Python 3中引入的. (2认同)

Ros*_*ron 19

当你创建一个可调用的返回另一个callable时,函数方法更容易,更便宜.有两个主要区别:

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

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

然而,一个装饰可以返回比调用其他的东西或事情比一个调用.通过课程,您可以:

  1. 将方法和属性添加到修饰的可调用对象,或对它们实现操作(嗯哦).
  2. 创建在放置在类中时以特殊方式起作用的描述符(例如classmethod,property)
  3. 使用继承来实现类似但不同的装饰器.

如果您有任何疑问,请问自己:您是否希望装饰器返回一个与函数完全相同的函数?使用返回函数的函数.您是否希望装饰器返回一个自定义对象,该对象可以执行更多功能或与功能不同的功能?创建一个类并将其用作装饰器.


Jac*_*zny 6

事实上,没有"两种方式".只有一种方法(限定一个可调用对象)或尽可能多的方式,因为有在python使一个可调用的对象(也可能是其他对象的方法,lambda表达式中,"部分"对象的结果,任何是可赎回).

函数定义是制作可调用对象的最简单方法,并且作为最简单的方法,在大多数情况下可能是最好的.使用类为您提供了更多可能来干净地编写更复杂的案例(即使在最简单的情况下,它看起来相当优雅),但它的作用并不明显.