day14作业:装饰器

装饰器

一:编写函数,(函数执行时间用time.sleep(n)代表)

import time
def home(n):
	time.sleep(n)
	print('welcome to home page')

二:编写装饰器,为函数加上统计时间的功能

def timmer(func):
	def wrapper(*args,**kwargs):
		start_time=time.time()
		res=func(*args,**kwargs)
		stop_time=time.time()
		print(stop_time-start_time)
		return res
	return wrapper

三:编写装饰器,为函数加上认证的功能

认证文件来源

def outter(engine='file'):
	def deco2(func2):
		def wrapper2(*args,**kwargs):
			name=input('username>>>: ').strip()
			pwd=input('password>>>: ').strip()

			if engine == 'file':
				print('基于file的认证')
				if name == 'juanfu' and pwd == '123':
					print('login successful')
					res2=func2(*args,**kwargs)
					return res2
				else:
					print('username or password error')
			elif engine == 'mysql':
				print('基于mysql的认证')
			elif engine == 'ldap':
				print('基于ldap的认证')
			else:
				print('未知的engine')

		return wrapper2
	return deco2
@outter(engine='mysql')  # @deco2  # index=deco2(index)
def index(x,y):
	print('index=>',x,y)

index(1,2)  # index=>wrapper

角色认证

def auth(role):
    def wrapper(func):  # 被装饰的函数对象
        def inner(*args, **kwargs):  # 被装饰的函数对象的参数: 可能有,也可能没有
            # 调用被装饰对象前添加的功能可以在此处写
            # 调用前添加认证
            if role == '销售部':
                res = func(*args, **kwargs)  # timer()
                # 调用被装饰对象后添加的功能可以在此处写
                return res
            elif role == '技术能力有限部门':
                res = func(*args, **kwargs)  # timer()
                # 调用被装饰对象后添加的功能可以在此处写
                return res
            else:
                print('该用户没有权限...')
        return inner
    return wrapper

@auth('vip')
def index():
    pass

四:编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),要求登录成功一次,后续的函数都无需再输入用户名和密码

注意:从文件中读出字符串形式的字典,可以用eval(’{“name”:“egon”,“password”:“123”}’)转成字典格式

方式一:

login=False
def auth(func):
	def wrapper(*args,**kwargs):
		global login
		if login :
			res = func(*args, **kwargs)
			return res
		else:
			while True:
				username=input('请输入用户名: ').strip()
				pwd=input('请输入用户名: ').strip()
				with open('user.txt','r',encoding='utf-8')as f:
					dic=f.read()
					eval(dic)
				if username in dic and pwd in dic:
					print('登录成功')
					login=True
					res=func(*args,**kwargs)
					return res
				else:
					print('用户名或密码错误')
	return wrapper

@auth
def home(n):
	global login
	time.sleep(n)
	print('welcome to home page')
home(1)
@auth
def index():
	global login
	print('====>from index')
index()

方式二:

# 1) 先将user.txt文件中的数据读取出来,把 str 转换成 dict 类型
with open('user.txt', 'r', encoding='utf-8') as f:
    # 从文件中读取出来的都是字符串
    user_data = f.read()
    # print(user_data, type(user_data))
    # 通过eval内置函数,将str ---> dict 类型
    # eval,可以将字符串转行成python中对应的数据类型;
    user_dict = eval(user_data)
    # print(user_dict, type(user_dict))
# 用于记录是否有用户登录
user_login = {'user': None}
# 注意(涨知识):
# 在函数内部引用全局变量时,可变类型不需要global,不可变类型需要使用global
# 登录功能
def login():
    while True:
        username = input('请输入用户名: ').strip()
        password = input('请输入密码: ').strip()
        if username == user_dict.get('name') and password == user_dict.get('password'):
            # 登录成功后,必须记录用户登录状态
            # 将user_login全局变量,引用到函数内部来修改
            user_login['user'] = username
            print('login successful!')
            break
        else:
            print('登录失败!')

# 2) 登录认证装饰器编写
def login_auth(func):  # 被装饰的函数对象
    def inner(*args, **kwargs):  # 被装饰的函数对象的参数: 可能有,也可能没有
        # 用户登录认证的逻辑
        if user_login.get('user'):
            res = func(*args, **kwargs)
            # 调用被装饰对象后添加的功能可以在此处写
            return res
        else:
            # 调用登录功能,让用户去登录
            login()
            res = func(*args, **kwargs)
            return res
    return inner
@login_auth
def pay():
    print('pay...')
@login_auth
def transfer():
    print('transfer...')
pay()
import time
time.sleep(1)
transfer()

五:编写装饰器,为多个函数加上认证功能,要求登录成功一次,在超时时间内无需重复登录,超过了超时时间,则必须重新登录

方式一:

import time
import random
user={'user':None,'login_time':None,'timeout':0.0005}

def timmer():
	def wrapper():
		start_time=time.time()
		res=func(*args,**kwargs)
		stop_time=time.time()
		print(stop_time-start_time)
		return res
	return wrapper

def auth(func):
	def wrapper(*args,**kwargs):
		if user['user']:
			timeout=time.time()-user['login_time']
			if timeout < user['timeout']:
				return func(*args,**kwargs)

		while True:
			username=input('请输入用户名: ').strip()
			pwd=input('请输入用户名: ').strip()
			with open('user.txt','r',encoding='utf-8')as f:
				dic=f.read()
				eval(dic)
			if username in dic and pwd in dic:
				user['user']=username
				user['login_time']=time.time()
				print('登录成功')
				res=func(*args,**kwargs)
				return res
			else:
				print('用户名或密码错误')
	return wrapper

