Python学习之路6 - 装饰器
装饰器
定义:本质是函数,(装饰其他函数)就是为其他函数添加附加功能。
原则:1.不能修改被装饰的函数的源代码
2.不能修改被装饰的函数的调用方式
实现装饰器的知识储备:
1.函数即“变量”
2.高阶函数(满足下列条件之一就是高阶函数)
- a:把一个函数名当作形参传给另一个函数(在不修改被装饰函数源代码的情况下修改其功能,但是调用方式变了)
- b:返回值中包含函数名(不修改函数的调用方式,而修改函数功能)
3.嵌套函数
总结:
高阶函数+嵌套函数=>装饰器
1. 函数即变量
def bar(): #这里定义个函数
print('this is bar...') func = bar #将函数当变量一样赋值给func func() #这是func加上()就可以当函数用了
这就是函数即变量。
2. 高阶函数
a:把一个函数名当做形参传给另一函数(在不修改被装饰函数源代码的情况下修改其他功能,但是调用方式变了)
def bar():
print('this is bar...')
bar()
print('----------------------------------')
def test(func): #在这里增加了功能
print(func)
test(bar) #但是这里修改了调用方式
b:返回值中包含函数名(不修改函数的调用方式,而修改函数功能)
def bar():
print('this is bar...')
bar()
print('----------------------------------')
def test(func): #在这里增加了功能
print(func)
return func #这里返回了函数地址
bar = test(bar) #将函数地址赋给一个变量,该变量和传入函数同名
bar() #这个变量加上括号,就可以当函数用了,同时又没有修改函数的调用方式
3. 嵌套函数
x = 1
def test1():
def test2():
def test3():
x = 3
print(x)
test3()
test2()
test1()
像这样在一个函数里面定义一个函数就叫做嵌套函数。
现在三个知识点都已经解释过了,下面先实现一个原始版的装饰器。
原始版装饰器
import time def test1(): #这里是被装饰的函数
time.sleep(1)
print("this is test1....") def timer(func): #这里是装饰器函数
def deco():
strat = time.time()
func()
stop = time.time()
print("run time %s" %(stop-strat))
return deco test1 = timer(test1) test1()
这个装饰器的功能是测试test1函数的运行时间,deco函数有这个功能,所以这里其实我想运行的是deco函数,timer()函数的返回值也就是deco函数的地址;同时deco函数想要运行也要满足另一个条件,那就是需要调用timer函数,只有当timer函数运行的时候timer函数里面写的那些东西才会生效或者说被激活,deco函数才会定义成功。到此,test=timer(test1)这句代码的意思就是,先调用timer函数让deco函数的定义生效,同时将要被装饰的函数test1函数的地址传入,让deco函数里面的func函数生效,这是timer函数又会将deco函数的地址返回,并将地址赋值给test1这个变量。然后下面的test1后面加上括号,变成test1()的形式,就可以运行了。这样一个原始版的装饰器就写完了。
接下来要写一个真实装饰器的实例
import time def timer(func):
def deco():
start_time = time.time()
func()
stop_time = time.time()
print('the func run time is %s' %(stop_time-start_time))
return deco @timer #这里等于 test = timer(test),要装饰哪个函数,就在哪个函数前面加上这个
def test():
time.sleep(2)
print('this is test...') test()
上面这些都是一些比较基本的,如果装饰有参数的函数且参数的个数还都不一定怎么办呢?下面写一个高级案例 -- 有参数的装饰器
高级案例 -- 有参数装饰器
import time def timer(func):
def deco(*args,**kwargs): #在这里接收参数
start_time = time.time()
func(*args,**kwargs)
stop_time = time.time()
print('the func run time is %s' %(stop_time-start_time))
return deco @timer
def test(name):
time.sleep(2)
print('this is test...',name) test('vector')
如果原test函数里面有返回值,被装饰后我们打印它print(test()),结果会是none。因为这时的test=deco,而deco没有返回值,所以打印不出来。这样就会出现一个问题,如果test函数有返回值,test函数的一个功能(返回值)就会被弄丢了。
解决办法看下面案例。
高高级案例 -- 有返回值的装饰器
import time
def timer(func):
def deco(*args,**kwargs):
start_time = time.time()
res = func(*args,**kwargs)
stop_time = time.time()
print('the func run time is %s' %(stop_time-start_time))
return res #这里将func的返回值返回
return deco @timer
def test(name):
time.sleep(2)
print('this is test...',name)
return 'asdfasdfgdfgd' print(test('vector'))
这样就可以打印出返回值了。
还有些时候我们需要给装饰器进行传参,给内部使用。解决方案看下面。
高高高级案例 -- 给装饰器传参
import time
def timer(temp):
print('this is ',temp) #这里是加进来的参数
def out(func):
def deco(*args,**kwargs):
start_time = time.time()
res = func(*args,**kwargs)
stop_time = time.time()
print('the func run time is %s' %(stop_time-start_time))
return res
return deco
return out @timer('temp')
def test(name):
time.sleep(2)
print('this is test...',name)
return 'asdfasdfgdfgd' print(test('vector'))
实际上就是整体又在外面加了一层内嵌函数。
Python学习之路6 - 装饰器的更多相关文章
- Python学习之路7☞装饰器
一:命名空间与作用域 1.1命名空间 局部命名空间: def foo(): x=1 def func(): pass 全局命名空间: import time class ClassName:pass ...
- Python成长之路_装饰器
一.初入装饰器 1.首先呢我们有这么一段代码,这段代码假设是N个业务部门的函数 def f1(aaa): print('我是F1业务') if aaa == 'f1': return 'ok' def ...
- python学习日记(函数--装饰器)
楔子 前提,我有一段代码(一个函数). import time def run_time(): time.sleep(0.1) print('我曾踏足山巅') 需求1:现在,我想计算这段代码的运行时间 ...
- 【Python学习之二】装饰器
装饰器 首先,给出装饰器的框架: def log(func): def wrapper(*args, **kw): print('call %s():' % func.__name__) return ...
- python 学习笔记7(装饰器)
闭包(closure)是函数式编程的重要的语法结构. 定义:如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure). def outer ...
- Python 学习笔记9(装饰器,decorator)
31 装饰器 装饰器可以对一个函数.方法或者类进行加工,是一种高级的python语法. 装饰函数 接收一个可调用对象作为输入参数,并返回一个新的可调用对象. 把函数传递给装饰器,然后增加新的功能,返回 ...
- python学习之路-day4-装饰器&json&pickle
本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 一.生成器 1.列表生成式 >>> L = [x * x for x in range(10 ...
- Python学习笔记九:装饰器,生成器,迭代器
装饰器 本质是函数,装饰其他函数,为其他函数添加附加功能 原则: 1不修改原函数的源代码 2不修改原函数的调用方式 知识储备: 1函数即变量 使用门牌号的例子说明函数,调用方式与变量一致 2高阶函数 ...
- Python学习第二阶段,day1, 装饰器,生成器,迭代器
装饰器 不得不说,这是对初学者最难以理解的概念了,虽然我学过面向对象,但还是被搞懵逼了..前面还好理解,主要是后面“装饰器的装饰器”我理解不了.装饰器工厂,根据传入的参数不同去返回不同的装饰器,我不得 ...
随机推荐
- Javascript--将十进制数字转换成罗马数字显示
下午在FCC(FreeCodeCamp)中文网上做到一道练习题:将给定的数字转换成罗马数字.折磨了一个多小时,终于能把基本功能给实现了.过程如下: 关于罗马数字 罗马数字的详细介绍可见百度,或者罗马数 ...
- 解决webview上移
//解决webview上移 $(".webView").blur(function() { setTimeout(function() { var scrollHeight = d ...
- Linux基础入门---学习心得
之前一直以为Linux和Windows差不多,但是学习了Linux基础入门之后才发现两种操作系统之间差距非常大. Linux只是在硬件之上的内核和系统调用,就连我们在Windows里习以为常的图形界面 ...
- python格式化输出、逻辑表达式和字符编码
格式化输出: %s 字符串占位符;%d 整数占位符 注意:如果前面有了占位符,那么后面所有的%都是占位,如果要输出“%”,需要使用转移符,即"%%" #定义三个变量 name = ...
- 用GO把你想说的话写到比特币链上
比特币除了币转账还有不少好玩的地方,比如把你想说的话写上去,可以当做留念.记录.或者装逼.今天用GO语言写了一个比特币交易构建.交易签名的程序. 生成的交易信息可以在比特币控制台用sendrawtra ...
- jquery ajax实例教程和一些高级用法
jquery ajax的调用方式:jquery.ajax(url,[settings]),jquery ajax常用参数:红色标记参数几乎每个ajax请求都会用到这几个参数,本文将介绍更多jquery ...
- 实验四: Android程序设计
实验四 Android程序设计 1 实验目的及要求 1.安装 Android Stuidio. 2.完成Hello World, 要求修改res目录中的内容,Hello World后要显示自己的学号. ...
- 20155236 《Java程序设计》实验二实验报告
20155236 <Java程序设计>实验一(Java开发环境的熟悉)实验报告 一.实验内容及步骤 实验内容 1.初步掌握单元测试和TDD 2.理解并掌握面向对象三要素:封装.继承.多态 ...
- 20155338 2016-2017-2 《Java程序设计》第4周学习总结
20155338 2016-2017-2 <Java程序设计>第4周学习总结 教材学习内容总结 内容有很多,这里这是选取几个比较重要的一部分来展示. 1.继承 •定义:继承基本上就是避免多 ...
- 【LG3703】[SDOI2017]树点涂色
[LG3703][SDOI2017]树点涂色 题面 洛谷 题解 更博辣,更博辣!!! 猪年的第一篇博客 一次只能染根到\(x\),且染的颜色未出现过 这句话是我们解题的关键. 设\(x\)到根的颜色数 ...