Python——生成器、列表生成式、迭代器

Python列表生成式

列表推导式的一般语法

 

[express for item1 in iterable1 if condition1
for item2 in iterable2 if condition2
....
for itemn in iterablen if conditionn
]

这种语法等价于以下代码

 

s = []
for item1 in iterable1:
      if condition1:
          for item2 in iterable2:
              if condition2:
                ....
                for itemN in iterableN:
                    if conditionN:
                        expression

下面举一些列表推导式的栗子:

 

a = [1,3,5,7,9,10]
b = ['a','b','c','d','e']

# a列表中所有项*2
c = [2*s for s in a]
print(c)
# 带有条件的列表推导式
d = [s for s in a if s>=5]
print(d)

# 多item
e = [(x,y) for x in a for y in b if x > 0]
print(e)

  • Python中生成列表可以使用如下的表达式:

 

a = [x for x in range(10)]
# 0,1,2,3,4,5,6,7,8,9
  • 元组或列表赋值

 

t = ('128',222)
a,b = t
这里a,b将被赋值为t的两个元素
等价于 a = t[0] b =t[1]
print(a)
print(b)
# 128 222

生成器

通过列表生成式,我们可以直接创建一个列表,但是受到内存的限制,列表的容量是有限的。而且我们创建的数据过于庞大会占用很大的内存空间。所以,如果列表元素可以按照某种算法推算出来,我们就可以在循环的过程中不断推算后续的元素。这样就不必创建列表。从而节省了大量的空间。在Python中,我们称这种一边循环一边计算的机制,称为生成器 generator,生成器用来创建Python序列的一个对象。它可以迭代庞大的序列,且不需要在内存中创建和存储整个序列。任何使用yield的函数都称为生成器

生成器的创建

通过列表生成式创建

要创建一个generator,我们可以把列表生成式的[]改成一个()这样就创建了一个generator
生成器表达式是一个对象,它执行的计算与列表推导相同,但会迭代地生成结果。它的语法也与列表推导式相同,但要用圆括号代替方括号

  • 生成器表达式的语法

 

(expression for item1 in iterable1 if condition1 
for item2 in iterable2 if condition2
...
for itemN in iterableN if conditionN
)

生成器表达式和列表推导式不同,生成器表达式实际上不创建列表或者立即对圆括号内的表达式求值。相反,它会创建一个生成器对象,该对象通过迭代并按照需要生成的值,看个栗子

 

a = [1, 2, 3, 4]
b = (10 * i for i in a)
print(type(b))
print(b.__next__())
print(next(b))
>>>
<class 'generator'>
10
20

**使用生成器表达式和列表推导式可以极大地提高性能和n

 

L   = [x * x for x in range(10)]
L
g = (x*x for x in range(10))
g
# <generator object <genexpr> at 0x1022ef630>

这里L是一个list g是一个generator

使用yield

生成器本质上其实是一个函数,函数就会有返回值,我们在函数中使用yield

 

def gerator():
    print('ok')
    yield 1
    print('next')
    yield 2

g = gerator()
print(g)
print(next(g))
print(next(g))
######
<generator object gerator at 0x102210fc0>
ok
1
next
2

如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator

generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句后返回。再次执行时从上次返回的yield语句处继续执行

我们这样定义函数后,直接执行这个函数不会被内部执行了,这个函数就会成为一个生成器对象
上面的生成器函数中,我们执行完第一个next中,程序会执行第一个yield的值,然后会记录执行位置,再执行第二个next时从上一次记录的位置继续执行,执行中遇到return,会认为函数的结束,那么生成器也会结束。

读取生成器的元素 next()

要生成的值并不在生成器中,而需要我们一个一个的去生成,可以通过next()函数获得生成器generator()的下一个返回值:

 

>>> next(g)

generator保存的是算法,所以每次调用next(g),就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误
但是我们在使用generator后,基本上永远不会调用next(),而是通过for循环来迭代,并且不需要关心stopIteration的错误.for循环要求作用的对象是迭代对象,生成器就是一个迭代对象。所以可以直接使用for循环来取生成器的值

 

for i in g:
    print(i)

会在内部调用生成器的next()方法

执行迭代器的函数 send(p)

生成器也是函数,可以使用send(p)执行生成器函数并传递一个函数,这个函数会传递到yield的对象中。

  • 第一次使用send进入函数时只能传递一个None值,也就是说第一次send前如果没有next只能发送None数据

b.send(None)

 

def bar():
    print('before yield')
    count = yield 123
    print(count)
    yield 234
b = bar()

b.send(None)
b.send('abc')

Python 迭代器

在Python中,可以直接作用于for循环的数据类型可以分为:
1.集合数据类型 list、tuple、dict、set、str等
2.生成器generator 包括生成器和带yield的生成器函数
这些可以作用于for循环的对象统称为可迭代对象:Iterable
在Python中可以使用isinstance()判断一个对象是否是Iterable对象

 

from collections import Iterable

print(isinstance([], Iterable))
print(isinstance({}, Iterable))
print(isinstance((), Iterable))
print(isinstance('123', Iterable))
print(isinstance(100,Iterable))
#True
True
True
True
False
  • 判断是否是迭代器
    我们可以使用isinstance()判断一个对象是否是迭代器Iterator对象

 

from collections import Iterator

print(isinstance([], Iterator))
print(isinstance((), Iterator))
print(isinstance({}, Iterator))
print(isinstance('1111',Iterator))

我们可以看出list dict str tuple等数据类型虽然是Iterable,却不是Iterator,So
迭代器一定是可迭代对象,可迭代对象不一定是迭代器
那么为什么Python中 list dict str等数据类型不是Iterator?

因为Python中的Iterator对象表示的是一个数据流,而Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。这个数据流可以看做是一个有序序列。但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的的计算是惰性的,只有在需要返回下一给数据时才会计算
而Iterator可以表示一个无限大的数据流。
迭代器满足的条件:
1有iter方法
2有next方法

  • 可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator
  • 对于for循环,在内部所完成的三件事:
    1 调用可迭代对象的iter方法返回一个迭代器对象
    2 不断调用迭代器对象的next方法
    3 捕获StopIterator异常

for循环内部图解



链接:https://www.jianshu.com/p/3c6b652aa44a

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值