Python基础之装饰器
1、什么是装饰器?
Python的装饰器的英文名叫Decorator,当你看到这个英文名的时候,你可能会把其跟Design Pattern里的Decorator搞混了,其实这是完全不同的两个东西。虽然好像,他们要干的事都很相似——都是想要对一个已有的模块做一些“修饰工作”,所谓修饰工作就是想给现有的模块加上一些小装饰(一些小功能,这些小功能可能好多模块都会用到),但又不让这个小装饰(小功能)侵入到原有的模块中的代码里去。
实例:文件名hello.py
#!/usr/bin/env python # _*_ coding:utf-8 _*_ # Author: enzhi.wang def hello(fn): def wrapper(): print("hello,%s"% fn.__name__) fn() print("goodby,%s"% fn.__name__) return wrapper @hello def foo(): print("i am foo") foo()
当你运行代码,你会看到如下输出
C:\Python3.5\python.exe C:/Users/root/PycharmProjects/S14/day4/hello.py hello,foo i am foo goodby,foo
上面代码中你可以看到如下东西
1.函数foo前面有个@hello,hello就是我们前面定义的hello函数
2.hello函数中需要一个fn的参数,fn这个参数就是用来调取foo函数
3.hello函数中返回了一个wrapper函数,wrapper函数中回调了foo函数,并在回调前后加了两条语句。
小结:
@ + 函数名
功能:
1.自动执行hello函数,并且将hello函数下面的foo函数名当做参数传递给hello
2.将hello参数的返回值重新赋值给foo
2、Decorator的本质
对于Python的这个@注解语法糖- Syntactic Sugar 来说,当你在用某个@decorator来修饰某个函数func时,如下所示:
1 @decorator
2 def
func():
3 pass
其解释器会解释成下面这样的语句
func = decorator(func)
尼玛,这不就是把一个函数当参数传到另一个函数中,然后再回调吗?是的,但是,我们需要注意,那里还有一个赋值语句,把decorator这个函数的返回值赋值回了原来的func。 根据《函数式编程》中的first class functions中的定义的,你可以把函数当成变量来使用,所以,decorator必需得返回了一个函数出来给func,这就是所谓的higher order function 高阶函数,不然,后面当func()调用的时候就会出错。 就我们上面那个hello.py里的例子来说,
@hello def foo(): print("i am foo")
被解释成了
foo = hello(foo)
再回到我们hello.py的那个例子,我们可以看到,hello(foo)返回了wrapper()函数,所以,foo其实变成了wrapper的一个变量,而后面的foo()执行其实变成了wrapper()。
3.带参数的Decorator
当被调用的函数需要传入参数时如何用装饰器去装饰函数
实例:传入一个参数,文件名decorator_args1.py
#!/usr/bin/env python # _*_ coding:utf-8 _*_ # Author: enzhi.wang def outer(func): def inner(args): print('before') func(args) print('after') return inner @outer def func(args): print("hello %s"% (args)) func('enzhi')
当你运行上面代码会看到以下输出:
C:\Python3.5\python.exe C:/Users/root/PycharmProjects/S14/day4/decorator_args1.py before hello enzhi after
上面代码中你可以看到如下东西
1.函数func前面有个@outer,outer就是我们前面定义的outer函数
2.outer函数中需要一个func的参数,func这个参数就是用来调取func函数
3.func函数执行需要传入一个实参
4.outer函数中返回了一个inner函数,并且inner函数也需要接收一个实参,此时的func = inner
5.inner函数中回调了老的func函数,所以需要在inner函数内部调用func函数并传入一个参数
实例:传入多个参数 decorator_args2.py
#!/usr/bin/env python # _*_ coding:utf-8 _*_ # Author: enzhi.wang def outer(func): def inner(*args,**kwargs): print('before') func(*args,**kwargs) print('after') return inner @outer def f1(args): print("hello %s"% (args)) @outer def f2(*args,**kwargs): print("Name %s"% (kwargs['name'])) print("Age %d"% (kwargs['age'])) f1('enzhi') f2(name="Wangenzhi",age=26)
当你运行上面代码会看到以下输出:
C:\Python3.5\python.exe C:/Users/root/PycharmProjects/S14/day4/decorator_args2.py before hello enzhi after before Name Wangenzhi Age 26 after
上面代码中你可以看到如下东西
1.*args和**kwargs 这个两个参数用于在装饰器装饰不同的函数时可以接收多个参数
2. inner(*args,**kwargs) 接收参数传入给内部回调的函数
3. func(*args,**kwargs) inner内部回调时处理不同函数传入的多个参数或者没有参数
4、双层装饰器
#!/usr/bin/env python # _*_ coding:utf-8 _*_ # Author: enzhi.wang USER_LOGIN = {} def checklogin(func): def inner(*args,**kwargs): if USER_LOGIN.get('is_login',None): ret = func(*args,**kwargs) return ret else: print("请登录") return inner def checkusertype(func): "检查用户类型" def inner(*args,**kwargs): if USER_LOGIN.get('user_type',None) == 2: ret = func(*args,**kwargs) return ret else: print("无权查看") return inner @checklogin @checkusertype def index(): print("Index") @checklogin def home(): print("Home") def login(user): if user == 'admin': USER_LOGIN['is_login'] = True USER_LOGIN['user_type'] = 2 else: USER_LOGIN['is_login'] = True def main(): while True: inp = input("1、登录;2、查看信息;3、管理员\n >>>") ': username = input("输入用户名:") login(username) ': home() ': index() main()
上面代码会看到如下东西:
1.@checklogin2.@checkusertype双层的装饰器它的解释顺序是右下到上1.先执行@checkusertype,返回checkusertype内部inner函数。此时index = checkusertype(index)2.执行@checklogin,返回checklogin内部inner函数,此时checklogin内部inner函数中的func函数等于checkusertype内部inner函数执行顺序是由上到下1.执行@checklogin,如果if USER_LOGIN.get('is_login',None):满足条件就会执行ret = func()2.执行ret = func(),而func此时是checkusertype内部inner函数,就会执行条件判断if USER_LOGIN.get('user_type',None) == 2:3.如果if USER_LOGIN.get('user_type',None) == 2:条件满足就会执行ret = func(*args,**kwargs),此时func指向的是老的index4.执行func()调用index()函数中的print("Index")
Python基础之装饰器的更多相关文章
- python基础—函数装饰器
python基础-函数装饰器 1.什么是装饰器 装饰器本质上是一个python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能. 装饰器的返回值是也是一个函数对象. 装饰器经常用于有切 ...
- 十. Python基础(10)--装饰器
十. Python基础(10)--装饰器 1 ● 装饰器 A decorator is a function that take a function as an argument and retur ...
- [python基础]关于装饰器
在面试的时候,被问到装饰器,在用的最多的时候就@classmethod ,@staticmethod,开口胡乱回答想这和C#的static public 关键字是不是一样的,等面试回来一看,哇,原来是 ...
- Day11 Python基础之装饰器(高级函数)(九)
在python中,装饰器.生成器和迭代器是特别重要的高级函数 https://www.cnblogs.com/yuanchenqi/articles/5830025.html 装饰器 1.如果说装 ...
- 1.16 Python基础知识 - 装饰器初识
Python中的装饰器就是函数,作用就是包装其他函数,为他们起到修饰作用.在不修改源代码的情况下,为这些函数额外添加一些功能,像日志记录,性能测试等.一个函数可以使用多个装饰器,产生的结果与装饰器的位 ...
- python基础-----函数/装饰器
函数 在Python中,定义一个函数要使用def语句,依次写出函数名.括号.括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用return语句返回. 函数的优点之一是,可以将代码块与主程 ...
- python基础之装饰器(实例)
1.必备 #### 第一波 #### def foo(): print 'foo' foo #表示是函数 foo() #表示执行foo函数 #### 第二波 #### def foo(): print ...
- 【Python基础】装饰器的解释和用法
装饰器的用法比较简单,但是理解装饰器的原理还是比较复杂的,考虑到接下来的爬虫框架中很多用到装饰器的地方,我们先来讲解一下. 函数 我们定义了一个函数,没有什么具体操作,只是返回一个固定值 请注意一下缩 ...
- 学习PYTHON之路, DAY 5 - PYTHON 基础 5 (装饰器,字符格式化,递归,迭代器,生成器)
---恢复内容开始--- 一 装饰器 1 单层装饰器 def outer(func): def inner(): print('long') func() print('after') return ...
随机推荐
- poj-1703-Find them, Catch them
Find them, Catch them Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 41928 Accepted: ...
- servlet基本原理(手动创建动态资源+工具开发动态资源)
一.手动开发动态资源 1 静态资源和动态资源的区别 静态资源: 当用户多次访问这个资源,资源的源代码永远不会改变的资源. 动态资源:当用户多次访问这个资源,资源的源代码可能会发送改变. <scr ...
- [小北De编程手记] : Lesson 06 玩转 xUnit.Net 之 定义自己的FactAttribute
xUnit.Net本身提供了标记测试方法的标签Fact和Theory.在前面的文章<Lesson 02 玩转 xUnit.Net 之 基本UnitTest & 数据驱动>中,也对它 ...
- WebSocket 学习笔记--IE,IOS,Android等设备的兼容性问题与代码实现
一.背景 公司最近准备将一套产品放到Andriod和IOS上面去,为了统一应用的开发方式,决定用各平台APP嵌套一个HTML5浏览器来实现,其中数据通信,准备使用WebSocket的方式.于是,我开始 ...
- JavaScript学习(2):对象、集合以及错误处理
在这篇文章里,我们讨论一下JavaScript中的对象.数组以及错误处理. 1. 对象 对象是JavaScript中的一种基本类型,它内部包含一些属性,我们可以对这些属性进行增删操作. 1.1 属性 ...
- $('div a') 与$('div>a'),.div+.div2与.div~.div2
$('div a'):div标签下所有层次a元素的jquery对象 $('div>a'):div标签下子元素层次a元素的jquery对象 <body> <div class=' ...
- something
var colors=['red','green','yellow']; console.log(colors)//['red','green','yellow'] console.log(color ...
- ENVI【非监督分类】
非监督分类的概念: 非监督分类,又称“聚类分析或者点群分析”.在多光谱图像中搜寻.定义其自然相似光谱集群的过程.它不必对图像地物获取先验知识,仅依靠图像上不同地物光谱信息进行特征提取,在统计特征的差别 ...
- Hyhyhy – 专业的 HTML5 演示文稿工具
Hyhyhy 是创建好看的 HTML5 演示文档的工具.它具备很多的特点:支持 Markdown,嵌套幻灯片,数学排版,兼容性,语法高亮,使用 Javascript API ,方便的骨架.它支持 Fi ...
- [deviceone开发]-直播APP心形点赞动画示例
一.简介 这个示例展示do_Animator组件的简单使用,通过点击"点赞"按钮,不断弹出心形图片,向上动画漂移到顶部消失.间隔时间和上下左右移动的步长都是一定范围的随机值. 二. ...