装饰器迭代器

今日内容:函数部分
    无参装饰器:嵌套两层的闭包函数
    有参装饰器:嵌套三层的闭包函数(***)

    装饰器的语法糖

    叠加多个装饰器的加载顺序与执行顺序

    函数部分
        迭代器


**储备知识1**
代码演示,把接收的参数格式原封不动的转交给其内部的函数

def index(x,y):
    print(x,y)

def wrapper(*args,**kwargs):
    index(*args,**kwargs)  # index(1,2,z=3)

wrapper(1,2,z=3)

**储备知识2**
嵌套调用和嵌套定义

def outter():
    def wrapper():
        pass

**储备知识3:**
结论1:L-》E-》G-》B
结论2:名称空间的嵌套关系是在函数定义阶段扫描语法时生成的

**储备知识4:闭包函数**

def outter(x):
    def wrapper():
        print(x)
    return wrapper

f=outter(222)  # f=函数wrapper的内存地址
f()

**储备知识5:为函数体传参的两种方案

方案一:**
def wrapper(x):
    print(x)

wrapper(111)
wrapper(222)

**方案二:**
def outter(x):
    def wrapper():
        print(x)
    return wrapper

f = outter(111)  #f = 函数wrapper的内存地址
f()

f = outter(222)  #f = 函数wrapper的内存地址
f()
"""
**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

**举例使用**

def sayhi(func):
    def wrapper(*args,**kwargs):
        print('hello')
        res = func(*args,**kwargs)
        return res
    return wrapper

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 为了找到一种统一迭代取值方案(适用于str、list、tuple、dict、set,文件对象)
    2 节省内存

**3 如何用迭代器**

    可迭代的对象iterable:
        内置有__iter__方法的对象(str、list、tuple、dict、set,文件对象)
    迭代器对象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)
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)
posted @ 2021-08-10 17:06  停在夏季  阅读(26)  评论(0编辑  收藏  举报
-->