原文地址:https://blog.csdn.net/qq_41333582/article/details/82219190
一. 迭代
1. 迭代的概念
使用for循环遍历取值的过程叫做迭代,比如:使用for循环遍历列表获取值的过程
for value in [2, 3, 4]:
print(value)
2. 可迭代对象
使用for循环遍历取值的对象叫做可迭代对象, 比如:列表、元组、字典、集合、range、字符串
3. 判断对象是否为可迭代对象
# 元组,列表,字典,字符串,集合,range都是可迭代对象
from collections import Iterable
# 判断对象是否是指定类型
result = isinstance((3, 5), Iterable)
print("元组是否是可迭代对象:", result)
result = isinstance([3, 5], Iterable)
print("列表是否是可迭代对象:", result)
result = isinstance({"name": "张三"}, Iterable)
print("字典是否是可迭代对象:", result)
result = isinstance("hello", Iterable)
print("字符串是否是可迭代对象:", result)
result = isinstance({3, 5}, Iterable)
print("集合是否是可迭代对象:", result)
result = isinstance(range(5), Iterable)
print("range是否是可迭代对象:", result)
result = isinstance(5, Iterable)
print("整数是否是可迭代对象:", result)
# 提示: 以后还根据对象判断是否是其它类型,比如以后可以判断函数里面的参数是否是自己想要的类型
result = isinstance(5, int)
print("整数是否是int类型对象:", result)
class Student(object):
pass
stu = Student()
result = isinstance(stu, Iterable)
print("stu是否是可迭代对象:", result)
result = isinstance(stu, Student)
print("stu是否是Student类型的对象:", result)
4. 自定义可迭代对象
自定义可迭代对象: 在类里面定义iter方法创建的对象就是可迭代对象
二. 迭代器
1. 自定义迭代器对象
自定义迭代器对象: 在类里面定义iter和next方法创建的对象就是迭代器对象
from collections import Iterable
from collections import Iterator
# 自定义可迭代对象: 在类里面定义__iter__方法创建的对象就是可迭代对象
class MyList(object):
def __init__(self):
self.my_list = list()
# 添加指定元素
def append_item(self, item):
self.my_list.append(item)
def __iter__(self):
# 可迭代对象的本质:遍历可迭代对象的时候其实获取的是可迭代对象的迭代器, 然后通过迭代器获取对象中的数据
my_iterator = MyIterator(self.my_list)
return my_iterator
# 自定义迭代器对象: 在类里面定义__iter__和__next__方法创建的对象就是迭代器对象
class MyIterator(object):
def __init__(self, my_list):
self.my_list = my_list
# 记录当前获取数据的下标
self.current_index = 0
# 判断当前对象是否是迭代器
result = isinstance(self, Iterator)
print("MyIterator创建的对象是否是迭代器:", result)
def __iter__(self):
return self
# 获取迭代器中下一个值
def __next__(self):
if self.current_index < len(self.my_list):
self.current_index += 1
return self.my_list[self.current_index - 1]
else:
# 数据取完了,需要抛出一个停止迭代的异常
raise StopIteration
my_list = MyList()
my_list.append_item(1)
my_list.append_item(2)
result = isinstance(my_list, Iterable)
print(result)
for value in my_list:
print(value)
执行结果:
True
MyIterator创建的对象是否是迭代器: True
1
2
2. iter()函数和next()函数
- iter函数: 获取可迭代对象的迭代器,会调用可迭代对象身上的iter方法
- next函数: 获取迭代器中下一个值,会调用迭代器对象身上的next方法
3. for循环的本质
-
遍历的是可迭代对象
for item in Iterable 循环的本质就是先通过iter()函数获取可迭代对象Iterable的迭代器,然后对获取到的迭代器不断调用next()方法来获取下一个值并将其赋值给item,当遇到StopIteration的异常后循环结束。
-
遍历的是迭代器
for item in Iterator 循环的迭代器,不断调用next()方法来获取下一个值并将其赋值给item,当遇到StopIteration的异常后循环结束。
4. 利用斐波那契数列实现迭代器
class Fibonacci(object):
def __init__(self, num):
# num:表示生成多少fibonacci数字
self.num = num
# 记录fibonacci前两个值
self.a = 0
self.b = 1
# 记录当前生成数字的索引
self.current_index = 0
def __iter__(self):
return self
def __next__(self):
if self.current_index < self.num:
result = self.a
self.a, self.b = self.b, self.a + self.b
self.current_index += 1
return result
else:
raise StopIteration
fib = Fibonacci(5)
# value = next(fib)
# print(value)
for value in fib:
print(value)
三. 生成器
1. 生成器的概念
生成器是一类特殊的迭代器,它不需要再像上面的类一样写iter()和next()方法了, 使用更加方便,它依然可以使用next函数和for循环取值
2. 创建生成器的两种方式
- 第一种方法很简单,只要把一个列表生成式的 [ ] 改成 ( )
- 在def函数里面看到有yield关键字那么就是生成器
总结:
在使用生成器实现的方式中,我们将原本在迭代器next方法中实现的基本逻辑放到一个函数中来实现,但是将每次迭代返回数值的return换成了yield,此时新定义的函数便不再是函数,而是一个生成器了。
简单来说:只要在def中有yield关键字的 就称为 生成器
3.yield 和 return 对比
- 使用了yield关键字的函数不再是函数,而是生成器。(使用了yield的函数就是生成器)
- 代码执行到yield会暂停,然后把结果返回出去,下次启动生成器会在暂停的位置继续往下执行
- 每次启动生成器都会返回一个值,多次启动可以返回多个值,也就是yield可以返回多个值
- return只能返回一次值,代码执行到return语句就停止迭代,抛出停止迭代异常
4. 使用 send方法可以为生成器传参
注意:如果第一次启动生成器使用send方法,那么参数只能传入None,一般第一次启动生成器使用next函数
总结:
生成器创建有两种方式,一般都使用yield关键字方法创建生成器
yield特点是代码执行到yield会暂停,把结果返回出去,再次启动生成器在暂停的位置继续往下执行