美文网首页
python学习:装饰器

python学习:装饰器

作者: 倔犟的贝壳 | 来源:发表于2021-11-06 15:58 被阅读0次

在python中,函数也是对象,我们可以把函数作为另外一个函数的返回值(也就是闭包),也可以在函数里面嵌套函数。如下:

def func_closure():
    print("func_closure")
    def get_message(message):
        print("got a message:{}".format(message))
    return get_message

send_message = func_closure()
send_message("hello world")
#输出
func_closure
got a message:hello world

func_closure()返回了get_message函数对象,并把它赋值给send_message变量,这样,send_message就相当于get_message函数了,可以像get_message()那样使用。

装饰器

装饰器将额外增加的功能,封装在自己的装饰器函数或类中;如果你想要调用它,只需要在原函数的顶部,加上 @decorator 即可。显然,这样做可以让你的代码得到高度的抽象、分离与简化。

看一个简单的装饰器

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

上述中,函数 my_decorator() 就是一个装饰器,它把真正需要执行的函数 greet() 用wrapper包裹在其中,并且改变了它的行为,但是原函数 greet() 不变。还有更简洁的表述方法,即使用@decorator:

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

@my_decorator
def greet(message):
    print(message)
 
greet("hello world")

如上,如果想要在函数前后增加额外的功能,将额外增加的功能放在修饰器中,在原函数上顶部加上@your_decorator即可。

假如我们之前是可以随便评论

#原来的提交评论
def commit_comment(text):
    print("comment is:{}".format(text))
#输出
#comment is:柯南更新了!

现在需要在评论前判断是否已登录,使用装饰器

def auth(func):
    def wrapper(text):
        print("Check if the user is logged in")
        func(text)
    return wrapper

#原来的提交评论
@auth
def commit_comment(text):
    print("comment is:{}".format(text))

commit_comment("柯南更新了!")

把检查用户登录写成一个装饰器auth,在现在需要检查用户登录的函数的顶部加上@auth即可。完全无需改动原有的代码逻辑,既简洁又方便。

装饰器的作用与意义,在于其可以通过自定义的函数或类,在不改变原函数的基础上,改变原函数的一些功能。

装饰器wrapper的参数

上面我们已经有一个不传参数的和一个传参数的装饰器。如果一个装饰器要用在几个不同的且参数个数也不同的函数上呢,参数该怎么写呢?
通常情况下,我们会把*args和**kwargs,作为装饰器内部函数 wrapper() 的参数。*args和**kwargs,表示接受任意数量和类型的参数,因此装饰器就可以写成下面的形式:

import functools
def my_decorator(func):
  @functools.wraps(func) #使方法名保持原有的方法名
  def wrapper(*args,**kwargs):
      print("wrapper of decorator")
      func(*args,**kwargs)
  return wrapper

注意上面的@functools.wraps(func),它能够使方法名保持原有的方法名,如果不加这一行的话,那方法的方法名就变成了wrapper

类装饰器

不仅函数可以做成装饰器,类也可以写成装饰器。类装饰器主要依赖于函数__call__(),每当你调用一个类的实例时,函数__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(id(self),self.num_calls))
        return self.func(*args, **kwargs)

@Count
def example(message):
    print("message is:{}".format(message))
@Count
def example2(number):
    print("number is:{}".format(number))
    
example("hello world")
example("welcome to shenzhen")
print('-------- 分割线------')
example2(1)
example2(2)

#输出
140414128260528 num of calls is: 1
message is:hello world
140414128260528 num of calls is: 2
message is:welcome to shenzhen
-------- 分割线------
140414128262688 num of calls is: 1
number is:1
140414128262688 num of calls is: 2
number is:2

从上面的例子中可以看到,类装饰器对于同一个函数,只会实例化一次。如果你输出type(example),你会发现,它的类型是Count。在函数定义的时候,它就初始化了成了Count的实例,后面每一次调用其实是Count实例的__call__函数的调用。

装饰器的嵌套

装饰器还可以嵌套,一个函数可以有多个装饰器装饰

@decorator1
@decorator2
def func(): pass

执行顺序是:decorator1->decorator2->func()

Classes can also be decorated: just like when decorating functions
官方文档上说,类也可以被装饰器装饰,如下:

@f1
class Foo: pass

但目前暂时还没想到类装饰器怎么用。

相关文章

  • 装饰器模式

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

  • python中的装饰器

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

  • TypeScript: 类的装饰器(三)

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

  • Python装饰器学习

    Python装饰器学习 Python装饰器学习(九步入门)基础部分根据此文来学习的,接下来将根据此文内容进行整理,...

  • python装饰器

    最近在学习python3,对于python的装饰器,多线程以及异步IO有点卡顿。这两天在研究python的装饰器,...

  • 什么是Python装饰器?看小编手把手教学

    讲 Python 装饰器前,我想先举个例子,虽有点污,但跟装饰器这个话题很贴切。 学习Python中有不明白推荐加...

  • python--装饰器--测试程序运行次数以及程序运行时间

    python的装饰器应用极其广泛,在python--学习的章节有所描述,在这里写两个常用的装饰器。 测试程序运行次...

  • [译] Python装饰器Part II:装饰器参数

    这是Python装饰器讲解的第二部分,上一篇:Python装饰器Part I:装饰器简介 回顾:不带参数的装饰器 ...

  • Python ☞ day 5

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

  • Python中的装饰器

    Python中的装饰器 不带参数的装饰器 带参数的装饰器 类装饰器 functools.wraps 使用装饰器极大...

网友评论

      本文标题:python学习:装饰器

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