@auth
def home(n):
	time.sleep(n)
	print('welcome to home page')

@auth
def index():
	time.sleep(1)
	print('====>from index')

home(0.0001)
index()

方式二:

import time
# 1) 先将user.txt文件中的数据读取出来,把 str 转换成 dict 类型
with open('user.txt', 'r', encoding='utf-8') as f:
    # 从文件中读取出来的都是字符串
    user_data = f.read()
    # print(user_data, type(user_data))
    # 通过eval内置函数,将str ---> dict 类型
    # eval,可以将字符串转行成python中对应的数据类型;
    user_dict = eval(user_data)
    # print(user_dict, type(user_dict))

# 用于记录是否有用户登录
user_login = {'user': None}


# 注意(涨知识):
# 在函数内部引用全局变量时,可变类型不需要global,不可变类型需要使用global
# 登录功能
def login():
    while True:
        username = input('请输入用户名: ').strip()
        password = input('请输入密码: ').strip()
        if username == user_dict.get('name') and password == user_dict.get('password'):
            # 登录成功后,必须记录用户登录状态
            # 将user_login全局变量,引用到函数内部来修改
            # 以登录用户名  作为 字典的key, 以一个列表作为该用户的value值,value值的格式是 [用户名, 密码, 登录成功时的时间]
            now_time = time.time()
            user_login['user'] = [username, password, now_time]
            print('login successful!')
            break
        else:
            print('登录失败!')


# 2) 登录认证装饰器编写
def login_auth(func):  # 被装饰的函数对象
    def inner(*args, **kwargs):  # 被装饰的函数对象的参数: 可能有,也可能没有
        # 用户登录认证的逻辑
        # [用户名, 密码, 登录成功时的时间]
        user_info = user_login.get('user')
        if user_info:

            # 判断用户的登录时间是否失效, 假设判断超时时间为 5 秒
            # 1) 获取当前时间
            n_time = time.time()
            if (n_time - user_info[2]) <= 5:
                res = func(*args, **kwargs)
                # 调用被装饰对象后添加的功能可以在此处写
                return res
            else:
                login()
        else:
            # 调用登录功能,让用户去登录
            login()

    return inner


@login_auth
def pay():
    print('pay...')


@login_auth
def transfer():
    print('transfer...')

# 1) 先调用pay函数,此时未登录,装饰器就会先去执行登录功能
pay()

# 模拟延时6秒
time.sleep(6)

# 2) 执行到该行代码时,证明已经登录成功
transfer()

六:编写下载网页内容的函数,要求功能是:用户传入一个url,函数返回下载页面的结果

七:为题目五编写装饰器,实现缓存网页内容的功能:

具体:实现下载的页面存放于文件中,如果文件内有值(文件大小不为0),就优先从文件中读取网页内容,否则,就去下载,然后存到文件中

扩展功能:用户可以选择缓存介质/缓存引擎,针对不同的url,缓存到不同的文件中

八:还记得我们用函数对象的概念,制作一个函数字典的操作吗,来来来,我们有更高大上的做法,在文件开头声明一个空字典,然后在每个函数前加上装饰器,完成自动添加到字典的操作

方式一:

dic={}

def deco(name):
	def wrapper(func):
		dic[name]=func.__name__
	return wrapper

@deco('story1')
def f1():
	print('小鸟妈妈问小鸟:"今天扎什么发型"')
@deco('story2')
def f2():
	print('小鸟说:"啾啾".')
print(dic)

方式二:

func_dic = {}
number = 1

def func_dict_add(func):
    global number
    func_dic[number] = func
    # func_dic[func.__name__] = func
    number += 1
    def inner(*args, **kwargs):

        res = func(*args, **kwargs)
        return res
    return inner


print('装饰前: ', func_dic)
@func_dict_add
def func1():pass
@func_dict_add
def func2():pass
@func_dict_add
def func3():pass
@func_dict_add
def func4():pass
@func_dict_add
def func5():pass
print('装饰后: ', func_dic)

九 编写日志装饰器,实现功能如:一旦函数f1执行,则将消息2017-07-21 11:12:11 f1 run写入到日志文件中,日志文件路径可以指定

注意:时间格式的获取

方式一:

import time
time.strftime('%Y-%m-%d %X')
def d_deco(func):
	def wrapper(*args,**kwargs):
		res=func(*args,**kwargs)
		with open('access.log','a',encoding='utf-8')as f:
			t=time.strftime('%Y-%m-%d %H:%M:%S')
			msg=f'{t} {func.__name__} run\n'
			f.write(msg)
		return res
	return wrapper

@d_deco
def f1():
	print('小鸟妈妈问小鸟:"今天扎什么发型"')
@d_deco
def f2():
	print('小鸟说:"啾啾".')

f1()
f2()

方式二:

import time
# 获取当前时间,并且是人能看得懂时间格式
# print(time.strftime('%Y-%m-%d %X'))
def wrapper(func):
    def inner(*args, **kwargs):
        timer = time.strftime('%Y-%m-%d %X')
        with open('log.txt', 'a', encoding='utf-8') as f:
            log_data = f'{timer} {func.__name__} run...\n'
            f.write(log_data)

        res = func(*args, **kwargs)
        return res
    return inner


@wrapper
def f1():
    pass

f1()
f1()
f1()
f1()
f1()

猜你喜欢

转载自blog.csdn.net/yikenaoguazi/article/details/107497010
今日推荐