装饰器进阶和迭代器

装饰器进阶和迭代器

昨日补充

可变类型,直接在函数内部调用

不可变类型,需要在函数内部调用,要使用global

叠加装饰器:

每一个新的功能都应该写一个新的装饰器

需求:

为被装饰对象,添加统计时间与登录认证的功能

# 登录认证

import time


def re_login():
    with open('a.txt', 'r', encoding='utf-8') as rf:
        data = rf.read()
        data1 = data.strip('
').split('|')
        data2 = ''.join(data1)
        data3 = data2.split('
')
    return data3

    # print(data3)


# 登录认证装饰器
def login(func):
    def inner1(*args, **kwargs):
        username = input('请输入用户名:').strip()
        password = input("请输入密码:").strip()

        res = re_login()

        if username + password in res:
            print('恭喜您,登录成功!')
            re = func(*args, **kwargs)
            return re

        else:
            print('对不起,登录失败!')
            re = func(*args, **kwargs)
            return re

    return inner1


# 统计时间装饰器
def time_record(func):
    def inner2(*args, **kwargs):
        print('开始统计!')
        start_time = time.time()
        res = func(*args, **kwargs)
        end_time = time.time()
        print(f'执行时间:{end_time - start_time}')
        return res

    return inner2


# @login  # inner1=inner(inner2)
# @time_record  # inner2

@time_record
@login
def func():
    print('开始下载电影!')
    time.sleep(5)
    print('下载电影结束!')


func()


开始统计!
请输入用户名:godlover
请输入密码:123456
恭喜您,登录成功!
开始下载电影!
下载电影结束!
执行时间:11.740200519561768



什么是叠加装饰器:

在同一个被装饰对象中,添加多个装饰器,并执行

@装饰1

@装饰2

def 被装饰对象():

​ pass

ps:装饰器在调用被装饰对象时才添加功能

装饰顺序:从下至上

执行顺序:从上至下

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


info_dict1 = {
    'name_info': None
}


def re_login():
    username = input('请输入用户名:').strip()
    password = input('请输入密码:').strip()
    with open('a.txt', encoding='utf-8') as f:
        for line in f:
            # print(line)
            name, pwd = line.strip('
').split('|')
            if username == name and password == pwd:
                print('登录成功!')
                info_dict1['name_info'] = name
            else:
                print('登录失败!')


def login(func):
    def inner(*args, **kwargs):
        if info_dict1.get('name_info'):
            print('免密登录成功!')
            res = func(*args, **kwargs)
            return res
        else:
            re_login()

    return inner


@login
def func1():
    print(1)


@login
def func2():
    print(2)


@login
def func3():
    print(3)


func1()
func2()
func3()




请输入用户名:godlover
请输入密码:123456
登录成功!
登录失败!
免密登录成功!
2
免密登录成功!
3


叠加装饰器的理解
内部的具体运行方式


def wrapper1(func):
    def inner1(*args, **kwargs):
        print('1-----start')
        # 被装饰对象在被调用时,如果还有其他装饰器,则会先执行其他装饰器中的inner
        res = func(*args, **kwargs)
        print('1-----end')
        print(res)
        return res

    print(1)
    return inner1


def wrapper2(func):
    def inner2(*args, **kwargs):
        print('2-----start')
        res = func(*args, **kwargs)
        print('2-----end')
        print(res)
        return res

    print(2)

    return inner2


def wrapper3(func):
    def inner3(*args, **kwargs):
        print('3-----start')
        res = func(*args, **kwargs)
        print('3-----end')
        print(res)
        return res


    print(3)

    return inner3


@wrapper1  # 3
@wrapper2  # 2
@wrapper3  # 1
def func():
    print('from func')
    return 1


func()


3
2
1
1-----start
2-----start
3-----start
from func
3-----end
1
2-----end
1
1-----end
1




ps:

无论inner中出现任何判断,都要返回fun(*args,**kwargs)的结果

当被装饰器对象还有其他装饰器时跳过直接执行inner

无参装饰器:

装饰在被装饰对象时,没有传参数的装饰器

@wrapper

有参装饰器:

@wrapper('参数')

用途:

在某些时候我们需要给用户的权限进行分类

# 调用时@wrapper('参数1')
def user_auth(user_role):
    def wrapper(func):
        def inner(*args, **kwargs):
            if user_role == 'SVIP':
                print(1)
                res = func(*args, **kwargs)
                return res
            elif user_role == '普通用户':
                print(2)
                res = func(*args, **kwargs)
                return res

        return inner

    return wrapper


# @user_auth('SVIP')  # 相当于@和后面的分开,先执行函数user_auth,返回wrapper,再将@和wrapper结合起来,返回inner
# def func():
#     print('from func')
#
#
# func()

@user_auth('普通用户')
def func():
    print('from func')


func()



2
from func

wraps:是一种修复工具,修复地是被装饰对象的空间

例如查看函数内部的注释:

from functools import wraps


def wrapper(func):
    @wraps(func)  # 是一个修复工具,用来修复被装饰对象的空间
    def inner(*args, **kwargs):
        '''
        这里是inner的注释
        :param args:
        :param kwargs:
        :return:
        '''
        res = func(*args, **kwargs)
        return res

    return inner


@wrapper
def func():
    '''
    这里是func的注释
    :return:
    '''
    print('from func')


print(func.__doc__)



   这里是func的注释
    :return:

迭代器

迭代器的工具

迭代:指的是重复迭代,每一个迭代的结果都是基于上一次的结果而来的

迭代器:指的是迭代取值的工具

可迭代对象:所有的序列类型:str,list,dict,tuple,set,f

什么是可迭代对象:

凡是内部有_ iter _()方法的都是可迭代对象

什么是迭代器对象:

通过可迭代对象._ iter _()方法的返回值就是迭代器对象

如何迭代取值:

迭代器对象._ next _()

ps:迭代器中的值取完时,会报错StopIteration

list =['jason','sean','egon','tank']
iter_list1 = list._iter_()
while True:
    #try:捕获异常
    try:
        print(iter_list1._next_())#报错
    except StopIteration:
        break
        

迭代器的优缺点:

优点:

1.不依赖于索引,迭代取值

2.节省内存空间

缺点:

1.取指定的某个值比较麻烦,每次取值都要从第一个值开始,无法通过索引取值

2.不能够通过len()计算长度

总结

可迭代对象 vs 迭代器对象

获取可迭代对象:

定义序列类型

特点:

凡是内置有_ iter _()方法的都是可迭代对象

获取迭代器对象:

过可迭代对象._ iter _()方法的返回值就是迭代器对象

特点:

内置有_ next _()方法

for 循环的原理

in自动将可迭代对象调用_iter_()方法变成迭代器对象

for i in 可迭代对象:
#迭代器对象调用_next_()方法取值
print(I)
里面也调用捕获异常机制

迭代器对象的本质是一个可迭代对象

文件本质既是可迭代对象又是迭代器对象

文件计较特殊:文件读取出来的时候就是一个迭代器对象

最后注意:

可迭代器对象不一定是迭代器对象(文件既是可迭代对象,也是迭代器对象,但是其他可迭代器不是迭代器对象)

但是迭代器对象一定是可迭代对象

原文地址:https://www.cnblogs.com/godlover/p/11854158.html