1.迭代器(迭代取值和索引取值的对比)
# 迭代器主要就是一个迭代取值,另外一种取值方式就是索引(下标)取值
l = [1, 2, 3, 4]
res = l.__iter__()
res.__next__() # 1
res.__next__() # 2
res1 = l.__iter__()
res1.__next__() # 1
res1.__next__() # 2
迭代取值 1. 不依赖于索引取值的一种取值方式 2. 不能够重复取值,只能够从左往右固定取值 索引取值 1. 它能够重复取值(通过索引l[0]) 2. 它需要是容器类型
2.生成器(自定义的迭代器)(yield)
背景: 通过列表生成式,我们可以直接创建一个列表,但是,受到内存限制,列表容量肯定是有限的,而且创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。 所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间,在Python中,这种一边循环一边计算的机制,称为生成器:generator , python中生成器是自定义迭代器的一种
生成器如何使用 关键字:yield ''' 当函数中一旦出现了yield关键字,函数在没有被调用的时候仍然是普通函数,但是只要一调用函数,那么,该函数就不是普通函数了 就变成了生成器
def index():
print('from index')
print('from index')
print('from index')
yield 123,234,345 # 以元组的方式返回
print('second')
print('second')
print('second')
print('second')
yield 'hello'
print('three')
yield
res=index() # res.__iter__()
print(res) # <generator object index at 0x000002CDB20BEA50>
## 生成器其实就是一个自定义的迭代器
# res.__next__() # 只要你调用next方法,代码就会走到函数中第一个yield关键字所在的位置停住
# res.__next__() # 代码从上一次yield停住的地方继续往下执行,走到遇到下一个yield停住
print(res.__next__()) # None 123
print(res.__next__()) # None 123
print(res.__next__()) # None 123
3.生成器yield关键字的其他用法
def eater(name):
print('%s:正在吃...' % name)
while True:
food = yield
print('%s正在吃%s' % (name, food))
'''eater就变成了生成器'''
res=eater('jerry') # 生成器对象:generator object
print(res) # <generator object eater at 0x0000021869489B30>
res.__next__()
# res.__next__()
# send做了两件事情:1. 传值给yield、2. 执行__next__
res.send('包子')
res.send('水果')
res.send('水果')
res.send('水果')
res.send('水果')
res.send('水果')
res.send('水果')
res.send('水果')
res.send('水果')
4.生成器试题
利用生成器的原理实现range函数的功能
利用生成器的原理实现range函数的功能
# range() 三种玩法
def my_range():
pass
for i in range(0,10):
print(i)
def my_range(start, stop=None, step=1):
if not stop: # 意味着只传了一个参数,stop没有值
stop = start
start = 0
while start < stop:
yield start
start+=step
# print(my_range(0, 20))
# for i in my_range(0, 20):
# print(i)
# for i in my_range(0, 20, 2):
# print(i)
for i in my_range(10):
print(i)
5.生成器表达式
列表生成式
res = [name for name in names_list]
print(res) # 就是一个列表
res1 = (name for name in names_list)
print(res1)
names_list = ['kevin', 'jerry', 'tony', 'oscar']
res1 = (name for name in names_list)
print(res1) # <generator object <genexpr> at 0x00000218F4569CF0>
print(res1.__next__())
print(res1.__next__())
print(res1.__next__())
print(res1.__next__())
生成器表达式如果不使用数据,就不给你数
把迭代器、生成器看成是一个工厂,什么时候需要数据工厂就给你加工数据 目的:就是为了节省内存空间
6.yield和return的对比
yield 1. 代码遇到yield不会停止,而是停住
2. yield也可以有返回值,并且还支持多个,以元组的形式返回
3. yield可以把一个函数变成生成器,next取值
return 1. 代码遇到return就会停止 ’
2. return可以有返回值并且还支持多个,以元组的形式返回