python生成器和迭代器
2021-12-01 本文已影响0人
Cache_wood
@[toc]
观察者模式
亦称
– 发布(publish )-订阅(Subscribe)模式
– 模型-视图(View)模式
– 源-收听者(Listener)模式
– 从属者模式
要义
– 一个目标对象管理所有依赖于它的观察者对象,并且在它本身的状态改变时主动发出通知
– 观察者模式完美地将观察者和被观察的对象分离
- 优点
– 观察者与被观察者之间抽象耦合
– 可以触发多个符合单一职责的模块
– 可以很方便地实现广播 - 场景
– 消息交换,如消息队列;
– 多级触发,如一个中断即会引发一连串反应 - 缺点
– 效率不一定高
import time
class Investor:
def __init__(self,name,stock):
self._name=name
self._stock=stock
@property
def stock(self):
return self._stock
@stock.setter
def stock(self,value):
self._stock=value
def update(self):
print("{} invest on {} with price {}: sell it now!!!".format(self._name,self._stock.name,self._stock.price))
class Stock:
def __init__(self,name,price):
self._name=name
self._price=price
self._investors=[]
@property
def name(self):
return self._name
@property
def price(self):
return self._price
@price.setter
def price(self,value):
if self._price>value:
self.notify()
self._price=value
def attach(self,investor):
self._investors.append(investor)
def notify(self):
for investor in self._investors:
investor.update()
def main():
s=Stock('区块链',11.11)
i1=Investor('zjc',s)
i2=Investor('lys',s)
s.attach(i1)
s.attach(i2)
s.price=13
time.sleep(1)
s.price=10
if __name__=='__main__':main()
zjc invest on 区块链 with price 13: sell it now!!!
lys invest on 区块链 with price 13: sell it now!!!
迭代
- 通过
for … in
等遍历数据结构如tuple,list,dict
字符串等 - 判断一个对象是否可迭代
from collections import Iterable
isinstance([1,2,3],Iterable)
- 同时迭代序号和元素
for i,value in enumerate(['A','B','C']):
pass
生成器
- 通过列表推导式构建生成器
L = [x*x for x in range(10)] #列表
G = (x*x for x in range(10)) #生成器
-
通过
next()
函数获得generator
的下一个返回值 -
通过
for … in
进行遍历 -
通过定义函数构建生成器
- 函数定义需要包含
yield
关键字 - 在执行中遇到
yield
会中断,下次继续执行
暂停并保存当前所有运行信息,返回yield
的值,并在下一次执行next()
方法时从当前位置继续运行
- 函数定义需要包含
-
获取返回值需要捕获
StopIteration
异常 -
注意区分普通函数和
generator
函数 -
普通函数调用直接返回结果
-
generator
函数的调用实际返回一个generator
对象
def fib(max):
n,a,b=0,0,1
while(n<max):
yield b
a,b=b,a+b
n+=1
return 'done'
print(fib(6))
<generator object fib at 0x000001E77234AB30>
#生成器不会直接直接打印出值,只会一个个加载
for f in fib(6):
print(f)
1
1
2
3
5
8
#循环打印出值,但是不会出'done'
f=fib(6)
while True:
try:
print(next(f))
except StopIteration as si:
print(si.value)
break
1
2
3
5
8
done #这种方法可以打印出'done'
from collections import Iterable
#flatten函数用来展平
def flatten(items,ingore_types=(str,bytes)):
for x in items:
if isinstance(x,Iterable) and not isinstance(x,ingore_types):
yield from flatten(x,ingore_types)
else:
yield x
items=[1,2,[3,4,5],[6,7],[[[8]]],9,10]
finput=list(flatten(items)) #转化为列表
print(finput)
#for x in flatten(items):
# print(x)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
迭代器
- 可以被
next()
函数调用并不断返回下一个值的对象称为迭代器 - 迭代器可以记住遍历位置
- 迭代器只能往前不能后退(“消耗”数据)
- 可以使用
isinstance()
判断一个对象是否是Iterator
对象
isinstance((x for x in range(10)),Iterator)
- 生成器都是迭代器,但是
list,dict,str
虽然是Iterable
,却不是Iterator
- 把
list,dict,str
等Iterable
变成Iterator可以使用iter()
函数 -
Iterator
对象表示一个数据流
被next()
函数调用并不断返回下一个数据在,直到没有数据抛出StopIteration
错误
可将该数据流看作是长度未知的有序序列,只能不断通过next()
函数实现按需计算下一个数据
可表示无限大数据流,例如全体自然数,而使用list
等不可能存储全体自然数
创建迭代器
-
iter()
函数 - 把一个类作为一个迭代器使用需要在类中实现两个方法
__iter__()
与__next__()
-
__iter__()
返回一个特殊的迭代器对象,这个对象实现了__next__()
方法 -
__next__()
方法返回下一个元素并通过StopIteration
异常标识迭代的完成
from typing import Iterator
class Numbers:
def __init__(self,start=1,step=1,max=100):
self._start=start
self._step=step
self._max=max
self._a=self._start
#self._list=[]
def __iter__(self):
return self
#return iter(self._list)
def __next__(self):
if self._a <= self._max:
x = self._a
self._a += self._step
return x
else:
raise StopIteration('大于max:{}'.format(self._max))
num=Numbers(start=2,step=2,max=100)
myiter=iter(num)
for i in range(10):
print(next(myiter))
2
4
6
8
10
12
14
16
18
20