Python基础(8)- 关键字yield

浏览: 1391

前几天遇到了这个yield,不知道是干嘛的,这里学习整理下,主要参考了:

如何理解Python关键字yield

Python高级特性

上面介绍的都很好,这里就根据自己的理解,简单整理下。

1. 什么是迭代

    常见的list、tuple等集合,我们会通过遍历,比如for循环来获取每一个元素,这就是迭代。这些可以遍历的对象,也叫做可迭代对象

小例子

a = [1,2,3]
print(a)
for i in a:
print(i)

b = 'abcd'
print(b)
for i in b:
print(i)

c = {'name':'lufei','age':20}
print(c)
for k in c:
print(k)
for v in c.values():
print(v)
for k,v in c.items():
print(k,v)

#out
[1, 2, 3]
1
2
3
abcd
a
b
c
d
{'name': 'lufei', 'age': 20}
name
age
lufei
20
name lufei
age 20

我们怎样判断一个对象是否可以去迭代呢?可以使用collections模块的Iterable

print(type(a),isinstance(a,Iterable))
print(type(b),isinstance(b,Iterable))
print(type(c),isinstance(c,Iterable))
print(type(123),isinstance(123,Iterable))

#out
<class 'list'> True
<class 'str'> True
<class 'dict'> True
<class 'int'> False

2. 列表生成式(List Comprehensions)

  一个非常简单的方式来生成list,像这样:

range(10)
Out[56]: range(0, 10)

list(range(10))
Out[57]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

list(x for x in range(10))
Out[58]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

list(x*x for x in range(10))
Out[59]: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

[x*x for x in range(3)]
Out[60]: [0, 1, 4]

#上面的for后面还可以加上if判断
[x for x in range(10) if x>5]
Out[61]: [6, 7, 8, 9]

#for循环也可以嵌套
[x+y for x in 'abc' for y in 'xyz']
Out[62]: ['ax', 'ay', 'az', 'bx', 'by', 'bz', 'cx', 'cy', 'cz']

3.迭代器

  前面,我们说了for循环和可迭代对象,像这种可以使用for循环不断取出先一个元素的对象,就叫做迭代器(Iterator)。迭代器不单单可以使用for循环来遍历,

还可以使用next()函数不断获取下一个元素,当没有下一个元素时,会抛出StopIteration异常。

我们可以使用collections模块的Iterator来判断一个对象是否为迭代器

from collections import Iterator

isinstance([1,2,3],Iterator)
Out[2]: False

isinstance('abc',Iterator)
Out[3]: False

isinstance({'name':'lufei','age':20},Iterator)
Out[4]: False

创建一个迭代器有3中方式:

  1. 为对象创建 __iter__()和__next__()方法
  2. 内置的iter()可以将可迭代对象转换为迭代器
  3. 生成器
a = [1,2,3]

type(iter(a))
Out[6]: list_iterator

isinstance(iter(a),Iterator)
Out[7]: True

4. 生成器

  上面,我们使用list()或者[],很简单方便的生成了一个列表,只要我们将[]替换为(),就创建一个一个generator。生成器可以一边循环,一边计算生成下一个元素,而不是像list一样,一下生成所有的数据。

(x+y for x in 'abc' for y in 'xyz')
Out[63]: <generator object <genexpr> at 0x0000021AE0FC9D58>

a = (x+y for x in 'abc' for y in 'xyz')

a
Out[66]: <generator object <genexpr> at 0x0000021AE0FC9518>

isinstance(a,Iterator)
Out[67]: True

通常,我们使用yield语句可以返回一个生成器,很多例子,这里都是举一个斐波那契数列

yield类似return,只不过他返回的是生成器,调用了next()之后,

def fab(n):
a,b,i = 0,1,0
while i<n:
print(b)
a,b = b,a+b
i+=1

fab(5)

#out
1
1
2
3
5

#使用yield改造
def fab(n):
a,b,i = 0,1,0
while i<n:
yield b
a,b = b,a+b
i+=1

for i in fab(5):
print(i)

我们调用fab的时候,执行到yield,会返回一个生成器,当调用next()后,程序会回到yield停止的地方继续往下执行

这样,就是每次只生成当前元素,而不是一下子生成所有的元素;

当然,for循环替我们调用了next(),并处理了StopIteration异常。

好了,梳理好上面这些概念,到yield这里,其实还好,平时在理解下,多用用,好,就到这。

推荐 0
本文由 liutangwow 创作,采用 知识共享署名-相同方式共享 3.0 中国大陆许可协议 进行许可。
转载、引用前需联系作者,并署名作者且注明文章出处。
本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责。本站是一个个人学习交流的平台,并不用于任何商业目的,如果有任何问题,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

0 个评论

要回复文章请先登录注册