装饰器

举报
darkpard 发表于 2022/03/17 08:07:52 2022/03/17
【摘要】 自学python时,觉得装饰器是个很难理解的概念,后来也一直没机会使用它。最近看到公众号早起Python的《人人都能看懂的Python装饰器入门教程!》,很受启发,撰文记之。1. 定义与原则先来看装饰器的定义:一种增加函数功能的简单方法,可以快速地给不同的函数或类插入相同的功能。它有两个原则1)不能修改被装饰函数的原代码2)不能修改被装饰函数的调用方式2. 案例定义并不是很好理解,我们先来看...

自学python时,觉得装饰器是个很难理解的概念,后来也一直没机会使用它。最近看到公众号早起Python的《人人都能看懂的Python装饰器入门教程!》,很受启发,撰文记之。

1. 定义与原则

先来看装饰器的定义:

一种增加函数功能的简单方法,可以快速地给不同的函数或类插入相同的功能。

它有两个原则

1)不能修改被装饰函数的原代码

2)不能修改被装饰函数的调用方式

2. 案例

定义并不是很好理解,我们先来看一个案例。

比如我们有一个猫的方法和一个狗的方法如下:

def cat():
    print('This is a cat.')
    
def dog():
    print('This is a dog.')

它们的调用方法和调用结果如下:

图片

现在我们想要猫的方法在打印“This is a cat.”前先打印一个“This is an animal.”,要狗的方法在打印“This is a dog.”前也先打印一个“This is an animal.”。我们可以用装饰器的方式来实现,即写一个装饰器函数如下:

def animal(func):
    def print_():
        print('This is an animal.')
        func()
    return print_

从两个函数的原代码、调用和调用结果可以看到,这是符合装饰器的原则的。

图片

当然,它其实还不是完整的装饰器,请容我稍后再议。

3. 原理

装饰器的基本原理其实是以函数为参数的调用与返回,如下图所示:

图片

就是调用animal函数是以cat和dog函数名作为参数,返回结果是print_函数。

3.1. functools

但是,上述经过装饰器装饰后cat或dog方法的调用发生了一个变化。我们原来想要调用cat方法或dog方法,但结果却成了调用print_方法。

图片

为此python提供了一个库叫functools,掉用它里面的wraps来装饰print_函数,就能解决问题。只需要将装饰器做出下改动即可:

import functools
def animal(func):
    @functools.wraps(func)
    def print_():
        print('This is an animal.')
        func()
    return print_

图片

至于functools.wraps是如何达到这个功能的,网上也有很多资料,我们这里就只研究如何让电灯发光,不讨论如何发电了。

3.2. 传参

但还有一个问题是我们所关心的,那就是如何传参。

当我们的cat方法和dog方法带有参数时,装饰器是如何传参的?比如我们的cat方法如下:

def cat(name):
    print('This is ' + name + '.')

这就要求我们的print_方法同样进行传参,需要进一步改写如下:

import functools
def animal(func):
    @functools.wraps(func)
    def print_(*args, **kwargs):
        print('This is an animal.')
        func(*args, **kwargs)
    return print_

图片

参考文献:

  1. https://mp.weixin.qq.com/s/gGcBazI8Qr31RhiB9EhOVA
  2. https://www.cnblogs.com/wendyw/p/9724231.html
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。