python之路---装饰器补充(嵌套顺序)

叠加装饰器的使用是有顺序的:

1.解释@语法是自下而上的

2.执行装饰器是自上而下的

import time

state = {"uname": None}
def auth(func):
    def wapper1(*args,**kwargs):
        if state['uname']:
            res = func(*args, **kwargs)
            return res
        else:
            uname =input('输入用户名:')
            upwd = input('输入密码:')
            if uname == 'bob' and upwd == '123':
                print('登陆成功...')
                state['uname'] = uname
                res = func(*args,**kwargs)
                return res
    return wapper1

def timer(func):
      def wrapper2(*args,**kwargs):
          start_time = time.time()
          res=func(*args,**kwargs)
          end_time = time.time()
          print(end_time - start_time)
          return res
      return wrapper2

@auth
@timer
def music():
    time.sleep(1)
    print('进入音乐模式...')
    return 123
music()

@auth在上,执行结果为--->

输入用户名:bob
输入密码:123
登陆成功...
进入音乐模式...
1.0007665157318115

@timer在上,执行结果为--->

输入用户名:bob
输入密码:123
登陆成功...
进入音乐模式...
5.942626476287842

说明了:timer统计了登录过程的用时

解析:

因为解释@语法是从下自上的,所以--->

1.先解释@timer

python解释器将@下的函数名(music,这个函数名指向music这个函数体的内存地址)作为参数传给timer--->

得到timer(music)--->进一步得到wapper2这个函数名(指向wapper2这个函数体的内存地址),那么此刻@timer 为wapper2,timer内的func = music

2.在解释@auth

python解释器将@下面的函数名wapper2作为参数传给auth-->得到auth(wapper)--->进而得到wapper1这个函数名(指向wapper1的函数体内存地址),而此刻auth内的func = wapper2

而执行是自上而下的..

def auth(func):
    print('1')
    def wapper1(*args,**kwargs):
        print('from auth external')
        res = func(*args,**kwargs)
        print('from auth internal')
        return res
    return wapper1

def timer(func):
      print('2')
      def wrapper2(*args,**kwargs):
          print('from timer external')
          res=func(*args,**kwargs)
          print('from timer internal')
          return res
      return wrapper2

@auth
@timer
def music():
    print('进入音乐模式...')
music()

#执行结果:--->
2
1
from auth external
from timer external
进入音乐模式...
from timer internal
from auth internal

解析:

2在最前面说明python是先解释timer的,拿到wapper2的地址后,解释auth(此时打印1),然后在执行wapper1这个函数体代码,打印from auth external,执行wapper2(*args,**kwargs)时跳到timer内执行wapper2函数体代码,打印from timer external,然后执行music()这个被装饰对象,打印进入音乐模式,然后等待music函数执行完毕后打印from timer internal,等到这步,auth函数内的wapper2才算执行完毕,打印from auth internal

猜你喜欢

转载自blog.csdn.net/ltfdsy/article/details/81328883