python基础之可迭代对象和迭代器傻傻分不清楚

学习目录

1. 判断对象是可迭代对象和迭代器 

2. 常见的列表等是可迭代对象,但不是迭代器

3. 使用iter()将可迭代对象转换为迭代器 

4. for...in...循环的实现过程 

5. 自定义迭代器 

6. 生成器也是迭代器

概念

可迭代对象:指python中可以用来迭代(支持for循环)的对象,比如常见的列表/元组/字典/字符串等,这些对象中都会定义__iter__魔法方法。

迭代器:指可以帮助我们迭代其他对象的一种对象。这类对象会定义__iter__,__next__魔法方法,可通过next()函数获取迭代的结果。

可迭代对象不一定是迭代器,但迭代器肯定是可迭代对象。因为迭代器要求必须同时实现__iter__方法和__next__方法, 而一旦实现了__iter__方法就必然是一个可迭代对象。但是反过来则不成立,可迭代对象可以不是迭代器。

判断对象是可迭代对象还是迭代器

在python模块中先导入Iterable和Iterator。

from typing import Iterable,Iterator
或者
from collections.abc import Iterable,Iterator

通过isinstance(Object, Iterable)可判断一个对象是否是可迭代对象

通过isinstance(Object, Iterator)可判断一个对象是否是迭代器

常见的列表等是可迭代对象,但不是迭代器

#定义一个列表
listA = [1,4,3,2]
print(f'列表是否是迭代对象 :{isinstance(listA,Iterable)}')
print(f'列表是否是迭代器 {isinstance(listA,Iterator)}')

#结果:
列表是否是迭代对象 :True
列表是否是迭代器 False

python安装后有个自带的模块builtins.py,找到定义的list类,会发现该类中定义了__iter__方法,没有定义__next__方法。

class list(object):
  """
  Built-in mutable sequence.
  If no argument is given, the constructor creates a new empty list.
  The argument must be an iterable if specified.
  """
	def append(self, *args, **kwargs): # real signature unknown
	""" Append object to the end
	.....
	def __iter__(self, *args, **kwargs): # real signature unknown
	""" Implement iter(self). """
		pass

因此使用next()执行会报错列表不是一个迭代器。

next(listA)

#会报错如下
Traceback (most recent call last):
File "test.py", line 9, in <module>
next(listA)
TypeError: 'list' object is not an iterator

使用iter()将可迭代对象转换为迭代器

还是以上面的列表举例,使用iter()将列表转换为迭代器。

list_iter = iter(listA)
print(f'列表使用iter()后是否是迭代对象 :{isinstance(list_iter,Iterable)}')
print(f'列表使用iter()后是否是迭代器 {isinstance(list_iter,Iterator)}')

#打印结果
列表使用iter()后是否是迭代对象 :True
列表使用iter()是否是迭代器 True

for...in...循环的实现过程

 for item in Iterable先通过iter()函数获取可迭代对象Iterable的迭代器,然后对迭代器不断调⽤next()⽅法来获取下⼀个值并将其赋值给item,当遇到StopIteration的异常后循环结束。

自定义迭代器

创建一个类,定义__iter__和 __next__方法,实现自定义的迭代器。

举例:传入一个数字,返回被2整除的大于0的数字。

class MyIterator():
	def __init__(self,digitnum):
		self.digitnum=digitnum
		self.current_num = 0
	def __iter__(self):
		print('调用了__iter__方法')
		return self
	def __next__(self):
		print('调用了__next__方法')
		while True:
			if self.current_num >= self.digitnum:
				raise StopIteration
			if self.current_num % 2 == 0 and self.current_num != 0:
				temp_num = self.current_num
				self.current_num += 1
				return temp_num
			self.current_num += 1

实例化后执行for循环

myiterator = MyIterator(11)
#for循环自定义的迭代器
for i in myiterator:
	print(i)
#结果如下:
调用了__iter__方法
调用了__next__方法
2
调用了__next__方法
4
调用了__next__方法
6
调用了__next__方法
8
调用了__next__方法
10
调用了__next__方法

生成器也是迭代器

  • 函数式生成器

在函数中使用yield关键字,而不是return关键字,代表该函数是生成器。生成器也是一种迭代器,可以使用for循环,每当函数执行到yield时会暂停,等待下次在该位置继续执行。

上面讲到的传入一个数字,返回被2整除的大于0的数用生成器实现如下。

def MyIterator(num):
	current_num = 0
	while current_num <= num:
		print (f'调用生成器 current_num : {current_num}')
		if current_num % 2==0 and current_num!=0:
			temp_num = current_num
			yield temp_num
		current_num += 1
#生成器也是一种迭代器
print(f'生成器 是否是可迭代对象 : {isinstance(MyIterator(10), Iterable)}')
print(f'生成器 是否是迭代器 : {isinstance(MyIterator(10), Iterator)}')
#结果:
生成器 是否是可迭代对象 : True
生成器 是否是迭代器 : True

执行for循环

for i in MyIterator(10):
	print(i)
#结果:
调用生成器 current_num : 0
调用生成器 current_num : 1
调用生成器 current_num : 2
2
调用生成器 current_num : 3
调用生成器 current_num : 4
4
调用生成器 current_num : 5
调用生成器 current_num : 6
6
调用生成器 current_num : 7
调用生成器 current_num : 8
8
调用生成器 current_num : 9
调用生成器 current_num : 10
10
  • 元组推导式其实是一种生成器

在前面章节中介绍了列表推导式/字典推导式/集合推导式,现在介绍下元组推导式,元组推导式的结构体类似于列表推导式,不再多做介绍,有兴趣的读者可以翻阅之前的文章。

#定义一个元组推导式
myiterator = ( i for i in range(10) if i != 0 and i%2==0)

#检查对象的类型
print(type (myiterator))

#结果是生成器
<class 'generator'>
#检查是否是迭代器
print (f'生成器 是否是可迭代对象 : {isinstance(myiterator,Iterable)}')
print (f'生成器 是否是迭代器 : {isinstance(myiterator,Iterator)}')
#结果
生成器 是否是可迭代对象 : True
生成器 是否是迭代器 : True
#使用for循环
for i in myiterator2:
print(i)
#结果
2
4
6
8

共勉: 东汉·班固《汉书·枚乘传》:“泰山之管穿石,单极之绠断干。水非石之钻,索非木之锯,渐靡使之然也。”

-----指水滴不断地滴,可以滴穿石头;

-----比喻坚持不懈,集细微的力量也能成就难能的功劳。

----感谢读者的阅读和学习和关注,谢谢大家。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值