笔记-python-装饰器
笔记-python-装饰器
1. 装饰器
装饰器的实质是返回的函数对象的函数,其次返回的函数对象是可以调用的,搞清楚这两点后,装饰器是很容易理解的。
1.1. 相关概念理解
首先,要理解在Python中,函数也是一种对象
def foo(x):
print(x)
print(type(foo))
>>><class 'function'>
查看函数拥有的方法:
dir(foo)
>>>
['__call__',
'__class__',
'__closure__',
'__code__',
'__defaults__',
'__delattr__',
……]
因为函数是对象,所以函数可以作为参数传入另一个函数:
def bar(f, x):
x += 1
f(x)
bar(foo, 4) 5
1.2. 返回函数的函数
修饰函数是这样的一种函数,它接受一个函数作为输入,通常输出也是一个函数:
示例:
def loud(f):
def new_func(*args, **kw):
print('calling with', args, kw)
rtn = f(*args, **kw)
print('return value is', rtn)
return rtn
return new_func
loudlen = loud(len)
lisa = [10,20,30]
loudlen(lisa)
>>> loudlen
<function loud.<locals>.new_func at 0x000000894F4A2E18>
>>> len
<built-in function len>
解释:
在python中变量其实都是指针,对象、包括函数也是,可以相互赋值,下面也是合法的语句,在这个基础上理解容易得多;
loudlen1 = loudlen
loudlen1([10,20,30])
1.3. 使用 @
@是一个语法糖,与其说是修饰函数倒不如说是引用、调用它修饰的函数。
下面的一段代码,里面两个函数,没有被调用,也会有输出结果:
# 原理
def test(f):
print("before ...")
f()
print("after ...")
@test
def func():
print("func was called" )
直接运行,输出结果:
before ...
func was called
after ...
上面代码只定义了两个函数: test和func。没有地方调用它们。如果没有“@test”,运行应该是没有任何输出的。
但是,Python解释器读到函数修饰符“@”的时候,后面步骤会是这样了:
1. 去调用 test函数,test函数的入口参数就是那个叫“func”的函数;
2. test函数被执行,入口参数的(也就是func函数)会被调用(执行);
换言之,修饰符带的那个函数的入口参数,就是下面的那个整个的函数。
再来看一个例子:
def test(func):
func()
print("call test")
def test1(f):
f()
print( "call test1")
def main():
@test
def fun():
print("call fun")
@test1
def fun1():
print( "call fun1")
main()
输出结果:
call fun
call fun1
call test1
call test
仔细体会调用顺序。
需要注意的:
1. 函数先定义,再修饰它;反之会编译器不认识;
2. 修饰符“@”后面必须是之前定义的某一个函数;
1.4. 多重装饰
def first(func):
print('%s() was post to first()'%func.__name__)
def _first(*args,**kwargs):
print('call the function %s() in _first().'%func.__name__)
return func(*args, **kwargs)
return _first
def second(func):
print('%s() was post second()'%func.__name__)
def _second(*args, **kwargs):
print('call the function %s() in _second.'%func.__name__)
return func(*args, **kwargs)
return _second
@first
@second
def test():
return 'hello'
输出:
test() was post second()
_second() was post to first()
>>> test()
call the function _second() in _first().
call the function test() in _second.
'hello'
>>> test
<function first.<locals>._first at 0x000000A71BCBE488>
有意思的是在视觉效果上装饰器解释时是由内向外的,而执行时是由外至内的。
上面的代码实质上相当于下面的代码:
>>> def test():
return 'hello world'
>>> test=second(test)
test() was post to second()
>>> test
<function _second at 0x000000000316D3C8>
>>> test=first(test)
_second() was post to first()
>>> test
<function _first at 0x000000000316D358>
>>> test()
Call the function _second() in _first().
Call the function test() in _second().
'hello world'
1.5. 带参数的装饰器
上面都是无参数装饰,下面是一个有参数装饰的例子:
# 装饰器带参数
def log(text):
def decorator(func):
def wrapper(*args,**kw):
print("%s %s():" %(text, func.__name__))
print(args,kw)
return func(*args, **kw)
return wrapper
return decorator
@log("execute")
def now(*args,**kwargs):
print("time.ctime()")
now(1,2,3)
输出:
execute now():
(1, 2, 3) {}
time.ctime()
上面的@log(“execute“)等价于
now = log(“execute”)(now)
>>> now
<function log.<locals>.decorator.<locals>.wrapper at 0x000000B1AA97E400>
2. 附录:
面向切面编程AOP (Aspect Oriented Programming):
AOP主要实现的目的是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。
笔记-python-装饰器的更多相关文章
- python笔记 - day4-之装饰器
python笔记 - day4-之装饰器 需求: 给f1~f100增加个log: def outer(): #定义增加的log print("log") ...
- Python学习笔记:装饰器
Python 装饰器的基本概念和应用 代码编写要遵循开放封闭原则,虽然在这个原则是用的面向对象开发,但是也适用于函数式编程,简单来说,它规定已经实现的功能代码不允许被修改,但可以被扩展,即: 封闭:已 ...
- Python 装饰器学习心得
最近打算重新开始记录自己的学习过程,于是就捡起被自己废弃了一年多的博客.这篇学习笔记主要是记录近来看的有关Python装饰器的东西. 0. 什么是装饰器? 本质上来说,装饰器其实就是一个特殊功能的函数 ...
- Python 装饰器填坑指南 | 最常见的报错信息、原因和解决方案
本文为霍格沃兹测试学院学员学习笔记. Python 装饰器简介 装饰器(Decorator)是 Python 非常实用的一个语法糖功能.装饰器本质是一种返回值也是函数的函数,可以称之为“函数的函数”. ...
- 关于python装饰器
关于python装饰器,不是系统的介绍,只是说一下某些问题 1 首先了解变量作用于非常重要 2 其次要了解闭包 def logger(func): def inner(*args, **kwargs) ...
- python装饰器通俗易懂的解释!
1.python装饰器 刚刚接触python的装饰器,简直懵逼了,直接不懂什么意思啊有木有,自己都忘了走了多少遍Debug,查了多少遍资料,猜有点点开始明白了.总结了一下解释得比较好的,通俗易懂的来说 ...
- Python 装饰器学习
Python装饰器学习(九步入门) 这是在Python学习小组上介绍的内容,现学现卖.多练习是好的学习方式. 第一步:最简单的函数,准备附加额外功能 1 2 3 4 5 6 7 8 # -*- c ...
- python 装饰器修改调整函数参数
简单记录一下利用python装饰器来调整函数的方法.现在有个需求:参数line范围为1-16,要求把9-16的范围转化为1-8,即9对应1,10对应2,...,16对应8. 下面是例子: def fo ...
- python 装饰器学习(decorator)
最近看到有个装饰器的例子,没看懂, #!/usr/bin/python class decorator(object): def __init__(self,f): print "initi ...
- Python装饰器详解
python中的装饰器是一个用得非常多的东西,我们可以把一些特定的方法.通用的方法写成一个个装饰器,这就为调用这些方法提供一个非常大的便利,如此提高我们代码的可读性以及简洁性,以及可扩展性. 在学习p ...
随机推荐
- electron 集成 SQLCipher
mac 安装 brew /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/m ...
- js对secure的支持是没问题的,httponly是为限制js而产生的,当然httponly的cookie也不会被js创建
function setCookie4(c_name,value,expiredays){ var cookieStr = ""; var exdate=new Date(); e ...
- $.ajax和$.load的区别
http://lib.csdn.net/article/jquery/35614?knId=646
- 使用纯css实现波浪效果
有时候我们需要实现水晃动的效果,其实我们可以通过css旋转动画和圆角来实现. 首先来2个div,外层div相对定位,内层div绝对定位,内层div大致位于外层div上半部分.外层div设置一个颜色较深 ...
- 构建第一个Spring Boot2.0应用之application.properties和application.yml(八)
本节学习在项目中配置文件配置的方式,一种是通过applicaiton.properties,一种是通过application.yml方式. 一.环境: IDE:IntelliJ IDEA 2017.1 ...
- zip man man.config
zip man man.config zip -r zip1 man.config man.zip gzip a tar -cvf test.tar /home/* tar -tf test.tar ...
- php使用GD库实现图片水印和缩略图——给图片添加文字水印
今天呢,就来学习一下在php中使用PD库来实现对图片水印的文字水印方法,不需要PS哦! 首先,准备素材 (1)准备一张图片 (2)准备一张水印(最好是透明的,即背景是白色底) (3)准备一中字体(在电 ...
- Web前端学习流程
- 2018.6.6 基于Oracle数据库的航天信息系统JDBC练习
综合练习 一.语言和环境 A.实现语言 Java B.环境要求 JDK 6.0及其以上版本.MyEclipse7.5及其以上版本.Oracle11g.PL/SQL Developer 二.功能要求 开 ...
- 修改android studio中的avd sdk路径、avd sdk找不到的解决方案
要进行Android应用程序的开发,首先就要搭建好Android的开发环境,所需要的工具有如下4个:1.java JDK:2.Android SDK:3.Eclipse:4.ADT 1.java JD ...