Skip to content

Conversation

mirrornight
Copy link

No description provided.

@spacewander
Copy link
Owner

@mirrornight
你跑下这段代码,看下输出?

#!/usr/bin/env python3
# coding: utf-8
import functools

def foo(func):
    @functools.wraps(func)
    def foo(*args, **kwargs):
        print("foo")
        func(*args, **kwargs)
    return foo

def bar(func):
    @functools.wraps(func)
    def bar(*args, **kwargs):
        print("bar")
        func(*args, **kwargs)
    return bar

@foo
@bar
def one():
    raise Exception

r1 = one()

@spacewander
Copy link
Owner

上面的代码的输出是:

foo
bar
Traceback (most recent call last):
  File "./x.py", line 24, in <module>
    r1 = one()
  File "./x.py", line 9, in foo
    func(*args, **kwargs)
  File "./x.py", line 16, in bar
    func(*args, **kwargs)
  File "./x.py", line 22, in one
    raise Exception
Exception

装饰器是由顶而下执行的。

感谢你抽空提出 PR,但是这个修改并不是正确的。

@mirrornight
Copy link
Author

mirrornight commented Jul 29, 2019

等等!
import functools
def foo(func):
print('get in foo')
@functools.wraps(func)
def foo(*args, **kwargs):
print("foo")
func(*args, **kwargs)
return foo

def bar(func):
print('get in bar')
@functools.wraps(func)
def bar(*args, **kwargs):
print("bar")
func(*args, **kwargs)
return bar

@foo
@bar
def one():
raise Exception

r1 = one()

输出:
get in bar
get in foo
foo
bar
Traceback (most recent call last):
...
raise Exception
Exception

@spacewander spacewander reopened this Jul 30, 2019
@spacewander
Copy link
Owner

@mirrornight
从语法上看,你是对的。这里面其实有两组会被执行的“装饰器”,一种是装饰器函数自己,另一种是装饰器函数返回的函数。比如在下面这个例子里,

import functools

def foo(func):
    print('get in foo')
    @functools.wraps(func)
    def _foo(*args, **kwargs):
        print("foo")
        func(*args, **kwargs)
    return _foo

def bar(func):
    print('get in bar')
    @functools.wraps(func)
    def _bar(*args, **kwargs):
        print("bar")
        func(*args, **kwargs)
    return _bar

@foo
@bar
def one():
    raise Exception

one()

foobar 会在解析 one 时执行,顺序是先 barfoo。而 _foo_bar 会在运行 one 时执行,顺序是先 _foo_bar

从上下文看,原作者描述的应该是类似于运行 one 的场景。不过这里的装饰器执行顺序的表达容易引起误会,也许应该改成“洋葱模型”这种表达?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants