菜单

详解Python 装饰器实施各类迷思

2019年5月26日 - 金沙编程资讯

索求三个装饰器实行顺序

装饰器是Python用于封装函数或代码的工具,英特网能够搜到繁多篇章能够学学,小编在这里要研究的是多少个装饰器实行顺序的三个迷思。

疑问

大大多涉嫌多少个装饰器装饰的函数调用顺序时都会注解它们是自上而下的,比如上边这些例子:

def decorator_a(func):
  print 'Get in decorator_a'
  def inner_a(*args, **kwargs):
    print 'Get in inner_a'
    return func(*args, **kwargs)
  return inner_a

def decorator_b(func):
  print 'Get in decorator_b'
  def inner_b(*args, **kwargs):
    print 'Get in inner_b'
    return func(*args, **kwargs)
  return inner_b

@decorator_b
@decorator_a
def f(x):
  print 'Get in f'
  return x * 2

f(1)

地点代码先定义里多少个函数: decotator_a, decotator_b,
那七个函数实现的机能是,接收四个函数作为参数然后回来创造的另贰个函数,在那么些创设的函数里调用接收的函数(文字比代码绕人)。最终定义的函数
f 选择地点定义的 decotator_a, decotator_b
作为装饰函数。在当大家以1为参数调用装饰后的函数 f 后, decotator_a,
decotator_b
的各种是什么样吧(这里为了表示函数实行的先后顺序,接纳打字与印刷输出的艺术来查看函数的实践顺序)?

设若不假思量根据自下而上的尺度来判别地话,先实行 decorator_a 再执行
decorator_b , 那么会先输出 Get in decotator_a, Get in inner_a 再输出
Get in decotator_b , Get in inner_b 。但是事实并非如此。

实在运转的结果如下:

Get in decorator_a
Get in decorator_b
Get in inner_b
Get in inner_a
Get in f

函数和函数调用的分别

何以是先施行 inner_b 再执行 inner_a
呢?为了干净看清下面包车型地铁标题,得先分清八个概念:函数和函数调用。上边的例证中
f 称之为函数, f(1)
称之为函数调用,后者是对前者传入参数实行求值的结果。在Python中函数也是三个对象,所以
f 是代表二个函数对象,它的值是函数自个儿, f(一)
是对函数的调用,它的值是调用的结果,这里的概念下 f(一)
的值二。同样地,拿地点的 decorator_a 函数来讲,它回到的是个函数对象
inner_a ,那些函数对象是它里面定义的。在 inner_a 里调用了函数 func
,将 func 的调用结果作为值再次回到。

装饰器函数在棉被服装饰函数概念好后立即施行

说不上得理清的三个难题是,当装饰器装饰3个函数时,终究产生了什么。以后简化大家的例子,要是是上边那样的:

def decorator_a(func):
  print 'Get in decorator_a'
  def inner_a(*args, **kwargs):
    print 'Get in inner_a'
    return func(*args, **kwargs)
  return inner_a

@decorator_a
def f(x):
  print 'Get in f'
  return x * 2

正如过多介绍装饰器的篇章里所说:

@decorator_a
def f(x):
  print 'Get in f'
  return x * 2

# 相当于
def f(x):
  print 'Get in f'
  return x * 2

f = decorator_a(f)

故此,当解释器实行这段代码时, decorator_a 已经调用了,它以函数 f
作为参数, 重回它里目生成的三个函数,所以随后 f 指代的是 decorater_a
里面再次回到的 inner_a 。所以当以往调用 f 时,实际上相当于调用 inner_a
,传给 f 的参数会传给 inner_a , 在调用 inner_a 时会把接受到的参数传给
inner_a 里的 func 即 f ,最终回到的是 f
调用的值,所以在最外面看起来就像直接再调用 f 一样。

疑问的演讲

当理清上面两上边概念时,就能够理解地看清最原始的事例中产生了怎么。

当解释器施行上面这段代码时,实际上依据从下到上的一1已经相继调用了
decorator_a 和 decorator_b ,这是会输出对应的 Get in decorator_a 和
Get in decorator_b 。 那时候 f 已经相当于 decorator_b 里的 inner_b
。但因为 f 并不曾被调用,所以 inner_b 并未调用,依次类推 inner_b
内部的 inner_a 也并未有调用,所以 Get in inner_a 和 Get in inner_澳门金沙国际 ,b
也不会被输出。

@decorator_b
@decorator_a
def f(x):
  print 'Get in f'
  return x * 2

接下来最后一行业我们对 f 传入参数一张开调用时, inner_b
被调用了,它会先打字与印刷 Get in inner_b ,然后在 inner_b 内部调用了
inner_a 所以会再打字与印刷 Get in inner_a, 然后再 inner_a 内部调用的原本的
f,
并且将结果作为最后的回来。这时候你该知道为何输出结果会是那么,以及对装饰器施行种种实际发生了什么有鲜明了然了啊。

当大家在地方的事例最后一行 f
的调用去掉,放到repl里演示,也能很当然地看看顺序难题:

➜ test git:(master) ✗ python
Python 2.7.11 (default, Jan 22 2016, 08:29:18)
[GCC 4.2.1 Compatible Apple LLVM 7.0.2 (clang-700.1.81)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import test13
Get in decorator_a
Get in decorator_b
>>> test13.f(1)
Get in inner_b
Get in inner_a
Get in f
2
>>> test13.f(2)
Get in inner_b
Get in inner_a
Get in f
4
>>>

在实际上利用的气象中,当大家选取地点的法子写了五个装饰艺术譬喻先验证有未有记名
@login_required , 再作证权限够非常不足时 @permision_allowed
时,我们采纳下边包车型客车逐条来装点函数:

@login_required
@permision_allowed
def f()
 # Do something
 return

以上就是本文的全体内容,希望对大家的就学抱有扶助,也愿意咱们多多帮忙脚本之家。

您或许感兴趣的小说:

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图