python基础学习-day17==课后作业练习(无参装饰器)

# 必做题:
# 1.编写函数,(函数执行的时间用time.sleep(n)模拟)
import time

def func(x, y):
    num = x + y
    time.sleep(3)
    print(num)
    return num
# 2.编写装饰器,为函数加上统计时间的功能
import time  # 源码


# 统计时间装饰器
def timer(func):  # func ---> 被装饰对象
    def inner(*args, **kwargs):  # 被装饰对象需要接收的参数

        # 被装饰对象执行之前的时间
        start_time = time.time()
        # *args, **kwargs将接收过来的参数,传给调用的被装饰对象,会得到一个返回值
        res = func(*args, **kwargs)  # 调用被装饰对象, 这行代码就是被装饰对象的执行全过程
        # 被装饰对象执行结束后的时间
        end_time = time.time()

        # 打印被装饰对象的执行时间
        # func.__name__ ---> 可以获取函数的名称
        print(f'当前被装饰对象[{func.__name__}] 执行时间为: [{end_time - start_time}]')
        return res

    return inner


@timer  # timer = inner = timer(func)
def func_demo():
    time.sleep(3)  # 单位: 秒
# 使用装饰器的目的: 1装饰对象添加新的功能 2、前提: 不修改被装饰对象的源代, 不修改用方式
# inner = timer(func)
# func = inner
# func() # --> inner()
# func_demo()

import os

def timer(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        res = func(*args, **kwargs)
        end = time.time()
        print(end - start)
        return res

    return wrapper

num = timer(num)
num(1,2)
# 3.编写装饰器,为函数加上认证的功能
# 全局变量: 用于记录是否有用户登录
login_user = None


# 登录功能
def login():
    username = input('请输入用户名: ').strip()
    password = input('请输入密码: ').strip()
    if username == 'tank' and password == '123':
        print('登录成功')
        # 登录成功后,给全局变量赋值,记录当前用户已经登录
        global login_user
        login_user = username

    else:
        print('登录失败')


# 登录认证装饰器
def login_auth(func):
    def inner(*args, **kwargs):
        # 被装饰对象执行前,为其添加新的功能
        # 在此处做登录认证
        if login_user:
            # 被装饰对象执行  func ---> play, shopping
            res = func(*args, **kwargs)
            return res

            # 被装饰对象执行后,为其添加新的功能
        else:
            print('未有用户登录,无法使用好玩的功能!')
            login()

    return inner

# play 与 shopping 功能使用前 必须先登录 否则,不允许使用,让其执行登录功能
@login_auth
def play():
    # 不使用装饰器
    # if not login_user:
    #     login()
    print('开始play了啊....')
    pass


@login_auth
def shopping():
    pass
# login()
# play()
# shopping()
import os

def login(func):
    def wrapper(*args,**kwargs):
        user_name = input('请输入用户名:')
        user_psd = input('请输入密码:')
        with open('name.txt','rt',encoding='utf-8')as f:
            for line in f:
                username,password = line.strip().split(':')
            if username==user_name and user_psd==password:
                print('登陆成功!')
            #   执行之前的num函数
                res = func(*args,**kwargs)
                return res
            else:
                print('登录失败!')
    return wrapper
num
=login(num) num(1,2)
# 4.编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),要求登录成功一次,后续的函数都无需再输入用户名和密码
# 注意:从文件中读出字符串形式的字典,可以用eval('{"name":"egon","password":"123"}')转成字典格式
# 1、打开db.txt文件,读取用户数据,转成字典类型
with open('db.txt', 'r', encoding='utf-8') as f:
    # 直接读取文件中的数据,得到的数据类型是: str
    user_data = f.read()
    print(user_data, type(user_data))
    '''
    {"name": "tank", "pwd": "123"}
    '''
    # eval(str) ---> 从str字符串中,检测python代码的语法,
    # 如果里面有{key: value},会将该数据生成对应的类型的内存地址
    user_dic = eval(user_data)
    print(user_dic, type(user_dic))

user_dic = user_dic
# print(user_dic)
# print(type(user_dic))
login_info = None

def login():
    username = input('请输入用户名: ').strip()
    if username in user_dic.get('name'):
        password = input('请输入密码: ').strip()
        if password == user_dic.get('pwd'):
            print('login successful')
            global login_info
            login_info = {username: password}

        else:
            print('密码错误')
    else:
        print('用户不存在')


def login_auth(func):
    def inner(*args, **kwargs):
        if login_info:
            res = func(*args, **kwargs)
            return res
        else:
            login()
    return inner


@login_auth
def withdraw():
    pass
@login_auth
def shopping():
    pass

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

# 全局变量,用于计算函数登录后的执行总时长
sum_time = 0  # ---》 func1 --> 3 ---> 6

def time_wait(func):
    # 登录成功后,可以使用的功能时长,单位 秒
    wait_time = 6

    def inner(*args, **kwargs):
        # 执行前时间
        start_time = time.time()
        res = func(*args, **kwargs)
        # 执行后时间
        end_time = time.time()
        global sum_time
        # 第一个函数进来后,func1 执行时长为3, func2 执行时长为3
        sum_time += (end_time - start_time)
        print(f'登录后执行的总时长: {sum_time}')
        # func1执行的时长 >= wait_time
        if sum_time >= wait_time:
            # 需要重新去登录
            login()
            sum_time = 0
        else:
            return res

    return inner


@time_wait
def func1():
    time.sleep(3)

@time_wait
def func2():
    time.sleep(3)

# func1()
# func2()
#
# # 此时总时长为6秒
# func1()
六、# 思考题(选做),叠加多个装饰器,加载顺序与运行顺序
# @deco1 # index=deco1(deco2.wrapper的内存地址)
# @deco2 # deco2.wrapper的内存地址=deco2(deco3.wrapper的内存地址)
# @deco3 # deco3.wrapper的内存地址=deco3(index)
# def index():
#     pass
原文地址:https://www.cnblogs.com/dingbei/p/12555744.html