Published in:2024-10-24 |

容器、可迭代对象、迭代器、生成器

一、容器

1
2
3
4
5
6
7
8
9
10
11
12
# 容器(Container)

1. 容器是一种把多个元素组成在一起的一种数据结构

2. 容器中的元素是可以逐个迭代获取(Python自带)

3. 可以使用成员关系操作符来判断元素是否在容器中 in / not in

4. 容器在Python中并不是一个真实存在的类型,它是抽象的概念,不能直接实例化一个Container对象

5. Python中常见的容器类型:
list、tuple、dict、str、set、frozenset

二、可迭代对象

1
2
3
4
5
6
7
8
9
10
# 可迭代对象(iterable)

1. 很多容器都是可迭代对象
- for i in 对象: 该对象就是一个可迭代对象
- 实现__iter__方法

2. 可以使用iter(iterable)返回一个迭代器
- 一个对象可迭代的本质是 通过迭代器来实现的
l = [2,4,6,8,22]
iterator = iter(l)

三、迭代器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 迭代器(iterator)

1. iter(可迭代对象)可以返回这个对象的迭代器

2. 任何实现了__iter____next__方法的对象都是迭代器对象
迭代器如何实现迭代元素操作:
l = [2,4,6,8,22]
iterator = iter(l) # 获取迭代器
next(iterator) / iterator.__next__() # 获取下一个元素
迭代器获取可迭代对象中的元素是使用了__next__方法


3. 迭代器对象是一个带状态的对象 __index记录当前迭代的位置

4. 迭代器也是一个可迭代对象, 而可迭代对象不一定是一个迭代器(next)
for i in l: # l->iterator->next
print(i)

for i in iterator: # iterator->next
print(i)
1
2
3
4
5
6
7
8
9
10
# for循环底层实现
for i in [2,4,6,8,22]:
print(i)

1. 先获取in后面的可迭代对象的迭代器
iter(in后面的对象) 或 In后面的对象.__iter__

2. 使用上面1中获取到的迭代器,再调用它的__next__方法来返回可迭代对象中的元素
__next__ 底层有一个__index下标来记录当前迭代的位置 再return 可迭代对象[__index]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 自定义实现一个迭代器
class Stack:
def __init__(self,*args):
self.__items = list(args)
self.__index = 0

def __iter__(self):
return self

def __next__(self):
if self.__index < len(self.__items):
item = self.__items[self.__index]
self.__index += 1
return item
else:
raise StopIteration

s = Stack(1,2,3,4)
for item in s:
print(item)

iterator = iter(s)
print(next(iter(iterator)))
print(next(iter(iterator)))
print(next(iter(iterator)))
print(next(iter(iterator)))
print(next(iter(iterator)))

四、生成器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 生成器(generator)

a. 生成一个列表,列表中的所有元素都会存内存中,如果列表中的元素比较多,会大量占用内存空间,如果列表的后续元素可以按照某种算法推算出来,此时就可以使用生成器来完成

b. 生成器是一个特殊的迭代器 所以可以next(生成器)来获取下一个元素

l = [i for i in range(100)]

1. 列表推导式将[]改为()
g = (i for i in range(100)) # 返回了生成器

2. yield关键字
如果一个函数中包含了yield关键字,此时该函数就不再是一个普通的函数,而是一个生成器,调用函数在本质是构造了一个生成器

def getNumber():
print('aaaaaaaaaaa')
for i in range(5):
print('bbbbbbb')
yield i # yield相当于return返回了一个值,并且它会记住这个代码的位置,下一次迭代时,代码从上一次的位置继续执行

n = getNumber()
print(n)

print(next(n))
print(next(n))
Prev:
Next: