码迷,mamicode.com
首页 > 其他好文 > 详细

叠加装饰器与迭代器

时间:2019-11-14 00:18:16      阅读:129      评论:0      收藏:0      [点我收藏+]

标签:需要   day   open   strip()   普通用户   统计   rap   读取   pen   

一、叠加装饰器

叠加装饰器的定义

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

每一个新的功能都应该被放到一个新的装饰器,否则代码冗余,可扩展性差。

叠加装饰器:
装饰的顺序:由下到上装饰

执行的顺序:由上往下

注意:无论inner中出现任何判断最后都要返回“调用后的被装饰对象”。

‘‘‘
叠加装饰器:
    在同一个被装饰对象中,添加多个装饰器,并执行。
    @装饰1
    @装饰2
    @装饰3
    def 被装饰对象():
        pass

    注意: 装饰器在调用被装饰对象时才会执行添加的功能。

    - 叠加装饰器:
        - 装饰的顺序: 由下到上装饰
        - 执行的顺序: 由上往下

    注意: 无论inner中出现任何判断,最后都要返回“调用后的被装饰对象” func(*args, **kwargs)

‘‘‘

# def wrapper(func):
#     def inner(*args, **kwargs):
#         # 注册
#         res = func(*args, **kwargs)
#         # 登录
#         return res
#
#     return inner


# 需求: 为被装饰对象,添加统计时间 与 登录认证功能
import time

user_info = {
    user: None
}


# 登录功能
def login():
    # 判断用户没有登录时,执行
    # 登录功能
    # global user
    username = input(请输入账号: ).strip()
    password = input(请输入密码: ).strip()
    with open(user.txt, r, encoding=utf-8) as f:
        for line in f:
            print(line)
            name, pwd = line.strip(\n).split(:)  # [tank, 123]

    if username == name and password == pwd:
        print(登录成功!)
        user_info[user] = username
        return True
    else:
        print(登录失败!)
        return False


# 登录认证装饰器
def login_auth(func):  # func---》 download_movie
    def inner1(*args, **kwargs):

        ‘‘‘
        注意: 无论inner中出现任何判断,
        最后都要返回“调用后的被装饰对象” func(*args, **kwargs)
        ‘‘‘

        # 登录认证
        if user_info.get(user):
            # res = download_movie(*args, **kwargs)
            res = func(*args, **kwargs)
            return res

        else:
            flag = login()
            # 添加用户是否登录判断
            if flag:
                res = func(*args, **kwargs)
                return res

            else:

                login()
                return func(*args, **kwargs)

    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


# 下载电影功能
‘‘‘
    - 叠加装饰器:
        - 装饰的顺序: 由下到上装饰
        - 执行的顺序: 由上往下
‘‘‘
@time_record  # inner2 = time_record(inner1地址)
@login_auth  # inner1 = login_auth(download_movie)
def download_movie():
    print(正在下载电影...)
    time.sleep(2)
    print(下载电影完成...)
    return GTWZ.mp4


# login()
# 执行的顺序: 先执行time_record功能,再执行login_auth功能
# 统计登录时间 + 下载时间
# download_movie()


# 装饰顺序
# @login_auth  # inner1 = login_auth(inner2)
# @time_record  # inner2 = time_record(download_movie)
# def download_movie():
#     print(‘正在下载电影...‘)
#     time.sleep(2)
#     print(‘下载电影完成...‘)
#     return ‘GTWZ.mp4‘


# 执行顺序:
# 先执行login_auth, 再执行time_record
# 只统计下载电影的时间
# login()  # 先调用登录,模拟用户已登录
download_movie()

叠加装饰器模板

def wrapper1(func):
    def inner1(*args, **kwargs):
        print(1---start)
        # 被裝飾對象在調用時,如果還有其他裝飾器,會先執行其他裝飾器中的inner
        # inner2
        res = func(*args, **kwargs)
        print(1---end)
        return res
    return inner1


def wrapper2(func):
    def inner2(*args, **kwargs):
        print(2---start)

        res = func(*args, **kwargs)
        print(2---end)
        return res
    return inner2


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

‘‘‘
叠加裝飾器的裝飾順序與執行順序:
    - 裝飾順序: 调用wrapper装饰器拿到返回值inner
        由下往上裝飾
        
    - 執行順序: 调用装饰过后的返回值inner
        由上往下執行
‘‘‘


@wrapper1  # index《---inner1 = wrapper1(inner2)
@wrapper2  # inner2 = wrapper2(inner3)
@wrapper3  # inner3 = wrapper3(index)
def index():  # 被裝飾對象   # inner1 ---》
    print(from index...)


# 正在装饰
# inner3 = wrapper3(index)
# inner2 = wrapper2(inner3)
# inner1 = wrapper1(inner2)


‘‘‘
inner1()
inner2()
inner3()
index()
‘‘‘
index()  # 此处执行 # inner1() --> inner2() ---> inner3()

 

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

有参数装饰器:装饰被装饰对象时,有传参数的装饰器,如:wrapper(参数)

# 无参装饰器: 装饰在被装饰对象时,没有传参数的装饰器。
‘‘‘
# 以下是无参装饰器
@wrapper1  # inner1 = wrapper1(inner2)
@wrapper2  # inner2 = wrapper2(inner3)
@wrapper3
‘‘‘

# 有参装饰器: 在某些时候,我们需要给用户的权限进行分类
‘‘‘
# 以下是有参装饰器
@wrapper1(参数1)  # inner1 = wrapper1(inner2)
@wrapper2(参数2)  # inner2 = wrapper2(inner3)
@wrapper3(参数3)
‘‘‘


# 有参装饰器
def user_auth(user_role):  # ‘SVIP‘
    def wrapper(func):
        def inner(*args, **kwargs):
            if user_role == SVIP:
                print(超级用户)
                # 添加超级用户的功能
                res = func(*args, **kwargs)
                return res
            elif user_role == 普通用户:
                print(普通用户)
                # 添加普通用户的功能
                res = func(*args, **kwargs)
                return res

        return inner
    return wrapper


# 被装饰对象
# @user_auth(‘SVIP‘)
#wrapper = user_auth(‘普通用户‘)
#@wrapper
@user_auth(SVIP)  # wrapper = user_auth(‘普通用户‘)
# @wrapper  #<--- 返回结果(wrapper) <---- user_auth()
def index():
    pass
index()

wraps: 
是一个修复工具,修复的是被装饰对象的空间。
###from functools import wraps

‘‘‘
wraps: (了解)
    是一个修复工具,修复的是被装饰对象的空间。
    from functools import wraps

‘‘‘
from functools import wraps


def wrapper(func):

    @wraps(func)  # 修改名称空间: inner ---》 func
    def inner(*args, **kwargs):
        ‘‘‘
        此处是装饰器的注释
        :param func:
        :return:
        ‘‘‘
        res = func(*args, **kwargs)
        return res
    return inner  # ---》 func


@wrapper
def index():
    ‘‘‘
    此处是index函数的注释
    :return:
    ‘‘‘
    pass


print(index)  # 函数对象

# 函数对象.__doc__: 查看函数内部的注释
print(index.__doc__)  # inner.__doc__

二、迭代器

迭代器是迭代取值的工具

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

如果想要知道Python中迭代器是什么,必须先要知道什么是可迭代对象。

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

凡是内部有__iter__()f方法都是可迭代类型,如:list__iter__()

获取迭代器:

通过可迭代对象.__iter__()得到的返回值就是‘迭代器对象’

 

迭代器是迭代取值的工具,作用就是迭代取值

如何取值:

迭代器对象.__next__()   #每执行一次就会取出一个对象
list1 = [1, 2, 3, 4]
iter_list1 = list1.__iter__()   #返回迭代器对象
print(iter_list1.__next__())    #每执行一次就会取出一个对象
print(iter_list1.__next__())
print(iter_list1.__next__())
print(iter_list1.__next__())
print(iter_list1.__next__())   #当可迭代对象内部没有对象时再取就会报错

结果:
1
2
3
4
  File "/Users/tophan/python练习/day12/迭代器.py", line 7, in <module>
    print(iter_list1.__next__())
StopIteration

迭代器对象的优点:

1、不依赖索引迭代取值

2、节省空间

迭代器对象缺点:

1、取指定的某个值麻烦

2、每次取值都要从第一个值开始,无法通过索引取值。

#文件即是可迭代对象,也是迭代器对象,因为文件从读取出来就是迭代器对象

***可迭代对象不一定是迭代器对象

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

# x = 10
# while True:
#     print(x)

#
# list1 = [1, 2, 3, 4]  # 1, 2, 3, 4
# n = 0
# while n < len(list1):
#     print(list1[n])
#     n += 1


# 以下都是可迭代对象
‘‘‘
str1 = ‘hello tank!‘
str1.__iter__()
list1 = [1, 2, 3]  # list([1, 2, 3])
list1.__iter__()
set.__iter__()
dict.__iter__()
tuple.__iter__()
open(‘a.txt‘).__iter__()
‘‘‘


# str1 = ‘靓仔靓女‘

# iter_str1 = str1.__iter__()
# print(iter_str1)  # iterator指的是迭代器对象   # iter_str1 ---> 靓仔,靓女!
# print(iter_str1.__next__())
# print(iter_str1.__next__())
# print(iter_str1.__next__())
# print(iter_str1.__next__())

# 因为迭代器中的值已经取完了
# print(iter_str1.__next__())  # 报错,StopIteration


dict1 = {age: 17, name: tank}
iter_dict1 = dict1.__iter__()

print(iter_dict1.__next__())
print(iter_dict1.__next__())
# print(iter_dict1.__next__())

 补充:


不依赖索引的取值方式
tuple1 = (‘tank‘, ‘jason鸡哥‘, ‘sean‘, ‘饼哥‘)

# 获取迭代器对象: iter_list1
iter_tuple1 = tuple1.__iter__()

while True:
# 补充: try: 捕获异常
try:
print(iter_tuple1.__next__()) # 报错

# 立即触发此处代码 StopIteration
except StopIteration:
break

 

for 循坏内部原理:

for 循坏在工作时,首先会调用可迭代对象goods内置的_iter_方法拿到一个迭代器对象,
然后再调用该迭代器对象的__next__方法将取到的值赋给item,执行循坏体,周而复始,

直到捕捉到Stopliteration异常,结束迭代。

 

 

 

 

叠加装饰器与迭代器

标签:需要   day   open   strip()   普通用户   统计   rap   读取   pen   

原文地址:https://www.cnblogs.com/xy-han/p/11854004.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!