python3生成器_Python3 迭代器和生成器

想要搞明白什么是迭代器,首先要了解几个名词:容器(container)、迭代(iteration)、可迭代对象(iterable)、迭代器(iterator)、生成器(generator)。

看图是不是更清楚点呢......

一 容器(container)

容器是一种把多个元素组织在一起的数据结构,容器中的元素可以逐个地迭代获取,可以用in, not in关键字判断元素是否包含在容器中。通常这类数据结构把所有的元素存储在内存中(也有一些特例,并不是所有的元素都放在内存,比如迭代器和生成器对象)在Python中,常见的容器对象有:

list, deque, ….

set, frozensets, ….

dict, defaultdict, OrderedDict, Counter, ….

tuple, namedtuple, …

str

容器比较容易理解,因为你就可以把它看作是一个盒子、一栋房子、一个柜子,里面可以塞任何东西。从技术角度来说,当它可以用来询问某个元素是否包含在其中时,那么这个对象就可以认为是一个容器,比如 list,set,tuples都是容器对象。

print( 1 in [1, 2, 3]) # lists

# True

print(4 not in [1, 2, 3])

# True

print(1 in {1, 2, 3}) # sets

# True

print(4 not in {1, 2, 3})

# True

print(1 in (1, 2, 3)) # tuples

# True

print(4 not in (1, 2, 3))

# True

# 询问某元素是否在dict中用dict的中key:

d = {1: 'foo', 2: 'bar', 3: 'qux'}

print(1 in d)

# True

print('foo' not in d) # 'foo' 不是dict中的元素

# True

# 询问某substring是否在string中:

s = 'foobar'

print('b' in s)

# True

print('x' not in s)

# True

print('foo' in s)

# True

尽管绝大多数容器都提供了某种方式来获取其中的每一个元素,但这并不是容器本身提供的能力,而是可迭代对象赋予了容器这种能力,当然并不是所有的容器都是可迭代的,比如:

二 迭代(iteration)

什么是迭代,我的理解如下:

第一,迭代需要重复进行某一操作

第二,本次迭代的要依赖上一次的结果继续往下做,如果中途有任何停顿,都不能算是迭代

下面来看几个例子,能更好理解迭代的含义。

# 实例1

# 非迭代

count = 0

while count < 10:

print("hello world")

count += 1

# 实例2

# 迭代

count = 0

while count < 10:

print(count)

count += 1

实例1,仅仅只是在重复一件事,那就是不停的打印"hello world",并且,这个打印的结果并不依赖上一次输出的值。而实例2,就很好地说明迭代的含义,重复+继续。

三 可迭代对象 (iterable)

通俗的说就是在每一种数据类型对象中,都会有有一个__iter__()方法,正是因为这个方法,才使得这些基本数据类型变为可迭代。

当我们运行以下代码的时候:

x = [1,2,3]

for elem in x:

print(elem)

# 运行结果:

# 1

# 2

# 3

实际调用过程如下:

那么如何判断一个对象是否是可迭代呢?使用collections模块的Iterable类型判断

from collections import Iterable

print(isinstance('abc', Iterable)) # str是否可迭代

# True

print(isinstance([1,2,3], Iterable)) # list是否可迭代

# True

print(isinstance(123, Iterable)) # 整数是否可迭代

# False

四 迭代器(iterator)

通俗来讲任何具有__next__()方法的对象都是迭代器,对迭代器调用__next__()方法可以获取下一个值。

五 生成器(generator)

生成器是一个用简单的方式来完成迭代。简单来说,Python的生成器是一个返回可以迭代对象的函数。

那要怎么创建生成器呢,很简单的,在一般函数中使用yield关键字,可以实现一个最简单的生成器,此时这个函数变成一个生成器函数。yield与return返回相同的值,区别在于return返回后,函数状态终止,而yield会保存当前函数的执行状态,在返回后,函数又回到之前保存的状态继续执行。

看一下简单的生成器实例吧:

def test():

yield 1

yield 2

yield 3

g=test()

print('来自函数',g)

print(g.__next__())

print(g.__next__())

# 运行结果

# 来自函数

# 1

# 2

生成器与一般函数有什么区别呢?

生成器函数包含一个或者多个yield

当调用生成器函数时,函数将返回一个对象,但是不会立刻向下执行

像__iter__()和__next__()方法等是自动实现的,所以我们可以通过next()方法对对象进行迭代

一旦函数被yield,函数会暂停,控制权返回调用者

局部变量和它们的状态会被保存,直到下一次调用

函数终止的时候,StopIteraion会被自动抛出

来个例子看一下吧:

# 简单的生成器函数

def my_gen():

n=1

print("first")

# yield区域

yield n

n+=1

print("second")

yield n

n+=1

print("third")

yield n

a=my_gen()

print("next method:")

# 每次调用a的时候,函数都从之前保存的状态执行

print

print(next(a))(next(a))

print(next(a))

# 运行结果

# next method:

# first

# 1

# second

# 2

# third

# 3

print("for loop:")

# 与调用next等价的

b=my_gen()

for elem in my_gen():

print(elem)

# 运行结果

# for loop:

# first

# 1

# second

# 2

# third

# 3

来看看使用循环的生成器

# 逆序yield出对象的元素

def rev_str(my_str):

length=len(my_str)

for i in range(length-1,-1,-1):

yield my_str[i]

for char in rev_str("hello"):

print(char)

# 运行结果

# o

# l

# l

# e

# h

六 生成器表达式

Python中,有一个列表生成方法,也就是常说的列表解析,提到列表解析就先要弄明白三元表达式的概念,什么是三元表达式呢?来个实例看看吧

egg_list=[]

for i in range(10):

egg_list.append('鸡蛋%s' %i)

print(egg_list)

# ['鸡蛋0', '鸡蛋1', '鸡蛋2', '鸡蛋3', '鸡蛋4', '鸡蛋5', '鸡蛋6', '鸡蛋7', '鸡蛋8', '鸡蛋9']

# 使用三元表达式替换如上代码

l=['鸡蛋%s' %i for i in range(10)]

print(l)

# ['鸡蛋0', '鸡蛋1', '鸡蛋2', '鸡蛋3', '鸡蛋4', '鸡蛋5', '鸡蛋6', '鸡蛋7', '鸡蛋8', '鸡蛋9']

l1=['鸡蛋%s' %i for i in range(10) if i > 5 ]

print(l1)

# ['鸡蛋6', '鸡蛋7', '鸡蛋8', '鸡蛋9']

# l2=['鸡蛋%s' %i for i in range(10) if i > 5 else i] #没有四元表达式

# print(l2)

l3=['鸡蛋%s' %i for i in range(10) if i < 5]

print(l3)

# ['鸡蛋0', '鸡蛋1', '鸡蛋2', '鸡蛋3', '鸡蛋4']

了解了三元表达式,我们再来看看什么是生成器表达式,其实很简单,就是把三元表达式中的[]换成()即可。

a=(x for x in range(10))

b=[x for x in range(10)]

# 这是错误的,因为生成器不能直接给出长度

# print("length a:",len(a))

# 输出列表的长度

print("length b:",len(b))

# length b: 10

b=iter(b)

# 二者输出等价,不过b是在运行时开辟内存,而a是直接开辟内存

print(next(a))

print(next(b))

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值