函数--装饰器及语法糖


函数--装饰器

简单表述

由名称空间 函数对象 闭包函数组合而来

原则:

? 开放封闭原则

? 开放:对扩展开放

? 封闭:会修改封闭

核心思想:

? 在不改变 " 装饰对象内部代码 "和 ” 原有调用方式 “ 的基础之上添加额外功能

器:指的是工具
装饰:给被装饰对象添加额外的功能

def index():
    print('from index')
index()
#统计index函数的执行时间

 import time

#pirnt(time.time())		#1637036293.0609405
#获取的结果叫时间戳(运行代码的那一刻距离1970-1-1所经历的秒数)
time .sleep(3)		#让程序原地等待3秒
print('睡饱了')

def index()
	time.sleep(3)
    print('from index')

#统计index函数的执行时间
#在函数运行之前统计一次时间
start_time = time.time()
index()
#在函数运行完毕之后在统计
end_time = time.time()
#计算差值
print(end_time - start_time)

装饰器简易版本

#给函数添加统计执行时间的功能

improt time
def index():
    time.sleep(3)
    print('jjjjjj')
def outer(func)
	def get_time():
        start_time = time.time()
        func()
        end_time = time.time
        print('函数运行时间' % (end_time - start_time)
    return get_time		#将get_time函数名返回出去
index = outer(index)	#outer(index函数名)	#左侧的变量名index指代是函数名get_time
index()

解决参数问题

import time
def index():
    time.sleep(3)
    print('jkjkkjjkjk')
def login(name):
    time.sleep(1)
    print('%s正在解决'%name)
def outer(func):			#func指向的是函数名login
    #func = login
    def get_time(*args,**kwargs):
        start_time = time.time()
        func(*args,**kwargs)
        end_time = time.time()
        print('函数运行时间:%s' % (end_time - start_time))
    return get_time				#将get_time函数名返回出去
login = outer(login)
login('jason')
index = outer(index)
index()

解决返回值问题

import time
def index ():
    time.sleep(3)
    print('使劲敲!')
    return 'from index'
def login(name):
    time.sleep(1)
    print('%s正在解决'%name)
    return 'from login'
def outer(func):				#func指向的函数名login   #func = login
    def get_time(*args,**kwargs):
        start_time = time.time()
        res = func(*args,**kwargs)	#接收被装饰函数的返回值
        end_time = time.time()
        print('函数运行时间:%' % (end_time - start_time))
        return res				#执行完get_time之后返回被装饰函数执行后的返回值
    return = get_time			#将get_time函数名返回出去
#index = outer(index)
#res = index()
#print(res)
login = outer(login)
res1 = login('jason')
print(res1)

认证装饰器

import time


def index():
    time.sleep(1)
    print('百万大奖')


def home():
    time.sleep(1)
    print('就是敲')


def register():
    time.sleep(1)
    print('注册')

#定义一个用于记录用户是否登录的数据
is_login = {'is_login': False}


def login_auth(func):
    def auth(*args, **kwargs):
        if is_login.get('is_login'):
            res = func(*args, **kwargs)
            return res

        username = input('username>>>').strip()
        password = input('password>>>').strip()
        if username == 'jjj' and password == 111:
            res = func(*args, **kwargs)
            is_login['is_login'] = True
            return res
        else:
            print('用户名密码错误')
    return auth


index = login_auth(index)
index()
home = login_auth(home)
home()
register = login_auth(register)
register()

装饰器固定模板

def outer(func):
    def inner(*args, **kwargs):
        print('执行函数之前可以添加的额外功能')
        res = func(*args, **kwargs)  # 执行被装饰的函数
        print('执行函数之后可以添加的额外功能')
        return res  # 将被装饰函数执行之后的返回值返回
    return inner

装饰器语法糖

def outer(func):
    def inner(*args,**kwargs):
        print('执行函数前可以额外加的功能')
        res = func(*args,**kwargs):
        print('执行函数后可以额外加的功能')
        return res
    return inner
@outer
def index(*args,**kwargs):
    print('from index')
@outer 
def home():
    print('from home')
    
    '''语法糖必须紧贴着装饰对象上方'''
    '''装饰器语法糖会自动将下面紧贴的被装饰对象名字当做参数传给装饰器函数调用'''

扩展

双层语法糖

# 统计函数运行时间
import time
def get_time(func):
    def inner(*args, **kwargs):
        start_time = time.time()
        res = func(*args, **kwargs)  # 执行被装饰的函数
        end_time = time.time()
        print('函数执行时间:%s'%(end_time-start_time))
        return res  # 将被装饰函数执行之后的返回值返回
    return inner
# 校验用户登录装饰
def login_auth(func):
    def inner(*args, **kwargs):
        # 1.先获取用户的用户名和密码
        username = input('username>>>:').strip()
        password = input('password>>>:').strip()
        # 2.校验用户名和密码是否正确
        if username == 'jason' and password == '123':
            res = func(*args, **kwargs)  # 执行被装饰的函数
            return res  # 将被装饰函数执行之后的返回值返回
        print('用户名或密码错误 无权限执行')
    return inner
@login_auth
@get_time
def index():
    time.sleep(1)
    print('from index')
index()

装饰器修复技术

from functools import wraps
def outer(func):
    @wraps(func)  # 修复技术就是为了让被装饰对象更加不容易被察觉装饰了
    def inner(*args, **kwargs):
        print('执行函数之前可以添加的额外功能')
        res = func(*args, **kwargs)  # 执行被装饰的函数
        print('执行函数之后可以添加的额外功能')
        return res  # 将被装饰函数执行之后的返回值返回
    return inner


@outer  # index = outer(index)
def index():
    print('from index')
print(index)
help(index)

def home():
    """这是一个home函数"""
    print('from home')
# help(index)
# help(home)
# print(index)
# help(len)

有参装饰器

# 判断七句print执行顺序
def outter1(func1):
    print('加载了outter1')
    def wrapper1(*args, **kwargs):
        print('执行了wrapper1')
        res1 = func1(*args, **kwargs)
        return res1
    return wrapper1

def outter2(func2):
    print('加载了outter2')
    def wrapper2(*args, **kwargs):
        print('执行了wrapper2')
        res2 = func2(*args, **kwargs)
        return res2
    return wrapper2

def outter3(func3):
    print('加载了outter3')
    def wrapper3(*args, **kwargs):
        print('执行了wrapper3')
        res3 = func3(*args, **kwargs)
        return res3
    return wrapper3


@outter1
@outter2
@outter3
def index():
    print('from index')