装饰器

装饰器是干什么用的?
装饰器可以在不修改某个函数的情况下,给函数添加功能。
形象点来说,从前有一个王叔叔,他一个人住在家里,每天打扫家,看书。于是定义如下一个函数:

def uncle_wang():
sweeping()
reading()

后来呢,有一天,大头儿子一家搬到了王叔叔隔壁 。根据剧情,一天,大头儿子的妈妈请王叔叔来家里吃饭,那么,王叔叔的日程就添加了“去隔壁吃饭”这一项,但是又不能修改王叔叔之前的日程,怎么实现?这时,就可以给王叔叔添加一个装饰器,给这个装饰器起个名字,姑且就叫neighbor,然后就写成这样:

@neighbor
def uncle_wang():
sweeping()
reading()

然后王叔叔去大头儿子家吃饭就提上日程啦,哈哈。(只是吃饭哦,不要想多了(⊙v⊙))
这个neighbor其实也是个函数,参数就是uncle_wang(没错,可以把函数名当成参数传来传去,还能当做返回值),在装饰器里面实现“去隔壁吃饭”:

def neighbor(func):
eat_next_door() # 自定义函数,去隔壁吃饭
return func # 原来的函数不变,直接返回

最后是执行,直接运行uncle_wang()即可

# 执行函数
uncle_wang() # 相当于不加装饰器,直接执行 neighbor(uncle_wang)()

这感觉就像是用neighbor装饰了uncle_wang,丰富了王叔叔的生活,从此变成了隔壁老王。实现方式就是套娃,给uncle_wang套个neighbor,变成neighbor(uncle_wang)(这整个东西是个函数名),然后调用这个函数: neighbor(uncle_wang)(),形如:函数名()
在Python里,这个套娃的操作简化成了装饰器,直接在原函数上面添加@neighbor,然后调用的时候还是写成uncle_wang(),但是这个装饰过的王叔叔已经不是原来的王叔叔了,他现在其实是隔壁老王。

王叔叔的新日程搞定了,但是还有个问题,就是顺序。现在的日程顺序相当于:

eat_next_door()
sweeping()
reading()

请人吃饭当然是吃晚饭啦,所以eat_next_door()需要排在最后面,而neighbor函数不能先返回(return func)然后才执行eat_next_door(),众所周知,函数返回了就结束了,后面的东西都不管了。
所以,继续套娃,再搞个函数进去,写成这样:

def neighbor(func):
def wrapper(): # 套娃函数,注意这里是定义,不是执行
func() # 相当于不带装饰器的 uncle_wang()
eat_next_door() # 自定义函数,去隔壁吃饭
return wrapper # 直接返回套娃函数

这样顺序就对了,王叔叔很满意~
现在这个装饰器基本成型了,但是现在还不能处理原函数的参数和装饰器函数的参数,继续改进的实现方式可以去看廖雪峰老师的教程,写得很不错,我就是从那学来的。

附上完整代码:

# !/usr/bin/env python3
# -*- coding: utf-8 -*- def sweeping():
print('sweeping') def reading():
print('reading') def eat_next_door():
print('eat_next_door') def neighbor(func):
def wrapper(): # 套娃函数,注意这里是定义,不是执行
func() # 相当于不带装饰器的 uncle_wang()
eat_next_door() # 自定义函数,去隔壁吃饭
return wrapper # 直接返回套娃函数 @neighbor
def uncle_wang():
sweeping()
reading() if __name__ == "__main__":
uncle_wang()

(嗨,又水了一篇,之前还说要测一下手动实现和库函数实现的二分查找的耗时差距,正事还是放到下次吧……)

参考资料:

  1. 装饰器 - 廖雪峰的官方网站
  2. 隔壁老王的梗是怎么来的 - 知乎

