装饰器

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

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. Java 8 访问接口的默认方法

    Java 8 API提供了很多全新的函数式接口来让工作更加方便,有一些接口是来自Google Guava库里的,即便你对这些很熟悉了,还是有必要看看这些是如何扩展到lambda上使用的. 一.Opti ...

  2. 美团面试官问我一个字符的String.length()是多少,我说是1,面试官说你回去好好学一下吧

    本文首发于微信公众号:程序员乔戈里 public class testT { public static void main(String [] args){ String A = "hi你 ...

  3. 20191107-8 beta week 2/2 Scrum立会报告+燃尽图 07

    此作业要求参见 http://edu.cnblogs.com/campus/nenu/2019fall/homework/9960 小组名称:“组长”组 组长:杨天宇 组员:魏新,罗杨美慧,王歆瑶,梅 ...

  4. MSXM简单的使用

    // xml.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <string> #include <at ...

  5. 洛谷$P2168\ [NOI2015]$荷马史诗 贪心

    正解:贪心 解题报告: 传送门$QwQ$ 昂这个就哈夫曼树板子题鸭$QwQ$,只是从二叉变成多叉了$QwQ$ 考虑用类似合并果子的方法?就从两个变成$k$个了嘛,一样的鸭,然后就做完了$QwQ$ 注意 ...

  6. 初次在cmd使用git命令上传项目至github方法(笔记)

    在一切开始之前,先推荐一个git简易工具书--Git_Cheat_Sheet,非常适合新手.自行搜索即可,也有热心者提供了中文版. 一.下载 Git 从Git官网下载Git安装包 https://gi ...

  7. .NetCoreApi容器与MySql容器互联

    构建Mysql容器 1.拉取mysql镜像 docker pull mysql/mysql-server 2.创建mysql镜像 docker run -d -p 3306:3306 -e MYSQL ...

  8. array_diff 大bug

    $aa = array("手机号", "first","keyword1","keyword2","keywo ...

  9. window bat批处理 实用脚本

    一行一行读取txt里的内容 @echo off for /f %%i in (C:\Users\86132\Desktop\name.txt) do ( echo %%i>>name2.t ...

  10. 2018湘潭邀请赛 AFK题解 其他待补...

    A.HDU6276:Easy h-index Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/O ...