python装饰器使用

Python023

python装饰器使用,第1张

装饰器是从英文decorator翻译过来的,从字面上来看就是对某个东西进行修饰,增强被修饰物的功能,下面我们对装饰器做下简单介绍。

一、怎么编写装饰器

装饰器的实现很简单,本质是一个可调用对象,可以是函数、方法、对象等,它既可以装饰函数也可以装饰类和方法,为了简单说明问题,我们实现一个函数装饰器,如下代码:

有了这个装饰器,我们就可以打印出什么时候开始和结束调用函数,对于排查函数的调用链非常方便。

二、带参数的装饰器

上面的例子无论什么时候调用sum都会输出信息,如果我们需要按需输出信息怎么实现呢,这时就要用到带参数的装饰器了,如下代码:

对sum使用装饰器时没有参数,这时debug为0,所以调用sum时不会输出函数调用相关信息。

对multi使用装饰器时有参数,这时debug为1,所以调用multi时会输出函数调用相关信息。

三、函数名字问题

当我们打印被装饰后的函数名字时,不知道大家有没发现输出的不是函数本身的名字,如下代码会输出‘wrap’而不是‘sum’:

有时这种表现并不是我们想要的,我们希望被装饰后的函数名字还是函数本身,那要怎么实现呢?很简单,只需要引入functools.wraps即可,如下代码就会输出‘sum’了:

看完后是不是觉得python装饰器很简单,只要了解它的本质,怎么写都行,有好多种玩法呢。

装饰器(decorator)是Python中的高级语法。装饰的意思就是动态扩展被装饰对象的功能。装饰器可以用于装饰函数、方法和类。

一 嵌套函数

# 定义一个外层函数def foo(): # 定义了一个内部函数 def bar(): print("hello world")

函数bar是一个定义在foo函数内部的函数。

Python中的函数是支持嵌套的,也就是可以在一个函数内部再定义一个函数。

然后,我们还知道函数是可以当作变量的,于是我们就可以在foo函数中把定义的这个bar函数返回。就像下面这样:

# 定义一个外层函数def foo(): # 定义了一个内层函数 def bar(): print("hello world") return

barfunc = foo()func() # func -->bar,这里执行func其实就相当于执行了在foo函数内部定义的bar函数

二 闭包形态1

# 闭包形态1def foo(): name = "Andy" # 外部函数的局部变量 # 定义了一个内部函数 def bar():

print(name) # 虽然bar函数中没有定义name变量,但是它可以访问外部函数的局部变量name return barfunc =

foo()func() # func -->bar -->除了是一个函数,还包含一个值(它外层函数的局部变量)的引用

三 闭包形态2

# 闭包形态2def foo(name): # 给一个函数传参也相当于给函数定义了一个局部变量 # 定义了一个内部函数 def bar():

print(name) # 内部函数同样可以获取到传到外部函数的变量(参数) return barfunc = foo("Andy") #

把“Andy”当成参数传入foo函数 -->其内部定义的bar函数也能拿到这个“Andy”func() # func -->bar -->

除了是一个函数,还包含一个值(它外层函数的参数)的引用

四 装饰器形态1

# 还是定义一个外层函数def foo(name): # 我接收的参数是一个函数名 # 定义了一个内部函数 def bar():

print("这是新功能。。。") # 新功能 name() # 函数名加()就相当于执行-->我传进来原函数的函数名,这里就相当于执行了原函数

return bar# 定义一个被装饰的函数def f1(): print("hello world.") # 用foo函数装饰f1函数f1 =

foo(f1)# 不改变f1的调用方式f1() # -->此时函数已经扩展了新功能

五 装饰器形态2

# 还是定义一个外层函数def foo(name): # 接收的参数是一个函数名 # 定义了一个内部函数 def bar():

print("这是新功能。。。") # 新功能 name() # 函数名加()就相当于执行-->传进来原函数的函数名,这里就相当于执行了原函数

return bar# 定义一个被装饰的函数# 用foo函数装饰f1函数@foo # 使用f1 =

foo(f1)语法装饰的话稍显啰嗦,Python就提供了@语法,让装饰过程更简便def f1(): print("hello world.") #

不改变f1的调用方式f1() # -->此时函数已经扩展了新功能。

装饰器是一个函数,下记为函数A。函数A的返回值是

当你调用了一个被装饰器A装饰的函数B时,会将函数B作为变量传入函数A中。函数A最终会返回一个函数,记为函数C。在函数执行时会将变量传入函数C中执行并返回结果。

def a(func):

    def c(*args,**kwargs):

        print(args)

        print(kwargs)

        return func(*args,**kwargs)

    return c

@a

def b(*args):

    return sum(args)

if __name__ == '__main__':

    print(b)

    # <function a.<locals>.c at 0x021B7348>

    # 当你调用到函数b时,实际拿到的是将函数b作为参数放入a中执行后返回的函数c

    print(b(*[i for i in range(10)]))

    # (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)

    # {}

    # 45

    # 第一行是函数c打印args的结果

    # 第二行是函数c打印kwargs的结果

    # 第三行是最终print(c(0, 1, 2, 3, 4, 5, 6, 7, 8, 9))的结果