作业20200323

一:编写函数,(函数执行的时间用time.sleep(n)模拟)
二:编写装饰器,为函数加上统计时间的功能
三:编写装饰器,为函数加上认证的功能

import time

def timer(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        res = func(*args, **kwargs)
        end = time.time()
        print(f'程序用时:{end - start}')
        return res

    return wrapper

def auth(func):

    def login():
        user_info = 'egon', '1234'
        print('请登录')
        name = input("name >>>:").strip()
        pwd = input("pwd >>>:").strip()
        if (name, pwd) == user_info:
            print('登录成功')
            return True
        else:
            print('登录失败')
            return False

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

    return wrapper


@auth
@timer
def my_func():
    time.sleep(2)
    print('this is my_func')


if __name__ == '__main__':
    my_func()

四:编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),要求登录成功一次,后续的函数都无需再输入用户名和密码
注意:从文件中读出字符串形式的字典,可以用eval('{"name":"egon","password":"123"}')转成字典格式

atm.py

def auth(func):
    def wrapper(*args, **kwargs):
        if current_user:
            res = func(*args, **kwargs)
            return res
        else:
            print('请先登录')

    return wrapper


def login():
        with open('db.txt', 'rt', encoding='utf8') as f:
            name = input('name>>>:').strip()
            pwd = input('pwd>>>:').strip()
            for line in f:
                n = eval(line.strip()).get('name')
                p = eval(line.strip()).get('password')

                if (name, pwd) == (n, p):
                    current_user.append(name)
                    print("登录成功")
                    break
            else:
                print('用户名或密码错误')


def logout():
    print('欢迎下次再来')
    exit()


@auth
def transfer():
    print('this is transfer function')


@auth
def check_balance():
    print('this is check_balance function')


current_user = []

def atm():
    cmd_dict = {
        '1': ('登录', login),
        '2': ('查询余额', check_balance),
        '3': ('转账', transfer),
        '4': ('退出', logout),
    }

    while 1:
        cmd = input("请选择功能的编号:").strip()
        if cmd not in cmd_dict:
            print('好好输入别闹')
            continue

        func = cmd_dict.get(cmd)[1]
        func()
        
        
if __name__ == '__main__':
    atm()

db.txt

{"name":"egon","password":"123"}
{"name":"tank","password":"123"}

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

import time

def timer(func):
    def wrapper(*args, **kwargs):
        now = int(time.time())
        if now - current_user[1] < 20:
            res = func(*args, **kwargs)
            return res
        else:
            print('登录超时')

    return wrapper



def auth(func):
    def wrapper(*args, **kwargs):
        if current_user[0]:
            res = func(*args, **kwargs)
            return res
        else:
            print('请先登录')

    return wrapper



def login():
        with open('db.txt', 'rt', encoding='utf8') as f:
            name = input('name>>>:').strip()
            pwd = input('pwd>>>:').strip()
            for line in f:
                n = eval(line.strip()).get('name')
                p = eval(line.strip()).get('password')

                if (name, pwd) == (n, p):
                    current_user[0:2] = [name, int(time.time())]
                    print("登录成功")
                    break
            else:
                print('用户名或密码错误')


def logout():
    print('欢迎下次再来')
    current_user.clear()


@auth
@timer
def transfer():
    print('this is transfer function')


@auth
@timer
def check_balance():
    print('this is check_balance function')


# 记录用户名和登录时间
current_user = [None, 0]

def atm():
    cmd_dict = {
        '1': ('登录', login),
        '2': ('查询余额', check_balance),
        '3': ('转账', transfer),
        '4': ('退出', logout),
    }

    while 1:
        cmd = input("请选择功能的编号:").strip()
        if cmd not in cmd_dict:
            print('好好输入别闹')
            continue

        func = cmd_dict.get(cmd)[1]
        func()


if __name__ == '__main__':
    atm()

db.txt

{"name":"egon","password":"123"}
{"name":"tank","password":"123"}

六:选做题
思考题(选做),叠加多个装饰器,加载顺序与运行顺序,可以将上述实现的装饰器叠加起来自己验证一下

def deco1(func):
    def inner1(*args, **kwargs):
        func1(*args, **kwargs)
    return inner1

def deco2(func):
    def inner2(*args, **kwargs):
        func2(*args, **kwargs)
    return inner2

def deco3(func):
    def inner3(*args, **kwargs):
        func3(*args, **kwargs)
    return inner3
    

   
@deco1
@deco2
@deco3 
def index():
    pass

index()

# 上面语法糖的形式装饰器的本质就是:index = deco1(deco2(deco3(index)))		(表达式1)

# 加载顺序:从下往上
# 执行顺序:从上往下

# 加载时:按照表达式1的顺序
	- 首先,将被装饰函数index当实参传给deco3,返回deco3的inner3函数,
    - 然后,返回的inner3当实参传给deco2,返回deco2的inner2函数,
    - 最后,将返回的inner2当实参传给deco1,返回deco1的inner1,

# 加载完毕后,inner1的func1是inner2, inner2的func2是inner3, inner3的func3是index
    
# 运行时:index()
	- 首先,执行index()本质是执行deco1返回的inner1()
    - 然后, 执行inner1(),开始执行inner1内部的func1(func1指向inner2的内存地址),即开始执行inner2的内存地址上的函数,
    - 再然后, 执行inner2(), 开始执行inner2内部的func2(func2指向inner3的内存地址),即开始执行inner3的内存地址上的函数,
    - 最后,执行inner3(),开始执行inner3内部的func3(func3是最初的index),即执行index函数

posted @ 2020-03-23 18:13  the3times  阅读(29)  评论(0)    收藏  举报