这个Python修饰函数的逻辑执行顺序是什么?

Geo*_*Geo 4 python decorator

想象一下:

def b1(fnc):
  print "b1"
  return fnc

@b1
def a1():
  print "a1"

if __name__ == "__main__":
  a1() # will print b1 a1
Run Code Online (Sandbox Code Playgroud)

所以,当我使用时@b1,a1会转向a1 = b1(a1),对吗?然后,当我说:

a1()
Run Code Online (Sandbox Code Playgroud)

这转向:

b1(a1)
Run Code Online (Sandbox Code Playgroud)

然后进入:

print "b1"
return fnc
Run Code Online (Sandbox Code Playgroud)

究竟在哪里/谁正在呼叫fnc?我有一种感觉,我问的是一个非常愚蠢的问题,但我想明白.

NPE*_*NPE 7

装饰器只执行一次.它需要一个可调用的对象并返回一个可调用的对象.它返回的对象用于代替a1.

换句话说,b1a1定义的点处调用.它打印出来"b1"并返回a1不变.由于它返回a1不变,因此b1在任何后续调用中都不起任何作用a1.

因此,以下评论不太正确:

  a1() # will print b1 a1
Run Code Online (Sandbox Code Playgroud)

事实上,

  • a1()只打印"a1".
  • "b1"你看到的是由打印@b1/ def a1():.

如果您更改代码并重新运行,事件序列应该变得更加清晰:

def b1(fnc):
  print "b1"
  return fnc

@b1
def a1():
  print "a1"

if __name__ == "__main__":
  print 'in __main__'
  a1()
  a1()
Run Code Online (Sandbox Code Playgroud)

最后,为了达到你想要的效果,装饰器需要返回一个不同的可调用对象:

def b1(fnc):
  def decorated():
    print "b1"
    return fnc()
  return decorated

@b1
def a1():
  print "a1"

if __name__ == "__main__":
  print 'in __main__'
  a1()
  a1()
Run Code Online (Sandbox Code Playgroud)

在这里,很清楚谁在打电话fnc().