python函数(三)—装饰器

一、闭包函数

定义在内部的函数,包含对外部作用域而非全局作用域的引用,该函数就成为闭包函数

import time
def timmer():
      def wrapper():
    print('=======执行结果') 
  return wrapper

print(timmer())

timmer()()

二、装饰器修饰别人的工具,修饰添加功能,工具指的是函数

装饰器本身可以是任何可调用对象

原因:

为什么要使用装饰器

开放封闭原则:对修改是封闭的,对扩展是开放的

装饰器就是为了在不修改被装饰对象的源代码以及调用方式的前提下,为期添加新功能

(一)无参装饰器

1.无返回值

import time
def timmer(func):
    def wrapper():
        start_time=time.time()
        func()
        stop_time=time.time()
        print('运行时间是:%s'%(stop_time-start_time))
    return wrapper

@timmer
def compute_time():
    time.sleep(3)
    print('=========运行结束')
    
compute_time()
View Code

修饰器修饰其正下方的函数--compute_time,他将compute_time作为参数传递给自己,返回带compute_time参数的闭包函数--wrapper,而执行闭包函数的过程中又会去调用修饰器修饰的函数compute_time(因为本身被作为参数传递了进来,加括号即运行)执行而返回结果

2.捕获返回值

如果被修饰的函数带有返回值,那么如何获取返回值呢?

这就需要在闭包函数中接收这个返回值,并将其return出来

import time
def timmer(func):
    def wrapper():
        start_time=time.time()
        res=func()
        stop_time=time.time()
        print('运行时间是:%s'%(stop_time-start_time))
        return res
    return wrapper

@timmer
def compute_time():
    time.sleep(3)
    print('=========运行结束')
    return 1

# compute_time()
print(compute_time())
View Code

3.参数传递

import time
def timmer(func):
    def wrapper(*args,**kwargs):
        start_time=time.time()
        res=func(*args,**kwargs)
        stop_time=time.time()
        print('运行时间是:%s'%(stop_time-start_time))
        return res
    return wrapper

@timmer
def compute_time(name):
    time.sleep(3)
    print('欢迎%s回来'%name)
    print('=========运行结束')
    return 1

@timmer
def foo():
    time.sleep(1)
    print('普通调用')
    return 2

print(compute_time('larry'))
print(foo())
View Code

(二)有参装饰器

import time
def timmer(func):
    def wrapper(*args,**kwargs):
        print('====>timmer.wrapper')
        start_time=time.time()
        res=func(*args,**kwargs) #auth_wrapper
        stop_time=time.time()
        print('run time is %s' %(stop_time-start_time))
        return res
    return wrapper



login_user={'user':None,'status':False}
def auth(driver='file'):
    def auth2(func):
        def wrapper(*args,**kwargs):
            print('=======>auth.wrapper')
            time.sleep(5)
            if driver == 'file':
                if login_user['user'] and login_user['status']:
                    res=func(*args,**kwargs)
                    return res
                else:
                    name=input('>>: ')
                    password=input('>>: ')
                    if name == 'egon' and password == '123':
                        login_user['user']='egon'
                        login_user['status']=True
                        print('\033[45mlogin successful\033[0m')
                        res=func(*args,**kwargs)
                        return res
                    else:
                        print('\033[45mlogin err\033[0m')
            elif driver == 'ldap':
                print('==========ldap的认证')
            elif driver == 'mysql':
                print('==========mysql的认证')
                return func(*args,**kwargs)
            else:
                print('=========未知的认证来源')
        return wrapper
    return auth2


@auth('file') #@auth2====>index=auth2(index)===>index=auth_wrapper
@timmer #index=timmer(auth_wrapper) #index=timmer_wrapper
def index():
    time.sleep(3)
    print('welcome to index page')
@auth(driver='mysql')
def home(name):
    print('%s welcome to home page' %name)
index() 
View Code

对于内部函数来说,外部传入的参数总是可见的,所以如果需要为装饰器传递参数的话,可以在装饰器的外层包裹一层传递参数的函数将需要传递的参数传递进

posted @ 2017-05-27 17:06  geek_ace  阅读(167)  评论(0编辑  收藏  举报