18函数----装饰器

Python允许使用装饰器对函数进行装饰,装饰器可以帮助函数实现一些通用的功能,在函数调用前运行些预备代码或函数调用后执行清理工作。如:插入日志、检测性能(计时)、事务处理、缓存、权限校验等。这样编写函数时就可以专注于功能的实现,就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。

定义:装饰器本质就是函数,功能是在不更改原函数的代码前提下给函数增加新的功能。包装后返回一个装饰后的函数对象,该函数对象将更新原函数对象,程序将不再能访问原始函数对象。

装饰器的基础知识:=高阶函数+函数嵌套+闭包

原则:1不修改被修饰函数的源代码     2不修改被修饰函数的调用方式,在两者的前提上扩展其功能

例子1:

# 计算时间

import time

def deco(func):
    def wrapper(*args, **kwargs):#接收任意参数
        start_time = time.time()
        res = func(*args, **kwargs)#这里有括号,运行了func函数
        end_time = time.time()
        spend_time = end_time - start_time
        print('运行时间:', spend_time)
        return res
    return wrapper

@deco  # foo=deco(foo)
def foo():
    time.sleep(1)
    print('hello cc')

foo()

 例子2:

# 验证授权
user_list = [{'username':'cc','password':123},{'username':'dd','password':111}]
def auth(func):
    def wrapper(*args, **kwargs):
        name = input('name>>>:')
        pwd = int(input('pwd>>>:'))
        for i in user_list:
            if i['username'] == name and i['password'] == pwd:
                res = func(*args, **kwargs)
                return res
    return wrapper


@auth
def index():
    print('index....')
@auth
def shopping():
    print('shoppiing....')

index()
shopping()

 

例子3.1:带参装饰器(一)

# form functools import wraps提供了装饰器@wrap来保留原函数的属性
from functools import wraps

user_list = [{'username':'cc','password':123},{'username':'dd','password':111}]

def deco(type='a'):#type='a'默认参数
    def auth(func):
        @wraps(func)#保留原函数的属性
        def wrapper(*args, **kwargs):
            if type == 'a':
                print('这是参数aaaaaa')
            else:
                print('这是参数bbbbbb')
            name = input('name>>>:')
            pwd = int(input('pwd>>>:'))
            for i in user_list:
                if i['username'] == name and i['password'] == pwd:
                    res = func(*args, **kwargs)
                    return res
        return wrapper
    return auth


@deco()  # @deco(type='a')=====>@auth,但是这时候带了参数type='a'
def index():
    print('index....')


@deco(type='kkkk')
def shopping():
    '''kkkkkkkkkkkkkkkkkk'''
    print('shoppiing....')

index()
shopping()
print(shopping.__doc__)#装饰器@wrap来保留原函数的属性

 例子3.2  带参装饰器(二)flask_web开发实战101页

def permission_required(permission):
    def decorator(f):
        @wraps(f)  #@wrap来保留原函数的属性
        def decorated_function(*args, **kwargs):
            if not current_user.can(permission):
                abort(403)  #服务器拒绝了你的地址请求
            return f(*args, **kwargs)
        return decorated_function
    return decorator


def admin_required(f):
    return permission_required(Permission.ADMINISTER)(f)

#下面是使用
@auth.route('/admin')
@login_required
@admin_required
def for_admin():
    return 'for admin'


@auth.route('/moderator')
@login_required
@permission_required(Permission.MODERATE_COMMENTS)
def for_moderator():
    return 'for maderator'

 例3.3 模拟session

# 模拟session
from functools import wraps #装饰器@wrap来保留原函数的属性

userlist = [{'username':'cc', 'pwd':'123'},
            {'username':'dd', 'pwd':'234'},
            {'usernmae':'ee', 'pwd':'111'}]
current_dit = {'username':None, 'login':False} #记录用户登录状态

def auth(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        if current_dit['username'] and current_dit['login']:
            return func(*args, **kwargs)
        name = input('please input your name:')
        pwd = input('please input pwd:')
        for user in userlist:
            if name==user['username'] and pwd==user['pwd']:
                current_dit['username'] = name
                current_dit['login'] = True
                return func(*args, **kwargs)
        else:
            print('name or pwd wrong')
    return wrapper

@auth
def index():
    """dddd"""
    print('index...')

@auth
def shopping():
    print('shoping....')

index()
shopping()

  例子4:叠加多个装饰器

# 装饰器的加载顺序是从内到外的,从靠近函数的装饰器开始从内往外加载。
# 加载顺序:outer函数的调用顺序:自下而上
# 执行顺序:wrapper的执行顺序,自上而下
def outer1(func):
    print('加载了Outer1..')
    def wrapper1(*args, **kwargs):
        print('执行了wrapper1...')
        res = func(*args, **kwargs)
        return res
    return wrapper1

def outer2(func):
    print('加载了Outer2..')
    def wrapper2(*args, **kwargs):
        print('执行了wrapper2...')
        res = func(*args, **kwargs)
        return res
    return wrapper2

def outer3(func):
    print('加载了Outer3..')
    def wrapper3(*args, **kwargs):
        print('执行了wrapper3...')
        res = func(*args, **kwargs)
        return res
    return wrapper3

@outer1
@outer2
@outer3
def index():
    print('from index.....')   #====>index = outer1(outer2(outer3(index)))

print('========')
index()


#结果:
# 加载了Outer3..
# 加载了Outer2..
# 加载了Outer1..
# ========
# 执行了wrapper1...
# 执行了wrapper2...
# 执行了wrapper3...
# from index.....

 

上一篇:*args,**kwargs 的用法


下一篇:python通关 集合操作方法详解