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 装饰器执行顺序的更多相关文章

  1. Python装饰器执行顺序详解

    探究多个装饰器执行顺序 装饰器是Python用于封装函数或代码的工具,网上可以搜到很多文章可以学习,我在这里要讨论的是多个装饰器执行顺序的一个迷思. 疑问 大部分涉及多个装饰器装饰的函数调用顺序时都会 ...

  2. Python 装饰器执行顺序迷思

    Table of Contents 1. 探究多个装饰器执行顺序 1.1. 疑问 1.2. 函数和函数调用的区别 1.3. 装饰器函数在被装饰函数定义好后立即执行 1.4. 疑问的解释 2. 参考资料 ...

  3. python装饰器执行顺序

    . python 装饰器 1) 2层装饰器 def decorator(func): # TODO def wrapper(*args, **kwargs): # TODO func(*args, * ...

  4. Python面试题之多个装饰器执行顺序

    疑问 大部分涉及多个装饰器装饰的函数调用顺序时都会说明它们是自上而下的,比如下面这个例子: def decorator_a(func): print 'Get in decorator_a' def ...

  5. 粗浅聊聊Python装饰器

    浅析装饰器 通常情况下,给一个对象添加新功能有三种方式: 直接给对象所属的类添加方法: 使用组合:(在新类中创建原有类的对象,重复利用已有类的功能) 使用继承:(可以使用现有类的,无需重复编写原有类进 ...

  6. Python基础篇【第6篇】: Python装饰器

    装饰器 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装饰类, ...

  7. 理解Python装饰器

    装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象.它经常用于有切面需求的场景,比如:插入日志.性能测试.事务处理.缓存.权 ...

  8. Python装饰器由浅入深

    装饰器的功能在很多语言中都有,名字也不尽相同,其实它体现的是一种设计模式,强调的是开放封闭原则,更多的用于后期功能升级而不是编写新的代码.装饰器不光能装饰函数,也能装饰其他的对象,比如类,但通常,我们 ...

  9. python装饰器方法

    前几天向几位新同事介绍项目,被问起了@login_required的实现,我说这是django框架提供的装饰器方法,验证用户是否登录,只要这样用就行了,因为自己不熟,并没有做过多解释. 今天查看dja ...

随机推荐

  1. 下载svn

    http://subversion.apache.org/download.cgi?update=201708081800 Windows下载zip,其他系统的下载tar.gz

  2. CF1188B/E Count Pairs(数学)

    数同余的个数显然是要把\(i,j\)分别放到\(\equiv\)的两边 $ (a_i + a_j)(a_i^2 + a_j^2) \equiv k \bmod p $ 左右两边乘上\((a_i-a_j ...

  3. interior转换为interface

    在计算的过程中,我们想要将interior(内部面)转换为interface,操作如下:

  4. apache不能解析php之解决办法

    记录一下Ubuntu16.04下的apache服务器不能解析php的问题,如图所示: 对于这个Ubuntu16.04最直接最快速的解决办法就是执行如下命令: sudo apt-get install ...

  5. Go -- client 302 自动转 200 问题 cookie存储 模拟登陆问题

    不久前用go写了个http client,去模拟某网站(*.com)的登录操作.网站的登录逻辑:1.验证登录账号和密码:2.下发token.此token通过cookie下发:3.redirect到主页 ...

  6. arcgis python 拓扑规则

    面 Must Not Have Gaps (Area) | Must Not Overlap (Area) 面面 | Must Be Covered By Feature Class Of (Area ...

  7. 树莓派VNC

    sudo raspi-config Interfacing Options -> VNC 1.停止VNC窗口: vncserver -kill:1 2.修改密码 vncpasswd 3.重启服务 ...

  8. c语言程序课程设计题目

    <C语言程序设计>课程设计课题表 一.A类 .职工信息管理系统设计 职工信息包括职工号.姓名.性别.年龄.学历.工资.住址.电话等(职工号不重复).试设计一职工信息管理系统,使之能提供以下 ...

  9. ThreadPoolExecutor 定制线程池参数

    在 java 开发中经常需要执行一些“规格化”的任务,此时可以使用 java 线程池.节省创建线程时间,任务来时即可执行,高效. java 包是 java.util.concurrent .创建线程池 ...

  10. flutter DataTable数据表格

    数据表显示原始数据集.它们通常出现在桌面企业产品中.DataTable Widget实现这个组件 文档:https://api.flutter.dev/flutter/material/DataTab ...