Python 装饰器执行顺序
Python 装饰器执行顺序
之前同事问到两个装饰器在代码中使用顺序不同会不会有什么问题,装饰器是对被装饰的函数做了一层包装,然后执行的时候执行了被包装后的函数,例如:
def decorator_a(fun):
def inner_a(*args, **kwargs):
print 'inner_a'
return fun(*args, **kwargs)
return inner_a
@decorator_a
def test():
print 'test_func'
test()
inner_a
test_func
在 Python 中函数也是一个对象,可以和其他对象一样当作一个参数传递,例如对于一个普通的函数,可以传递一些参数,然后在函数里对相应的参数进行操作,例如:
def normal(param):
print 'param:', param
normal('test')
param: test
type(normal)
function
而对于函数对象,可以如下进行传递:
def get_func(f):
print f.__name__
get_func(normal)
normal
所以上面使用的装饰器语法糖其实和以下语句功能一样,把 test 函数对象传给了装饰器函数,装饰器函数的返回值是 1 个函数对象,然后把函数对象赋给了和原先传进去的函数同名的变量,这样新的变量也就是一个函数对象了,对于函数对象,会和普通的函数一样。当然,使用 @ 会使代码看上去更加清晰:
def test():
print 'test_func'
test = decorator_a(test)
test()
上面是一个装饰器的情况,那么如果有多个装饰器,执行的顺序是怎么样的呢?下面是另一个装饰器:
def decorator_b(fun):
def inner_b(*args, **kwargs):
print 'inner_b'
return fun(*args, **kwargs)
return inner_b
对于两个装饰器的执行顺序如下:
# 1
@decorator_a
@decorator_b
def two():
print 'two'
two()
inner_a
inner_b
two
# 2
@decorator_b
@decorator_a
def two():
print 'two'
two()
inner_b
inner_a
two
# 3
two = decorator_b(decorator_a(two))
two()
inner_b
inner_a
two
可以看到,两个装饰器的执行顺序是从上往下执行的,对于多个装饰器,和单个装饰器类似,只是把上一个装饰器返回的函数对象又作为下一个装饰器的参数传递进去了而已。
到这里,也就大概明白了装饰器的执行顺序以及简单原理,回到开头,对于使用中的多个装饰器,还是需要关注一下使用的顺序的,例如一个验证是否登陆的装饰器,需要在验证用户身份的装饰器上面。大概如下:
@login_in
@check_role
def hhh():
pass
Python 装饰器执行顺序的更多相关文章
- Python装饰器执行顺序详解
探究多个装饰器执行顺序 装饰器是Python用于封装函数或代码的工具,网上可以搜到很多文章可以学习,我在这里要讨论的是多个装饰器执行顺序的一个迷思. 疑问 大部分涉及多个装饰器装饰的函数调用顺序时都会 ...
- Python 装饰器执行顺序迷思
Table of Contents 1. 探究多个装饰器执行顺序 1.1. 疑问 1.2. 函数和函数调用的区别 1.3. 装饰器函数在被装饰函数定义好后立即执行 1.4. 疑问的解释 2. 参考资料 ...
- python装饰器执行顺序
. python 装饰器 1) 2层装饰器 def decorator(func): # TODO def wrapper(*args, **kwargs): # TODO func(*args, * ...
- Python面试题之多个装饰器执行顺序
疑问 大部分涉及多个装饰器装饰的函数调用顺序时都会说明它们是自上而下的,比如下面这个例子: def decorator_a(func): print 'Get in decorator_a' def ...
- 粗浅聊聊Python装饰器
浅析装饰器 通常情况下,给一个对象添加新功能有三种方式: 直接给对象所属的类添加方法: 使用组合:(在新类中创建原有类的对象,重复利用已有类的功能) 使用继承:(可以使用现有类的,无需重复编写原有类进 ...
- Python基础篇【第6篇】: Python装饰器
装饰器 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装饰类, ...
- 理解Python装饰器
装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象.它经常用于有切面需求的场景,比如:插入日志.性能测试.事务处理.缓存.权 ...
- Python装饰器由浅入深
装饰器的功能在很多语言中都有,名字也不尽相同,其实它体现的是一种设计模式,强调的是开放封闭原则,更多的用于后期功能升级而不是编写新的代码.装饰器不光能装饰函数,也能装饰其他的对象,比如类,但通常,我们 ...
- python装饰器方法
前几天向几位新同事介绍项目,被问起了@login_required的实现,我说这是django框架提供的装饰器方法,验证用户是否登录,只要这样用就行了,因为自己不熟,并没有做过多解释. 今天查看dja ...
随机推荐
- 中山纪中集训Day4双是测试(划沝) 九校联考-DL24凉心模拟Day2
A组T1 锻造 (forging) 1.1 题目背景 勇者虽然武力值很高,但在经历了多次战斗后,发现怪物越来越难打于是开始思考是不是自己平时锻炼没到位,于是苦练一个月后发现......自己连一个史莱姆 ...
- 数据结构Java版之邻接表实现图(十)
邻接表实现图,实际上是在一个数组里面存放链表,链表存放的是连接当前节点的其他节点. package mygraph; import java.util.ArrayList; import java.u ...
- SpringBoot配置虚拟化路径用于图片的展示
前言:springboot默认可以访问resources下的static文件夹下的静态资源,我们一般将图片指定上传到static下的某个文件夹,例如images,开发阶段可以使用,但是当项目打成jar ...
- js-关于异步原理的理解和总结
我们经常说JS是单线程的,比如Node.js研讨会上大家都说JS的特色之一是单线程的,这样使JS更简单明了,可是大家真的理解所谓JS的单线程机制吗?单线程时,基于事件的异步机制又该当如何,这些知识在& ...
- QtCore概述
所有其他Qt模块都依赖于这个模块. 要包含模块类的定义,请使用以下指令: include < QtCore > 如果您使用qmake来构建您的项目,则默认将QtCore包含在内. 核心功能 ...
- Apache log4j 1.2 - Short introduction to log4j
Apache log4j 1.2 - Short introduction to log4jhttps://logging.apache.org/log4j/1.2/manual.html log4j ...
- cordova run android 可能遇到的错误解决
运行: ionic cordova build 等待下载,然后根据提示 输入android或者ios平台,即可 运行cordova run android 报错: 最快捷的解决方法就是使用Androi ...
- 开源配置中心xxl-conf的核心原理分析
XXL-CONF是一款轻量级的开源配置中心项目,由国内大牛许雪里开发.下面是官方对其优点作出的描述: 一个轻量级分布式配置管理平台,拥有"轻量级.秒级动态推送.多环境.跨语言.跨机房.配置监 ...
- 用filter求素数
计算素数的一个方法是埃氏筛法, 所有的奇数: def _odd_iter(): n = 1 while True: n = n + 2 yield n 定义一个筛选函数: def _not_divis ...
- java 数据相除
编程的人都知道,java中的“/”.“%”运算,其中前者为取整,后者取余数.那么有没有快捷的运算方法取正常的运算结果呢? /** * TODO 除法运算,保留小数 * @author 袁忠明 * @d ...