函数式编程 之

装饰器 Decrator

1. 引子

>>> def func():
... print("abc")
...
>>> func()
abc
>>> f = func
>>> f()
abc
>>> id(func) - id(f)
0
>>> f.__name__
'func'
>>>
  • 现在由新的需求

    • func 进行扩展:每次打印 abc 之前打印当前系统时间
    • 但实现这个功能不能改动现有代码
    • => 使用装饰器

2. 简介

  • 在不改动函数代码的基础上无限制扩展函数功能的一种机制
  • 本质上讲,装饰器是一个返回函数高阶函数
  • 装饰器的使用
    • 使用 @ 语法
    • 即,在每次要扩展的函数定义前使用 @ + 函数名

3. 使用

  • 必要的导入
>>> import time
  • 先写好函数备用
>>> def print_date(f):
... def wrapper(*args, **kwargs):
... t = time.strftime("%Y-%m-%d", time.localtime())
... print(f"Date: {t}")
... return f(*args, **kwargs)
... return wrapper
...
>>>

3.1 例子1

  • 对函数进行功能扩展,每次执行函数前,打印当前日期
>>> @print_date
... def func():
... print("abc")
...
>>> func()
Date: 2019-12-20
abc
>>>
  • 装饰器的好处

    • 一处定义,多处装饰
    • 一旦被装饰,就能拥有装饰器的功能

3.2 例子2

  • 不使用 @,手动执行装饰器
>>> def manual():
... print("manual operation")
...
>>> func1 = print_date(manual)
>>> func1()
Date: 2019-12-20
manual operation
>>>

3.4 例子3

  • 不一定要像 print_date 中的 def wrapper(*args, **kwargs) 那么标准
>>> def cal_time(f):
... def wrapper(x, y):
... start = time.perf_counter_ns()
... f(x, y)
... stop = time.perf_counter_ns()
... print(f"run time: {stop - start}")
... return wrapper
...
>>> @cal_time
... def add_two_nums(x, y):
... print(f"{x} + {y} = {x + y}")
...
>>> add_two_nums(10, 20)
10 + 20 = 30
run time: 1606600
>>>
  • 注意:装饰器要写在被装饰的函数的上方

3.5 例子4

  • 两个装饰器
>>> def deco1(f):
... print("decorator1")
... def wrapper():
... print("decorator1's wrapper")
... f()
... return wrapper
...
>>> def deco2(f):
... print("decorator2")
... def wrapper():
... print("decorator2's wrapper")
... f()
... return wrapper
...
>>> @deco2
... @deco1
... def dbl_decos():
... print("double decorators")
...
decorator1
decorator2
>>> dbl_decos()
decorator2's wrapper
decorator1's wrapper
double decorators
>>>

3.6 例子5

  • 沿用例子4的思路,但是我换种写法,并把这些代码写到一个 .py 的文件中
def deco1(f):
print("先穿衬衫")
def wrapper():
print("再脱衬衫")
f()
return wrapper def deco2(f):
print("再穿西装")
def wrapper():
print("先脱西装")
f()
return wrapper @deco2
@deco1
def dbl_decos():
print("over") if __name__ == "__main__":
dbl_decos()

>>>

先穿衬衫
再穿西装
先脱西装
再脱衬衫
over
  • 装饰的过程:先执行 deco1,再执行 deco2
  • 调用的过程:先调用 deco2,再调用 deco1

