Python学习笔记:装饰器
Python 装饰器的基本概念和应用
- 代码编写要遵循开放封闭原则,虽然在这个原则是用的面向对象开发,但是也适用于函数式编程,简单来说,它规定已经实现的功能代码不允许被修改,但可以被扩展,即:
- 封闭:已实现的功能代码块
- 开放:对扩展开发
装饰器是 Python 高阶函数的语法糖,可以为已经存在的对象添加额外的功能,比如:
- 引入日志
- 函数执行时间统计
- 执行函数前预备处理
- 执行函数后清理功能
- 权限校验等场景
- 缓存
Python 装饰器的基本实现
装饰器的例程:
#!/usr/bin/env python3
#-*- coding:utf-8 -*-
#File Name:04_decorator_simple.py
#Created Time:2019-01-09 15:24:38 import time def timefun(func):
# wrapped_fun 即为闭包, func 为要装饰的函数
def wrapped_fun():
start_time = time.time()
func()
end_time = time.time()
print("%s\t运行用时 %f s" % (func.__name__, end_time - start_time))
return wrapped_fun # 返回内部函数的引用 def foo1():
for i in range(10000):
pass @timefun # 相当于 foo = timefun(foo)
def foo():
for i in range(100000):
pass if __name__ == "__main__":
foo1 = timefun(foo1)
foo1()
foo()
装饰器例程
foo1 运行用时 0.000491 s
foo 运行用时 0.002976 s
装饰器例程的运行结果
运行过程分析见下图:
Python 装饰器实现的基础为闭包,其会在闭包中调用目标函数,关于闭馆的详细内容,请参考 Python 学习笔记:闭包
Python 装饰器的使用
多个装饰器
#!/usr/bin/env python3
#-*- coding:utf-8 -*-
#File Name:05_decorator_multi.py
#Created Time:2019-01-09 15:55:31 def make_body(func):
"""添加 body"""
def wrapped():
return "<b>" + func() + "</b>"
return wrapped def make_italic(func):
"""设置为斜体"""
def wrapped():
return "<i>" + func() + "</i>"
return wrapped # 相当于 make_body(make_italic(foo))
@make_body
@make_italic
def foo():
return "Hello World" def foo1():
return "Hello Python" if __name__ == "__main__":
print(foo())
foo1 = make_body(make_italic(foo1))
print(foo1())
01 多个装饰器
<b><i>Hello World</i></b>
<b><i>Hello Python</i></b>
01 多个装饰器——运行结果
多个装饰器的运行过程分析:
含有不定长参数
#!/usr/bin/env python3
#-*- coding:utf-8 -*-
#File Name:06_decorator_multi_var.py
#Created Time:2019-01-09 16:20:30 from time import ctime def timefun(func):
def wrapped_func(*args, **kwargs):
print("%s called at %s" % (func.__name__, ctime()))
print("wrapped_func: ", end="")
print(args, kwargs)
func(*args, **kwargs) # 拆包
return wrapped_func @timefun
def foo(a,b,*args, **kwargs):
print("foo: %s, %s, %s, %s" %(a, b, args, kwargs)) if __name__ == "__main__":
foo(1,2,3,4,5, tmp=2)
02 含有不定长参数
foo called at Wed Jan 9 16:32:48 2019
wrapped_func: (1, 2, 3, 4, 5) {'tmp': 2}
foo: 1, 2, (3, 4, 5), {'tmp': 2}
02 含有不定长参数——运行结果
带有返回值
#!/usr/bin/env python3
#-*- coding:utf-8 -*-
#File Name: 07_decorator_multi_retrun.py
#Created Time:2019-01-09 16:20:30 from time import ctime def timefun(func):
def wrapped_func(*args, **kwargs):
print("%s called at %s" % (func.__name__, ctime()))
print("wrapped_func: ", end="")
print(args, kwargs)
return func(*args, **kwargs) # 此处如何没有 return,则26行会输出 None
return wrapped_func @timefun
def foo(a,b,*args, **kwargs):
print("foo: %s, %s, %s, %s" %(a, b, args, kwargs))
return "Hello world!" if __name__ == "__main__":
print(foo(1,2,3,4,5, tmp=2))
03带有返回值
foo called at Wed Jan 9 16:38:05 2019
wrapped_func: (1, 2, 3, 4, 5) {'tmp': 2}
foo: 1, 2, (3, 4, 5), {'tmp': 2}
Hello world!
03带有返回值——运行结果
装饰器中设置外部变量
#!/usr/bin/env python3
#-*- coding:utf-8 -*-
#File Name: 08_decorator_outside_var.py
#Created Time:2019-01-09 16:20:30 def timefun_arg(outside_var="Hello"):
def timefun(func):
def wrapped_func(*args, **kwargs):
print("wrapped_func: %s" % outside_var)
return func(*args, **kwargs)
return wrapped_func
return timefun @timefun_arg()
def foo(a,b,*args, **kwargs):
return "foo: Hello world!" @timefun_arg("Python") # 相当于 foo1 = timefun_arg("Python")(foo1)
def foo1(a,b,*args, **kwargs):
return "foo1: Hello world!" if __name__ == "__main__":
print(foo(1,2,3,4,5, tmp=2))
print(foo1(1,2,3,4,5, tmp=2))
04 装饰器中设置外部变量
定义多层函数,相当于双层的装饰器。
wrapped_func: Hello
foo: Hello world!
wrapped_func: Python
foo1: Hello world!
04装饰器中设置外部变量——运行结果
类装饰器
#!/usr/bin/env python3
#-*- coding:utf-8 -*-
#File Name:09_decorator_class.py
#Created Time:2019-01-09 16:53:33 class Test(object):
def __init__(self, func):
print("******初始化******")
print("Called by %s." % func.__name__)
self.func = func def __call__(self):
return self.func() @Test # 相当于 foo = Test(foo)
def foo():
return "Hello world!" def foo1():
return "Hello python!" if __name__ == "__main__":
print(foo())
foo1 = Test(foo1)
print(foo1())
05 类装饰器
类对象借助 __call__() 魔术方法,即可实现相应的类装饰器
******初始化******
Called by foo.
Hello world!
******初始化******
Called by foo1.
Hello python!
05 类装饰器运行结果
Python学习笔记:装饰器的更多相关文章
- python学习笔记--装饰器
1.首先是一个很无聊的函数,实现了两个数的加法运算: def f(x,y): print x+y f(2,3) 输出结果也ok 5 2.可是这时候我们感觉输出结果太单一了点,想让代码的输出多一点看起来 ...
- Python学习笔记--装饰器的实验
装饰器既然可以增加原来函数的功能,那能不能改变传给原函数的参数呢? 我们实验一下,先上代码: #!/usr/bin/env python # -*- coding: utf-8 -*- # @Date ...
- Python学习笔记: 装饰器Decorator
介绍 装饰器是对功能函数的加强. 在原来的功能函数之外,另外定义一个装饰器函数,对原来的功能函数进行封装(wrapper)并在wrapper的过程中增加一些辅助功能. 应用场景 如下场景: 业务函数f ...
- python 学习分享-装饰器篇
本篇内容为偷窃的~哈哈,借用一下,我就是放在自己这里好看. 引用地址:http://www.cnblogs.com/rhcad/archive/2011/12/21/2295507.html 第一步: ...
- python学习之装饰器-
python的装饰器 2018-02-26 在了解python的装饰器之前我们得了解python的高阶函数 python的高阶函数我们能返回一个函数名并且能将函数名作为参数传递 def outer() ...
- python学习day14 装饰器(二)&模块
装饰器(二)&模块 #普通装饰器基本格式 def wrapper(func): def inner(): pass return func() return inner def func(): ...
- Python学习 :装饰器
装饰器(函数) 装饰器作为一个函数,可以为其他函数在不修改原函数代码的前提下添加新的功能 装饰器的返回值是一个函数对象.它经常用于有切面需求的场景,比如:插入日志.性能测试.事务处理.缓存.权限校验等 ...
- python学习之-- 装饰器
高阶函数+嵌套函数 == 装饰器 什么是装饰器: 其实也是一个函数. 功能:为其他的函数添加附加功能 原则:不能修改被装饰的函数的源代码和调用方式 学习装饰器前首先要明白以下3条事项: 1:函数 即 ...
- 6月4日 python学习总结 装饰器复习
1. 装饰器的原理以及为什么要使用装饰器 在代码运行期间动态增加功能的方式,称之为"装饰器"(Decorator). 在不影响原代码结构的情况下为其添加功能 2. 装饰器的基本 ...
- 学习笔记——装饰器模式Decorator
装饰器模式,最典型的例子. 工厂新开了流水线,生产了手机外壳,蓝天白云花色.刚准备出厂,客户说还要印奶牛在上面,WTF…… 时间上来不及,成本也不允许销毁了重来,怎么办?弄来一机器A,专门在蓝天白云的 ...
随机推荐
- Java学习笔记--继承和多态(上)
1.通过继承来开发超类(superclass) 2.使用super 关键词唤起超类的构造方法 3.在超类中覆盖方法 4.区分override和overload 5.在Object类中探索toStrin ...
- Arduino连接pH计
关于arduino连接ph,核心的东西就是对ph传感器返回的信号值进行一系列的操作,注意因为返回的信号很弱,而且外部环境对其影响也很大,所以需要在电路设计上加入一些功能,比如信号放大.滤波等,电路设计 ...
- AJPFX关于面向对象之封装,继承,多态 (上)
Java是一种面向对象的语言,这是大家都知道的,他与那些像c语言等面向过程语言不同的是它本身所具有的面向对象的特性--封装,继承,多态,这也就是传说中的面向对象三大特性 一:从类和对象开始说起: Oo ...
- spring boot 监控与管理(actuator)
Spring POMs 中提供了一个特殊的依赖模块,即spring-boot-starter-actuator,我们只需要在我们的POM中添加依赖即可 <!-- 监控 管理 --> < ...
- Nginx 安装(CentOS )非yum安装
Nginx 安装(CentOS ) 一.安装编译工具及库文件 yum -y install make zlib zlib-devel gcc-c++ libtool openssl openssl-d ...
- CF1182E Product Oriented Recurrence
思路: fn = can * f1xn * f2yn * f3zn, 首先dp计算指数部分an = an-1 + an-2 + an-3 + 2 * n - 6, 而an-1 = an-2 + an- ...
- SID1190471 / 烦人的幻灯片 暴力出奇迹 !!!!!!!!!!!!!!!!!!
PID221 / 烦人的幻灯片 ☆ 提交你的代码 查看讨论和题解 你还木有做过哦 我的状态 查看最后一次评测记录 质量还不能统计出来哦~ 题目评价 质量 无 ★★★★★ ★★★★☆ ★ ...
- [转]latex输入数学符号速查
基本运算 乘法 x×y x \times y 乘方 23x 2^{3x} 平方根 x+y−−−−−√ \sqrt {x + y} 除法 x÷y x \div y 分数 xy \frac{x}{y} 异 ...
- String.format()的用法
string.format()用法 2011-06-21 14:58:57| 分类: 工作笔记 | 标签:string format用法 |字号大中小 订阅 1.格式化货币(跟系统的环境有关 ...
- meterpreter > screenshot
meterpreter > screenshotScreenshot saved to: /opt/metasploit/msf3/wLafQYhx.jpegmeterpreter > / ...