python学习笔记-装饰器

AlgoNebula
• 阅读 1725

怎么理解python中的装饰器

一个比喻

知乎上有一个比较形象的比喻 https://www.zhihu.com/questio...
人类穿着内裤很大程度上是为了遮羞和对关键部位进行保护,但是却不能提供保暖。因此我们还需要穿着长裤。长裤就是对内裤功能的补充,却不影响内裤本身的功能。

装饰器介绍

python中的装饰器的目的是为一个目标函数添加额外的功能却不修改函数本身。装饰器的本身其实是一个特殊的函数。主要的应用场景有插入日志,性能测试、事务处理等。

下面我们来举一个简单的例子一步一步了解一下。

我们首先写了三个函数,即对两个数做加减乘的操作并打印:

def func_sum(x, y):
    print x+y


def func_minus(x, y):
    print x - y


def func_multiply(x, y):
    print x*y

但是我们现在有了新需求,就是需要在日志中打印所有加、减、乘操作时的时间。

import logging
import time


def func_sum(x, y):
    logging.warning(time.strftime("%Y-%m-%d %H:%M:%S %Z", time.localtime(time.time())))
    print x+y


def func_minus(x, y):
    logging.warning(time.strftime("%Y-%m-%d %H:%M:%S %Z", time.localtime(time.time())))
    print x - y


def func_multiply(x, y):
    logging.warning(time.strftime("%Y-%m-%d %H:%M:%S %Z", time.localtime(time.time())))
    print x*y

显然像上面这样修改每一个函数,在每一个函数中添加重复代码是不合适的。真正理想的是我们可以定义一个函数,专门用来输出日志,输出完日志后,再执行真正的函数。

import logging
import time


def func_sum(x, y):
    print x+y


def func_minus(x, y):
    print x - y


def func_multiply(x, y):
    print x*y


def logging_first(func):
    logging.warning(time.strftime("%Y-%m-%d %H:%M:%S %Z", time.localtime(time.time())))
    return func

logging_first(func_sum)(20,30)

但是上面这中实现方式也存在着种种问题。

  1. log其实是logging_first(func_sum)时就打印了,而不是进行加、减、乘的时候打印的。

  2. 对加减乘函数的调用都需要修改成logging_first(func_sum)(20,30)类似方式。
    那么有啥更好的解决方式呢?

装饰器

import logging
import time


def func_sum(x, y):
    print x+y


def func_minus(x, y):
    print x - y


def func_multiply(x, y):
    print x*y


def logging_first(func):
    def wrapper(x, y):
        logging.warning(time.strftime("%Y-%m-%d %H:%M:%S %Z", time.localtime(time.time())))
        return func(x, y)
    return wrapper

logging_first(func_sum)(20, 30)

代码像上面这么写,可以较好地解决了上面提到的第一个问题。调用logging_first返回的是wrapper函数。执行wrapper函数的时候先打印log,然后马上执行了传入的func函数。

但是调用方式依旧需要修改成logging_first(func_sum)(20, 30)这种方式。
幸好,python给我们提供了优雅的语法糖。
我们可以将上面的代码修改成以下形式。

import logging
import time


def logging_first(func):
    def wrapper(x, y):
        logging.warning(time.strftime("%Y-%m-%d %H:%M:%S %Z", time.localtime(time.time())))
        return func(x, y)

    return wrapper


@logging_first
def func_sum(x, y):
    print x + y


@logging_first
def func_minus(x, y):
    print x - y


@logging_first
def func_multiply(x, y):
    print x * y

func_sum(20, 30)
func_minus(20, 30)
func_multiply(20, 30)

装饰器语法糖放在函数前面,相当于执行了logging_firts(func_sum)等。

点赞
收藏
评论区
推荐文章
Python进阶者 Python进阶者
3年前
编写一个闭包函数,要实现的功能是计数功能
大家好,我是皮皮。一、前言前几天在Python最强王者交流群有个叫【杰】的粉丝问了一个Python装饰器的问题,这里拿出来给大家分享下,一起学习下。二、解决过程这里【东哥】给出了解答,其实这个题目就是在考你装饰器的内容。代码如下:count0defwrapper(func):definner(args,kwargs):g
Irene181 Irene181
4年前
恶补了 Python 装饰器的六种写法,你随便问~
大家好,我是明哥。今天给大家分享一下关于装饰器的知识点,内容非常干,全程高能,认真吸收看完,一定会对装饰器有更深的理解。Hello,装饰器装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。装饰
Irene181 Irene181
4年前
浅析Python装饰器中的@property
一、使用@property优点将类方法转换为类属性,可以用来直接获取属性值或者对属性进行赋值。案例分析例:classExam(object):definit(self,score):self.scorescoredefgetscore(self):returnself.scoredef
Bill78 Bill78
4年前
python装饰器详解
你会Python嘛?我会!那你给我讲下Python装饰器吧!Python装饰器啊?我没用过哎以上是我一个哥们面试时候发生的真实对白。\分割线
Stella981 Stella981
3年前
Python何时执行装饰器
装饰器的一个关键特性是,它们在被装饰的函数定义之后立即运行。这通常是在导入时(即Python加载模块时),如示例72中的registration.py模块所示。  示例72registration.py模块registrydefregister(func):print(
Wesley13 Wesley13
3年前
(二十九) 初遇python OOP面向对象编程
各位读者大大们大家好,今天学习python的面向对象编程属性装饰器,并记录学习过程欢迎大家一起交流分享。!(https://oscimg.oschina.net/oscnet/2bffb0067c4967eca2188c825154f2e4a5d.jpg)新建一个python文件命名为py3\_oop6.py,在这个文件中进行操作代
Stella981 Stella981
3年前
Python进阶笔记(2)
'''装饰器装饰器(Decorators)是Python的一个重要部分。简单地说:他们是修改其他函数的功能的函数。他们有助于让我们的代码更简短。如果已经接触过FLASK的,想想路由功能。如果没有接触过FLASK的,建议学习下。''''''各种推导式(compre
Stella981 Stella981
3年前
Python 装饰器(Decorator)
Python 装饰器(Decorator)装饰模式有很多经典的使用场景,例如插入日志、性能测试、事务处理等等,有了装饰器,就可以提取大量函数中与本身功能无关的类似代码,从而达到代码重用的目的。下面就一步步看看Python中的装饰器。装饰器本身是一个Python函数,他可以让其他函数在不需要做任何代码变动
Stella981 Stella981
3年前
Python装饰器用法实例总结
一、装饰器是什么python的装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。简单的说装饰器就是一个用来返回函数的函数。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离
3A网络 3A网络
2年前
Golang 常见设计模式之装饰模式
Golang常见设计模式之装饰模式想必只要是熟悉Python的同学对装饰模式一定不会陌生,这类Python从语法上原生支持的装饰器,大大提高了装饰模式在Python中的应用。尽管Go语言中装饰模式没有Python中应用的那么广泛,但是它也有其独到的地方。接下来就一起看下装饰模式在Go语言中的应用。简单装饰器我们通过一个简单的例子来