Python里的装饰器的更多相关文章

  1. 对python里的装饰器

    内裤可以用来遮羞,但是到了冬天它没法为我们防风御寒,聪明的人们发明了长裤,有了长裤后宝宝再也不冷了,装饰器就像我们这里说的长裤,在不影响内裤作用的前提下,给我们的身子提供了保暖的功效. 再回到我们的主 ...

  2. python高级之装饰器

    python高级之装饰器 本节内容 高阶函数 嵌套函数及闭包 装饰器 装饰器带参数 装饰器的嵌套 functools.wraps模块 递归函数被装饰 1.高阶函数 高阶函数的定义: 满足下面两个条件之 ...

  3. 第二篇:python高级之装饰器

    python高级之装饰器   python高级之装饰器 本节内容 高阶函数 嵌套函数及闭包 装饰器 装饰器带参数 装饰器的嵌套 functools.wraps模块 递归函数被装饰 1.高阶函数 高阶函 ...

  4. Day11 Python基础之装饰器(高级函数)(九)

    在python中,装饰器.生成器和迭代器是特别重要的高级函数   https://www.cnblogs.com/yuanchenqi/articles/5830025.html 装饰器 1.如果说装 ...

  5. 【Python】【装饰器】

    Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现了say_hello()和say_goodbye()两个函数. def sa ...

  6. Python 语法糖装饰器的应用

    Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现了say_hello()和say_goodbye()两个函数. def sa ...

  7. python进阶04 装饰器、描述器、常用内置装饰器

    python进阶04 装饰器.描述器.常用内置装饰器 一.装饰器 作用:能够给现有的函数增加功能 如何给一个现有的函数增加执行计数的功能 首先用类来添加新功能 def fun(): #首先我们定义一个 ...

  8. python 多个装饰器的调用顺序

    python 多个装饰器的调用顺序 一般情况下,在函数中可以使用一个装饰器,但是有时也会有两个或两个以上的装饰器.多个装饰器装饰的顺序是从里到外(就近原则),而调用的顺序是从外到里(就远原则). 原代 ...

  9. python函数闭包-装饰器-03

    可调用对象 callable()  # 可调用的(这个东西加括号可以执行特定的功能,类和函数) 可调用对象即  callable(对象)  返回为  True  的对象 x = 1 print(cal ...

随机推荐

  1. ES6学习----let、const、解构赋值、新增字符串、模板字符串、Symbol类型、Proxy、Set

    这篇es6的学习笔记来自于表哥 表严肃,是我遇到过的讲课最通透,英文发音最好听的老师,想一起听课就去这里吧 https://biaoyansu.com/i/hzhj1206 ES6就是JS6,JS的第 ...

  2. 【题解】SDOI2010所驼门王的宝藏(强连通分量+优化建图)

    [题解]SDOI2010所驼门王的宝藏(强连通分量+优化建图) 最开始我想写线段树优化建图的说,数据结构学傻了233 虽然矩阵很大,但是没什么用,真正有用的是那些关键点 考虑关键点的类型: 横走型 竖 ...

  3. 1094 谷歌的招聘 (20 分)C语言

    2004 年 7 月,谷歌在硅谷的 101 号公路边竖立了一块巨大的广告牌(如下图)用于招聘.内容超级简单,就是一个以 .com 结尾的网址,而前面的网址是一个 10 位素数,这个素数是自然常数 e ...

  4. Python for Data Analysis 学习心得(一) - numpy介绍

    一.简介 Python for Data Analysis这本书的特点是将numpy和pandas这两个工具介绍的很详细,这两个工具是使用Python做数据分析非常重要的一环,numpy主要是做矩阵的 ...

  5. k8s-自动安装

    操作环境: centos7.3 node102-master-192.168.100.102 node103-node1-192.168.100.103 node104-node2-192.168.1 ...

  6. Date、Time类型拼接成字符串

    Date.Time类型拼接成字符串 语言用的是kotlin,和Java类似 var time = "" val sdf1 = SimpleDateFormat("yyyy ...

  7. (01)大话设计模式-简单工厂-java实现

    1.运算接口 public interface Operation { public double getResult(double NumberA , double NumberB); } 2.加减 ...

  8. Java截图小程序源码

    Java编写的全屏截图小程序 package cnom.test.testUtils; import java.awt.AWTException; import java.awt.Dimension; ...

  9. Java防锁屏小程序

    为防止系统桌面自动锁屏,只需打成jar包,写个批处理程序start.bat,双击执行保持dos窗口执行即可,无其他影响. 程序设计为每30秒动一次鼠标,可根据需要调整. 附代码: package ma ...

  10. Java程序员必备基础:内部类解析

    前言 整理了一下内部类的相关知识,算是比较全,比较基础的,希望大家一起学习进步. 一.什么是内部类? 在Java中,可以将一个类的定义放在另外一个类的定义内部,这就是内部类.内部类本身就是类的一个属性 ...