简体   繁体   中英

decorators execution of python

registry = []
def register(func):
 print('running register(%s)' % func)
 registry.append(func)
 return func

@register
def f1():
 print('running f1()')
@register
def f2():
 print('running f2()')
def f3():
 print('running f3()')
def main():
  print('running main()')
  print('registry ->', registry)
  f1()
  f2()
  f3()
if __name__=='__main__':
  main()

in the above program why doesnt the f1() f2() and f3() in main work if return func is not used in the register function

A decorator is a higher-order function which takes a function as input and returns a function as output. Decorator syntax is a way of calling this higher order function.

The lines

@register
def f1():
 print('running f1()')

are equivalent to the lines

def f1():
 print('running f1()')

f1 = register(f1)

Usually, the decorator modifies the decorated function. In this case it is returned unmodified. But -- it is still returned. If the decorator returned nothing then the decorator would replace f1 by None (which wouldn't be very useful). This particular decorator is called for its side effects (registering a function). The fact that it returns an unmodified function doesn't mean that it isn't called.

The output that you see should make sense now:

running register(<function f1 at 0x0000000001DCCBF8>)
running register(<function f2 at 0x0000000003566D90>)
running main()
registry -> [<function f1 at 0x0000000001DCCBF8>, <function f2 at 0x0000000003566D90>]
running f1()
running f2()
running f3()

You used @register twice, which calls register() twice, before main is run. Neither f1 nor f2 were actually changed by the decorator, hence they work as expected when called in main() . The printed value of registry shows that the decorator worked as intended: it registered the decorated f1, f2 but didn't register the undecorated f3 .

On the other hand, if you remove the line return func from the decorator, you see (something like):

running register(<function f1 at 0x00000000004DCBF8>)
running register(<function f2 at 0x0000000003586D90>)
running main()
registry -> [<function f1 at 0x00000000004DCBF8>, <function f2 at 0x0000000003586D90>]
Traceback (most recent call last):
  File "C:\Users\jcoleman\Documents\Programs\PythonScripts\socode.py", line 68, in <module>
    main()
  File "C:\Users\jcoleman\Documents\Programs\PythonScripts\socode.py", line 64, in main
    f1()
TypeError: 'NoneType' object is not callable

The decorator is still called twice -- but they are now (implicitly) returning None . As soon as f1() is hit in main you get a run-time error since at that stage f1 is None , which isn't callable.

See this question for more on decorators.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM