12 装饰器与迭代器

1 什么是装饰器
装饰器就是装饰别人的工具,具体是指为被装饰者添加新功能


装饰器-》函数
被装饰者-》函数

2 为何要用装饰器
装饰器的核心思想:(开放封闭原则)
在不修改被装饰者源代码以及调用方式的前提下,为被装饰者添加新功能

3 如何实现装饰器
可以用闭包函数去实现装饰器
一、装饰器的实现
# 被装饰者
# import time
#
# def index():
#     print('welcome to index page')
#     time.sleep(3)
#
# index()

# 方案一:问题-》修改了被装饰者的源代码
# import time
#
# def index():
#     start = time.time()
#     print('welcome to index page')
#     time.sleep(3)
#     stop = time.time()
#     print(stop - start)
#
# index()


# 方案二:问题-》会造成代码冗余
# import time
#
# def index():
#     print('welcome to index page')
#     time.sleep(3)
#
# start = time.time()
# index()
# stop = time.time()
# print(stop -start)
#
# start = time.time()
# index()
# stop = time.time()
# print(stop -start)
#
# start = time.time()
# index()
# stop = time.time()
# print(stop -start)

# # 方案三:问题-》修改了被装饰对象的调用方式
# import time
#
# def index():
#     print('welcome to index page')
#     time.sleep(3)
#
# def wrapper(func):
#     start = time.time()
#     func()
#     stop = time.time()
#     print(stop -start)
#
# wrapper(index)


# # 方案四:我们用wrapper函数赋值给原函数名index,wrapper应该与原函数保持一致,但是现在的问题是不一致
# import time
#
# def index():
#     print('welcome to index page')
#     time.sleep(3)
#
# def outter(func):  # func = 最原始那个index函数的内存地址
#     def wrapper():
#         start = time.time()
#         func()
#         stop = time.time()
#         print(stop -start)
#     return wrapper
#
# index = outter(index)  # f=outter(最原始那个index函数的内存地址)
#                    # f=函数wrapper的内存地址
#
# # print(f)
#
# index()



# 方案四:让wrapper的参数与返回值与被装饰者保持一致
# import time
#
# def index(x,y,z):
#     print('welcome to index page',x,y)
#     time.sleep(3)
#     return 123
#
#
# def outter(func):  # func = 最原始那个index函数的内存地址
#     def wrapper(*args,**kwargs):
#         start = time.time()
#         res = func(*args,**kwargs)
#         stop = time.time()
#         print(stop -start)
#         return res
#     return wrapper
#
# index = outter(index)  # f=outter(最原始那个index函数的内存地址)
#                    # f=函数wrapper的内存地址
#
#
# res = index(111,222,333)  # res = wrapper(111,222,333)
# print(res)

二、装饰器语法糖

import time
from functools import wraps

def outter(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        start = time.time()
        res = func(*args, **kwargs)
        stop = time.time()
        print(stop - start)
        return res
    return wrapper


@outter  # index = outter(index)
def index(x, y, z):
    """index函数的文档注释"""
    print('welcome to index page', x, y)
    time.sleep(3)
    return 123


# res = index(111, 222, 333)
# print(res)

# print(index)
help(index)

三、装饰器的模板

# def outter(func):
#     def wrapper(*args,**kwargs):
#         res = func(*args,**kwargs)
#         return res
#     return wrapper

案例:

案例1
#
def sayhi(func): # def wrapper(*args,**kwargs): # print('hello') # res = func(*args,**kwargs) # return res # return wrapper 案例2 # def auth(func): # def wrapper(*args,**kwargs): # u = input('username>>>: ').strip() # p = input("password>>>: ").strip() # if u == 'egon' and p == '123': # res = func(*args,**kwargs) # return res # else: # print("认证失败") # return wrapper # # @auth # def index(): # print('index=========>') # # index()

四、迭代器

1.迭代器指的是迭代取值的工具
什么是迭代???
迭代是一个重复的过程,但是每一次重复都是基于上一次结果而继续的
 # names = ['egon','tom','lili','jack','xxx']
    # msg = "hello world"

    dic = {'k1':111,'k2':2222,'k3':33333}

    def foo(xxx):
        i = 0
        while i < len(xxx):
            print(xxx[i])
            i += 1

    # foo(names)
    # foo(msg)
    foo(dic)

2.为何要用迭代器

 

  1 为了找到一种统一迭代取值方案(适用于strlisttupledictset,文件对象)
2 节省内存
3.如何用迭代器
可迭代的对象iterable
内置有__iter__方法的对象(strlisttupledictset,文件对象)
迭代器对象iterator:
内置有__iter__方法
内置有__next__方法
# "abc".__iter__()
# [1,23].__iter__()
# (1,2,3).__iter__()
# {'k1':111}.__iter__()
# {1,2,3}.__iter__()
# f = open('a.txt',mode='wt')
# f.__iter__()


# print(len("abc"))  # "abc".__len__()

# dic = {'k1':1111,'k2':2222,'k3':3333}
# iter_dic = dic.__iter__()  # iter_dic=iter(dic)
#
# # print(iter_dic)
# print(iter_dic.__next__())  # print(next(iter_dic))
# print(iter_dic.__next__())
# print(iter_dic.__next__())
# # print(iter_dic.__next__())  # 报错
#
# new_iter = dic.__iter__()
# print(new_iter.__next__())


# msg = "hello world"
# iter_msg = msg.__iter__()
#
# print(iter_msg.__next__())
# print(iter_msg.__next__())
# print(iter_msg.__next__())
# print(iter_msg.__next__())


dic = {'k1': 1111, 'k2': 2222, 'k3': 3333,'k4':4444,'k5':5555}

# iter_dic = iter(dic)
# iter_dic.__next__()
# print(iter_dic.__iter__().__iter__().__iter__() is iter_dic)

# while True:
#     try:
#         print(next(iter_dic))
#     except StopIteration:
#         break

# for x in dic:
#     print(x)




# 例1:
# dic = {'k1': 1111, 'k2': 2222, 'k3': 3333,'k4':4444,'k5':5555}
#
# iter_dic = iter(dic)
# for k in iter_dic:
#     print(k)
# print('='*50)
# # iter_dic = iter(dic)
# for k in iter_dic:
#     print(k)

# 例2
# with open('a.txt',mode='rt',encoding='utf-8') as f:
#     for line in f:
#         print(line)
#     print('='*50)
#     for line in f:
#         print(line)


l = [1,2,3,4,5,6,7,8,9]
iter_l=iter(l)

4.自定义迭代器

yield可以返回多次值
def func():
    print('hello1')
    print('hello1')
    print('hello1')
    yield 111
    print('hello2')
    print('hello2')
    print('hello2')
    yield 222
    print('hello3')
    print('hello3')
    print('hello3')
    print('hello3')
    yield 333
    print('hello4')
    print('hello4')
    print('hello4')
    print('hello4')

函数内但凡出现yield语法,我们再调用函数就不会立即触发函数体代码运行,会返回一个生成器对象,生成器对象就是一种自定义的迭代器

g = func()
# print(g)
# g.__iter__()
# g.__next__()

res=next(g)
print(res)

res=next(g)
print(res)

res=next(g)
print(res)

next(g)

 叠加多个装饰器

 

def deco1(func1):  # func1=函数wrapper2的内存地址
    def wrapper1(*args,**kwargs):
        print('=========>wrapper1')
        res1 = func1(*args,**kwargs)
        return res1
    return wrapper1

def deco2(func2):  # func2=函数wrapper3的内存地址
    def wrapper2(*args,**kwargs):
        print('=========>wrapper2')
        res2 = func2(*args,**kwargs)
        return res2
    return wrapper2

def deco3(func3):  # func3 = 最原始那个index函数的内存地址
    def wrapper3(*args,**kwargs):
        print('=========>wrapper3')
        res3 = func3(*args,**kwargs)
        return res3
    return wrapper3

        # index=函数wrapper1的内存地址

@deco1  # deco1(函数wrapper2的内存地址)->函数wrapper1的内存地址
@deco2  # deco2(函数wrapper3的内存地址)->函数wrapper2的内存地址
@deco3  # deco3(最原始那个index函数的内存地址)->函数wrapper3的内存地址
def index():
    print('=------------>index')
    return 123

res = index()
print(res)
# print(index)

迭代器实现range功能
#
def my_range(start, stop, step): # while start < stop: # 5 < 5 # yield start # 3 # start += step # start = 5 # # # g = my_range(1,5,2)

 

 五、for循环的工作原理:

基于for循环,我们完全可以不在依赖于索引取值了
dic={"a":1,"b":2,"c":3}
for k in dic:
    print(dic[k])

for循环的工作原理:

1.执行in后对象的dic._inter_()方法,得到一个迭代器对象inter_dic

2.执行next(iter_dic),将得到的值赋值给k,然后执行循环体代码

3.重复过程2,知道捕捉到异常StopIteration,结束循环


复制代码

 

 

 

 
 

 

 

 

 
posted @ 2021-08-10 22:26  甜甜de微笑  阅读(54)  评论(0编辑  收藏  举报