[Python3] 037 函数式编程 装饰器的更多相关文章

  1. s14 第4天 关于python3.0编码 函数式编程 装饰器 列表生成式 生成器 内置方法

    python3 编码默认为unicode,unicode和utf-8都是默认支持中文的. 如果要python3的编码改为utf-8,则或者在一开始就声明全局使用utf-8 #_*_coding:utf ...

  2. python函数式编程-装饰器

    在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator). 由于函数也是一个对象,而且函数对象可以赋值给变量,所以通过变量也能调用该函数. >>> def now() ...

  3. Python实用笔记 (15)函数式编程——装饰器

    什么函数可以被称为闭包函数呢?主要是满足两点:函数内部定义的函数:引用了外部变量但非全局变量. python装饰器本质上就是一个函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外的功能,装饰 ...

  4. Python3(十) 函数式编程: 匿名函数、高阶函数、装饰器

    一.匿名函数 1.定义:定义函数的时候不需要定义函数名 2.具体例子: #普通函数 def add(x,y): return x + y #匿名函数 lambda x,y: x + y 调用匿名函数: ...

  5. [Python3] 035 函数式编程 高阶函数

    目录 函数式编程 之 高阶函数 1. 引子 2. 系统提供的高阶函数 3. functools 包提供的 reduce 4. 排序 函数式编程 之 高阶函数 把函数作为参数使用的函数,叫高阶函数 1. ...

  6. [Python3] 034 函数式编程 匿名函数

    目录 函数式编程 Functional Programming 1. 简介 2. 函数 3. 匿名函数 3.1 lambda 表达式也称"匿名函数" 3.2 lambda 表达式的 ...

  7. python3【基础】-装饰器

    要理解充分理解python的装饰器,有充分理解下述三个知识点为前提: python作用域规则 函数即对象 闭包 一.python作用域规则: 首先介绍python中的作用域规则.python的作用域规 ...

  8. Python 元编程 - 装饰器

    Python 中提供了一个叫装饰器的特性,用于在不改变原始对象的情况下,增加新功能或行为. 这也属于 Python "元编程" 的一部分,在编译时一个对象去试图修改另一个对象的信息 ...

  9. 循序渐进Python3(四) -- 装饰器、迭代器和生成器

    初识装饰器(decorator ) Python的 decorator 本质上就是一个高阶函数,它接收一个函数作为参数,然后,返回一个新函数. 使用 decorator 用Python提供的 @ 语法 ...

随机推荐

  1. React使用JSX语法

    目录: 1.在React项目中启用JSX语法 2.在JSX中写js代码 3.使用JSX注意事项 1.在React项目中启用JSX语法  <--返回目录 JSX语法:符合xml规范的js语法 JS ...

  2. 配置https证书

    官网: https://certbot.eff.org/lets-encrypt/ubuntubionic-nginx ssl安装检测工具: https://www.myssl.cn/tools/ch ...

  3. 安装交叉工具链arm-linux-gcc

    基本步骤如下: (1)建立目录 $ sudo mkdir /usr/local/arm (2)复制文件 文件arm-linux-gcc-4.4.3.tar.gz,放在/var/ftp中,进入ftp,$ ...

  4. Volatile关键字的两个作用

    1.保证修饰的变量对所有线程的可见性,这里的“可见性”是指当一条线程修改了这个值,新值对于其他线程来说是可以立即得知的. 2.禁止指令重新排序化

  5. Linux-expect脚本-编写一个expect脚本

    1.声明expect #!/usr/bin/expect -f 2.设置超时时间,获取参数 set ip [lindex $argv 0 ] //接收第一个参数,并设置IP set password ...

  6. $\LaTeX$数学公式大全9

    $9\ Math\ mode\ accents$ $\acute{a}$ \acute{a} $\breve{a}$ \breve{a} $\ddot{a}$ \ddot{a} $\grave{a}$ ...

  7. Android学习_数据持久化

    数据持久化:将内存中的瞬时数据存储到设备中 1. 文件存储 存储一些简单的文本数据或二进制数据. 核心:Context类提供的openFileOutput()和openFileInput()方法,然后 ...

  8. BZOJ3331压力

    码量略大. 题意就是求路径必经点. tarjan缩点,所有的非割点只有是起点终点时才必经,直接开个ans数组就OK了. 至于割点,因为缩完点之后的图是vDcc和割点共同组成的,而且题目说连通,那就是棵 ...

  9. websocket聊天体验(二)

    上一篇说到后续可以支持:最近历史.表情+图片,顺便还实现了简易的音频和视频.暂时没有实现实时语音对讲,有待后续再研究.点开在线聊天页面,即可看到最近历史记录(18条). 聊天的底层数据都是基于txt文 ...

  10. 实验四《Android程序设计》实验报告封面

    实验四<Android程序设计>实验报告封面 课程:Java程序设计 班级:1753班 姓名:许钰玮 学号:20175329 指导教师:娄嘉鹏 实验日期:2019年5月13日 实验时间:1 ...