装饰器-练习

一. 编写函数,(函数执行的时间用time.sleep(n)模拟)

import time
def index(x, y, z):
    time.sleep(1)
    print('index is run...')
    return x, y, z

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

import time
def timer(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        res = func(*args, **kwargs)
        stop_time = time.time()
        print(f'{func.__name__} run time: ', stop_time - start_time)
        return res

    return wrapper


@timer  # index = wrapper = timer(index)
def index(x, y, z):
    time.sleep(1)
    print('index is run...')
    return x, y, z


res = index(1, 2, 3)
'''
index is run...
index run time:  1.0003461837768555
'''
print(res)  # (1, 2, 3)

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

import time
username = 'egon'
password = '123'


def login():
    inp_username = input("输入用户名>>:").strip()
    inp_password = input("输入用户密码>>:").strip()
    if inp_username == username and inp_password == password:
        print("恭喜登录成功!")
        return inp_username
    else:
        print("登录失败!")


def auth(func):
    def wrapper(*args, **kwargs):
        username = login()
        if username:
            res = func(*args, **kwargs)
            return res
    return wrapper

@auth  # index = wrapper = auth(index)
def index(x, y, z):
    time.sleep(1)
    print('index is run...')
    return x, y, z

res = index(1, 2, 3)
print(res)

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

# 注意:从文件中读出字符串形式的字典,可以用eval('{"username":"egon","password":"123"}')转成字典格式
import time
import os

DB_PATH = r'db.txt'
login_state = None
def create_db():
    if not os.path.isfile(DB_PATH):
        with open(DB_PATH, mode='wt', encoding='utf-8') as f:
            f.write('{"username":"egon","password":"123"}\n{"username":"alex","password":"123"}\n')



def read_db(name, pwd):
    with open(DB_PATH, mode='rt', encoding='utf-8') as f:
        for line in f:
            res = line.strip()
            if not res:
                continue
            current_user = eval(line)
            username, password = current_user.values()
            if name == username and password == pwd:
                return name

def login():
    create_db()
    
    inp_username = input("输入用户名>>:").strip()
    inp_password = input("输入用户密码>>:").strip()
    res = read_db(inp_username, inp_password)
    if res:
        print("恭喜登录成功!")
        global login_state
        login_state = inp_username
        return inp_username
    else:
        print("登录失败!")


def auth(func):
    def wrapper(*args, **kwargs):
        if not login_state:
            login()
        else:
            res = func(*args, **kwargs)
            return res
    return wrapper

@auth  # index = wrapper = auth(index)
def index(x, y, z):
    time.sleep(1)
    print('index is run...')
    return x, y, z

@auth  # home = wrapper = auth(home)
def home(x, y, z):
    time.sleep(0.5)
    print('home is run...')
    return x, y, z

res = index(1, 2, 3)
print(res)

res = home(4, 5, 6)
print(res)

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

import time
import os

DB_PATH = r'db.txt'
login_state = None
def create_db():
    if not os.path.isfile(DB_PATH):
        with open(DB_PATH, mode='wt', encoding='utf-8') as f:
            f.write('{"username":"egon","password":"123"}\n{"username":"alex","password":"123"}\n')



def read_db(name, pwd):
    with open(DB_PATH, mode='rt', encoding='utf-8') as f:
        for line in f:
            res = line.strip()
            if not res:
                continue
            current_user = eval(line)
            username, password = current_user.values()
            if name == username and password == pwd:
                return name

def login(*args):
    create_db()

    inp_username = input("输入用户名>>:").strip()
    inp_password = input("输入用户密码>>:").strip()
    res = read_db(inp_username, inp_password)
    if res:
        print("恭喜登录成功!")
        global login_state
        login_state = inp_username
        return inp_username
    else:
        print("登录失败!")


def auth(func):
    def wrapper(*args, **kwargs):
        if not login_state:
            login()
        else:
            res = func(*args, **kwargs)
            return res
    return wrapper


@auth  # index = wrapper = auth(index)
def index(*args):
    time.sleep(1)
    print('index is run...')
    return args

@auth  # home = wrapper = auth(home)
def home(*args):
    time.sleep(0.5)
    print('home is run...')
    return args

func_dic = {
    '0': ('登录', login),
    '1': ('index', index),
    '2': ('home', home),
}
def run(*args, **kwargs):
    while True:
        for key, value in func_dic.items():
            print(f'({key}):{value[0]}', end=' ')
        print()

        start_time = time.time()
        cmd = input('输入命令编号>>:').strip()
        stop_time = time.time()
        if stop_time - start_time >= 4:
            print('长时间没操作, 需要重新登录.')
            global login_state
            login_state = None
            continue
        if not cmd.isdigit():
            print('请输入数字')
            continue
        if cmd not in func_dic:
            print("输入命令编号范围不正确")
        func_dic[cmd][1](*args, **kwargs)

res = run(1, 2, 3)
print(res)

六. 选做题

# 思考题(选做),叠加多个装饰器,加载顺序与运行顺序,可以将上述实现的装饰器叠加起来自己验证一下
"""
@deco1 # index=deco1(deco2.wrapper的内存地址)
@deco2 # deco2.wrapper的内存地址=deco2(deco3.wrapper的内存地址)
@deco3 # deco3.wrapper的内存地址=deco3(index)
def index():
    pass
"""
def decorator1(func):
    def wrapper(*args, **kwargs):
        print('from decorator1')
        res = func(*args, **kwargs)
        return res
    return wrapper


def decorator2(func):
    def wrapper(*args, **kwargs):
        print('from decorator2')
        res = func(*args, **kwargs)
        return res
    return wrapper


def decorator3(func):
    def wrapper(*args, **kwargs):
        print('from decorator3')
        res = func(*args, **kwargs)
        return res
    return wrapper

@decorator1   # index = decorator1中的wrapper的内存地址 = decorator1(decorator2(decorator3(index)) )
@decorator2   # decorator2中的wrapper的内存地址 = decorator2(decorator3(index))
@decorator3   # decorator3中的wrapper的内存地址 = decorator3(index)
def index():
    print('from index')

index()
'''
from decorator1
from decorator2
from decorator3
from index
'''
# 加载顺序: index > decorator3 > decorator2 > decorator1
# 运行顺序: decorator1 > decorator2 > decorator3 > index
posted @ 2020-03-23 16:14  给你加马桶唱疏通  阅读(123)  评论(0编辑  收藏  举报