阅读目录
-
-
- 迭代器
- 生成器
- 推导式(生成式/解析式)
- 易错题/难题
迭代器
- 引入
dir([1,2].iter())是列表迭代器中实现的所有方法,
dir([1,2])是列表中实现的所有方法,
都是以列表的形式返回给我们的,为了看的更清楚,我们分别把他们转换成集合,
然后取差集。
print(set(dir([1,2].__iter__()))-set(dir([1,2])))
{
'__length_hint__', '__next__', '__setstate__'}
iter_l = [1,2,3,4,5,6].__iter__()
print(iter_l.__length_hint__())
print('*',iter_l.__setstate__(4))
print('**',iter_l.__next__())
print('***',iter_l.__next__())
-------
s = 123
for i in s:
print(i)
print(dir(str))
print(dir(list))
print(dir(int))
s = "周杰伦喜欢林俊杰"
it = s.__iter__()
print(dir(it))
1. 只能向前.
2. 几乎不占用内存, 节省内存(生成器)
3. for循环
4. 惰性机制 (面试题,难度系数比较高)
print(it.__next__())
print(it.__next__())
print(it.__next__())
print(it.__next__())
print(it.__next__())
print(it.__next__())
print(it.__next__())
print(it.__next__())
lst = ["周杰伦", "林俊杰", "汪峰", "姚明","潘长江"]
it=lst.__iter__()
while True:
try:
content=it.__next__()
print(content)
except StopIteration:
break
lst = ["肖战为什么这么帅","我不信","你们信吗?"]
it = lst.__iter__()
print("__iter__" in dir(it))
print("__next__" in dir(it))
可以通过dir来判断数据是否是可迭代的, 以及数据是否是迭代器
from collections import Iterable
from collections import Iterator
print(isinstance(lst, Iterable))
print(isinstance(lst, Iterator))
print(isinstance(it, Iterable))
print(isinstance(it, Iterator))
print('__next__' in dir(range(12)))
print('__iter__' in dir(range(12)))
from collections import Iterator
print(isinstance(range(100000000),Iterator))
lst = ["赵四","花生哥, 越来越皮", "天台见"]
it = lst.__iter__()
s = list(it)
print(s)
l=[1,2,3]
index=0
while index < len(l):
print(l[index])
index+=1
- 序列类型字符串,列表,元组都有下标,可以用上述的方式访问,
- 但非序列类型像字典,集合,文件对象无法使用;
for循环就是基于迭代器协议提供了一个统一的可以遍历所有对象的方法;
即在遍历之前,先调用对象的__iter__方法将其转换成一个迭代器;
然后使用迭代器协议去实现循环访问,这样所有的对象就都可以通过for循环来遍历了,
而且效果也确实如此,这就是无所不能的for循环。
生成器
def func():
print("娃哈哈")
yield 1
print("呵呵呵")
gen = func()
yield: 相当于return 可以返回数据. 但是yield不会彻底中断函数. 而是分段执行函数.
gen.__next__() 执行函数. 执行到下一个yield(找到下一个yield为止,等待下一次执行)
gen.__next__() 继续执行函数到下一个yield.
def order():
lst = []
for i in range(10000):
lst.append("衣服"+str(i))
return lst
li = order()
print(li)
def order():
for i in range(10000):
yield "衣服"+str(i)
g = order()
mingwei = g.__next__()
print(mingwei)
zhaoyining = g.__next__()
print(zhaoyining)
- send() 和__next__()是一样的;
send() 可以执行到下一个yield,也可以给上一个yield位置传值
def func():
print("我是第一个段")
a = yield 123
print(a)
print("周杰伦是第二段")
b = yield 456
print(b)
print("林俊杰是第三段")
c = yield 789
print(c)
print("李宗盛是最后一个段")
yield 79
g = func()
print(g.__next__())
print(g.send("煎饼果子"))
print(g.send("韭菜盒子"))
print(g.send("锅包肉"))
"""
我是第一个段
123
煎饼果子
周杰伦是第二段
456
韭菜盒子
林俊杰是第三段
789
锅包肉
李宗盛是最后一个段
79
"""
def eat():
print("我吃什么啊")
a = yield "馒头"
print("a=",a)
b = yield "鸡蛋灌饼"
print("b=",b)
c = yield "韭菜盒子"
print("c=",c)
yield "GAME OVER"
gen = eat()
ret1 = gen. __next__()
print(ret1)
ret2 = gen.send("胡辣汤")
print(ret2)
ret3 = gen.send("狗粮")
print(ret3)
ret4 = gen.send( "猫粮")
print(ret4)
>>>计算移动平均值(1)
def averager():
total = 0.0
count = 0
average = None
while True:
term = yield average
total += term
count += 1
average = total/count
g_avg = averager()
next(g_avg)
print(g_avg.send(10))
print(g_avg.send(30))
print(g_avg.send(5))
>>>计算移动平均值(2)_预激协程的装饰器
def init(func):
def inner(*args,**kwargs):
g = func(*args,**kwargs)
next(g)
return g
return inner
@init
def averager():
total = 0.0
count = 0
average = None
while True:
term = yield average
total += term
count += 1
average = total/count
g_avg = averager()
print(g_avg.send(10))
print(g_avg.send(30))
print(g_avg.send(5))
def func():
yield 1
yield 13
yield 26
yield 88
yield 46
yield 100
for i in func():
print(i)
'''
1
13
26
88
46
100
'''
print(list(func()))
def func():
print(111)
yield 222
a=func()
print(a)
print(list(a))
import time
def tail(filename):
f = open(filename)
f.seek(0, 2)
while True:
line = f.readline()
if not line:
time.sleep(0.1)
continue
yield line
tail_g = tail('tmp')
for line in tail_g:
print(line)
def gen1():
for c in 'AB':
yield c
for i in range(3):
yield i
print(list(gen1()))
def gen2():
yield from 'AB'
yield from range(3)
print(list(gen2()))
yield from
推导式(生成式/解析式)
lst = []
for i in range(1, 16):
lst.append("python"+str(i))
print(lst)
lst = ["python"+str(j) for j in range(1,16)]
print(lst)
lis=[i for i in range(10)if i%2==1]
print(lis)
>>>100以内能被3整除的数的平方
lst = [i*i for i in range(100) if i%3==0]
print(lst)
>>>寻找名字中带有两个e的人的名字
names = [['Tom', 'Billy', 'Jefferson' , 'Andrew' , 'Wesley' , 'Steven' ,'Joe'],
[ 'Alice', 'Jill' , 'Ana', 'Wendy', 'Jennifer', 'Sherry']]
lst=[name for el in names for name in el if name.count("e")>=2]
print(lst)
>>>给一个列表[11,22,33,44] 需要变成 字典{
0: 11, 1: 22, 2: 33, 3: 44}
li=[11,22,33,44]
dic={
}
for i in range(len(li)):
for j in range(len(li)):
if i==j:
dic[i]=li[i]
print(dic)
dic={
i:li[i] for i in range(len(li)) if i<2}
print(dic)
语法:{
k:v for循环 条件筛选}
>>>将字典的键值对调换顺序
dic = {
"jj": "林俊杰", "jay": "周杰伦", "zs": "赵四", "ln":"刘能"}
d(dic)={
v:k for k,v in dic.items()}
print(dic)
li=[1,1,2,3,3,5,6,6]
s={
el for el in li}
print(s)
tu = (i for i in range(10))
print(tu)
print(tu.__next__())
print(tu.__next__())
...
lst = [i for i in range(10)]
print(lst)
gen = (i for i in range(10))
延迟计算,一次返回一个结果。也就是说,它不会一次生成所有的结果,
这对于大数据量处理,将会非常有用。
sum([i for i in range(100000000)])
sum(i for i in range(100000000))
易错题/难题
def func():
print(111)
yield 222
g = func()
g1 = (i for i in g)
g2 = (i for i in g1)
print(list(g))
print(list(g1))
print(list(g2))
def func():
print(111)
yield 222
yield 333
g = func()
g1 = (i for i in g)
g3 = func()
g2 = (i for i in g3)
print(list(g))
print(list(g1))
print(list(g2))
def func():
print(111)
yield 222
yield 333
g = func()
g1 = (i for i in g)
g3 = func()
g2 = (i for i in g3)
print(g.__next__())
print(list(g1))
print(list(g2))
def add(a, b):
return a + b
def test():
for r_i in range(4):
yield r_i
g = test()
for n in [2, 10]:
g = (add(n, i) for i in g)
print(list(g))
————————
def add(a, b):
return a + b
def test():
for r_i in range(4):
yield r_i
g = test()
for n in [2, 10]:
g = (add(n, i) for i in g)
print(list(g))
n=2
g = (add(n, i) for i in g)
n=10
g = (add(n, i) for i in g)
g =(add(n, i) for i in (add(n, i) for i in g))
g =(add(10, i) for i in (add(10, i) for i in (0,1,2,3)))
print(list(g))
print(list(g))
def demo():
for i in range(4):
yield i
g=demo()
g1=(i for i in g)
g2=(i for i in g1)
print(list(g1))
print(list(g2))
- 协程应用:grep -rl /dir
tail&grep
import os
def init(func):
def wrapper(*args,**kwargs):
g=func(*args,**kwargs)
next(g)
return g
return wrapper
@init
def list_files(target):
while 1:
dir_to_search=yield
for top_dir,dir,files in os.walk(dir_to_search):
for file in files:
target.send(os.path.join(top_dir,file))
@init
def opener(target):
while 1:
file=yield
fn=open(file)
target.send((file,fn))
@init
def cat(target):
while 1:
file,fn=yield
for line in fn:
target.send((file,line))
@init
def grep(pattern,target):
while 1:
file,line=yield
if pattern in line:
target.send(file)
@init
def printer():
while 1:
file=yield
if file:
print(file)
g=list_files(opener(cat(grep('python',printer()))))
g.send('/test1')