美文网首页Python与数据分析
【Python学习笔记】装饰器

【Python学习笔记】装饰器

作者: 清梦载星河 | 来源:发表于2020-02-16 18:06 被阅读0次

1.先回顾函数的几个概念

1.1 函数可以赋予变量

def func(message):
    print("Got a message: {}".format(message))

send_message = func
send_message("helloworld")

# 输出
Got a message: helloworld

在上面的例子中,函数func()赋给了变量send_message,这样调用send_message就相当于调用了函数func()

1.2 函数可以当作参数

def get_message(message):
    return 'Got a message: ' + message

def root_call(func, message):
    print(func(message))

root_call(get_message, 'hello world')
# 输出
Got a message: hello world

在这个例子中,函数get_message()就作为函数root_call()的参数。

1.3 函数可以嵌套

def func(message):
    def get_message(message):
        print('Got a message: {}'.format(message))
    return get_message(message)

func('hello world')

# 输出
Got a message: hello world

这里在函数func()中嵌套了另一个函数get_message(),调用后作为func()的返回值返回。

1.4 函数的返回值可以是函数对象(闭包)

def func_closure():
    def get_message(message):
        print('Got a message: {}'.format(message))
    return get_message

send_message = func_closure()
send_message('hello world')

# 输出
Got a message: hello world

这个例子中,函数func_closure()的返回值是函数对象get_message()本身,之后将其赋给了变量send_message,再调用send_message。

2. 简单的装饰器

def my_decorator(func):
    def wrapper():
        print("wrapper of decorator")
        func()
    return wrapper

def greet():
    print('hello world')
    
greet = my_decorator(greet)
greet()

# 输出
wrapper of decorator
hello world

上述例子中,变量greet指向内部函数wrapper(),内部函数wrapper()调用原函数greet()。最后调用greet()时,先打印“wrapper of decorator”,然后再打印“hello world”。

这里的函数my_decorator()就是一个装饰器,它把真正需要执行的函数greet()包裹在其中,并且改变了它的
行为,但是原函数greet()不变

还可以使用更简洁的表示:

def my_decorator(func):
    def wrapper():
        print('wrapper of decorator')
        func()
    return wrapper

@my_decorator

def greet():
    print('hello world')
greet()

上面例子中的@my_decorator就相当于greet = my_decorator(greet),只不过更加简洁。

3. 带有参数的装饰器

建议直接设置“*args, **kwargs”,这样就能传入多个参数

def my_decorator(func):
    def wrapper(*args, **kwargs):
        print('wrapper of decorator')
        func(*args, **kwargs)
    return wrapper

4. 保留原函数的元信息

函数被装饰后,函数的元信息就会改变,例如上面的函数greet()被装饰以后,就变成了wrapper()。为了解决这个问题,我们可以使用内置的装饰器@functools.wrap来保留函数的元信息。其作用就是将元信息拷贝到对应的装饰器函数里。

import functools

def my_decorator(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        print('wrapper of decorator')
        func(*args, **kwargs)
    return wrapper

@my_decorator

def greet(message):
    print(message)

greet.__name__

# 输出
'greet'

5. 类装饰器

前面主要讲函数作为装饰器的用法,而类也可以作为装饰器。类装饰器主要依赖函数__call__()

class Count:
    def __init__(self, func):
        self.func = func
        self.num_calls = 0
        
    def __call__(self, *args, **kwargs):
        self.num_calls += 1
        print('num of calls is: {}'.format(self.num_calls))
        return self.func(*args, **kwargs)
    
@Count
def example():
    print('hello world')

example()

# 输出
num of calls is: 1
hello world

example()

# 输出
num of calls is: 2
hello world

6. 装饰器的嵌套

例如:

@decorator1
@decorator2
@decorator3
def func():
    ...

上面的语句等同于:

decorator1(decorator2(decorator3(func)))

具体示例:

import functools

def my_decorator1(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        print('execute decorator1')
        func(*args, **kwargs)
    return wrapper

def my_decorator2(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        print('execute decorator2')
        func(*args, **kwargs)
    return wrapper

@my_decorator1
@my_decorator2

def greet(message):
    print(message)
    
greet('hello world')

# 输出
execute decorator1
execute decorator2
hello world

相关文章

  • 大师兄的Python学习笔记(十四): 迭代器、生成器和协程

    大师兄的Python学习笔记(十三): 理解装饰器大师兄的Python学习笔记(十五): Socket编程 一、关...

  • Python ☞ day 5

    Python学习笔记之 装饰器& 偏函数 & 异常处理 & 断言 & 文件读写 &编码与解码 装饰器 概念:是一个...

  • Python—闭包与装饰器

    将之前学习Python的笔记整理记录下来。 闭包 装饰器

  • 装饰器模式

    介绍 在python装饰器学习 这篇文章中,介绍了python 中的装饰器,python内置了对装饰器的支持。面向...

  • python中的装饰器

    python装饰器详解 Python装饰器学习(九步入门) 装饰器(decorator) 就是一个包装机(wrap...

  • TypeScript: 类的装饰器(三)

    带参数的类的装饰器 学习 python 的同学应该知道,python 中也有装饰器,而且 python 中的众多框...

  • python学习笔记----装饰器

    装饰器 实质: 是一个函数参数:是你要装饰的函数名(并非函数调用)返回:是装饰完的函数名(也非函数调用)作用:为已...

  • Python学习笔记·装饰器

    给一个函数添加新功能 1. 装饰器介绍 如上面代码所示,装饰器是一个函数 可调用对象,接收一个函数作为参数,并将其...

  • python学习笔记-装饰器

    定义:装饰器本质是函数(装饰其他函数)就是为其他函数添加附加功能 原则:1、不能修改被装饰的函数的源代码2、不能修...

  • 【Python学习笔记】装饰器

    1.先回顾函数的几个概念 1.1 函数可以赋予变量 在上面的例子中,函数func()赋给了变量send_messa...

网友评论

    本文标题:【Python学习笔记】装饰器

    本文链接:https://www.haomeiwen.com/subject/rbrmfhtx.html