一,迭代器
可迭代对象:通俗理解,可以被for的对象。实际上,python协议中有:具有__iter__方法的就是可迭代对象
obj.__iter__(),内置容器被请求迭代时,会调用这个方法。
返回一个能够迭代容器内所有对象的迭代器,obj为字典时,只迭代键。
iterator.__next__()
返回容器的下一个元素
a = obj.__iter__() # 创建一个迭代器 a.__next__() # 一个一个取
具有__iter__和__next__的就是一个迭代器
迭代器特性:
惰性机制
不能逆行
一次性,用完即弃
ps.列表的查询速度比字典快
lis = [1, 2, 3, 4, 5] a = lis.__iter__() try: a.__next__() except StopIteration: break
二,生成器: 顾名思义,生成器就是能够被迭代的,返回一定规格的数据的
特殊函数。
优点:非常节省内存,读取大批量数据时要想到生成器,
生成器一定是迭代器,迭代器不一定是生成器,是可以让程序员自己制作的迭代器
1.生成器的本质是迭代器,生成器是一个返回迭代器的函数,只能用于迭代操作
2.使用了 yield 的函数被称为生成器(generator),能用__iter__()方法
yield是一种特殊的return
def func(): print(1) a = yield 'a' # 功能:1.挂起 2.next的返回值 3.接收send的值,没有send的话,默认a=None print(2) b = yield 'b' g = func() # 这里,把生成器func的地址给了变量g,打印g会得到内存地址 print(g.__next__()) generator.send() # 用于向yield传递值,赋值给上面line3的a # send执行过程包括一次传值和一个next方法,迭代到哪里,就会send到哪里 # 如果生成器还没有执行过next,send参数就只能接收None,因为send先传值,再next # 在没执行过next时,还没有在yield挂起,也就无法send给任何人,传None之外的 # 东西就会报错 print(g.__next__())
在调用生成器运行的过程中,next()每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。
def func(): li = [1, 2, 3] yield from li g = func() print(g.__next__()) # 打印1 # yield from 将可迭代对象逐个返回
三,装饰器
开放封闭原则
对扩展开放
对修改源代码封闭
作用:为已经存在的对象添加额外的功能
ps.像一个装饰打包机器,把送进来的对象以一定规格装饰后再打包送出去。即为对象添加特定功能的代码后,再送出去。
应用场景:插入日志、性能测试、事务处理、权限校验
def func(): print('这是原函数。') def wrapper(f): def inner(): pass # 新功能 f() return inner # 返回inner的函数指针 func = wrapper(func) # 现在func这个名字指向inner了 func() # 执行line5-6 @wrapper # 语法糖,相当于func1 = wrapper(func1) def func1(): pass
本质是闭包
外层用于把目标函数(函数名)带进来,即传参,并把完成工作后的内层函数(函数名)返回出去;
内层用于装饰目标函数。
经过装饰器修饰之后,目标函数的内存地址就变成了那个内层函数。虽然看起来函数名还是以前的那个,但内在已经变了。
为了不破坏原函数的逻辑,我们要保证内层函数wrapper和被装饰函数func的传入参数和返回值类型必须保持一致。
函数装饰器 @decorator
@wrapper # 语法糖,相当于func1 = wrapper(func1) def func1(): pass func1() # 此时,func1已经被wrapper装饰过了
装饰器链
用@进行装饰的顺序:从近到远
def decorator2(f): def new(): print(2) return '装饰两次'+f() return new def decorator1(f): def new(): print(1) return '装饰一次'+f() return new @decorator1 @decorator2 def func(): return "原函数" print(func()) # 输出: # 1 # 2 # 装饰一次装饰两次原函数 # line11-12等价于以下两行代码 func = decorator2(func) func = decorator1(func)
类方法的函数装饰器
import time def decorator(func): def wrapper(me_instance): start_time = time.time() func(me_instance) end_time = time.time() print(end_time - start_time) return wrapper class Method(object): @decorator def func(self): time.sleep(0.8) p1 = Method() p1.func() # 函数调用
对于类方法来说,都会有一个默认的参数self,它实际表示的是类的一个实例,所以在装饰器的内部函数wrapper也要传入一个参数me_instance就表示将类的实例p1传给wrapper,其他的用法都和函数装饰器相同。
from functools import wraps def decorator(func): @wraps(func) # 用于查看原函数的注释