# 序列
for i in list(range(1, 10)):
print(i)
# 迭代器
# range不会将数字一次性传入内存,适合处理大型文件
for i in range(1, 10):
print(i)
迭代器
迭代器是一种读取数据的方式,当需要迭代对象时,会自动调用系统函数iter(),函数作用如下:
- 检查对象是否实现了iter方法,如果实现了,就会调用它,返回一个迭代器。
- 如果没有实现iter方法,但是实现了getitem方法python会创建一个迭代器,尝试按顺序(从零开始)获取元素。
- 如果前两者都没有,则会抛出TypeError异常。
迭代器规定了两个方法:
- iter:返回迭代器本身
- next:返回下一个元素
读取完毕之后,要触发一个StopIteration异常
用一个类实现迭代器,功能类似range
class CountDown:
def __init__(self, step):
self.step = step
def __next__(self):
if self.step <= 0:
raise StopIteration
self.step -= 1
return self.step
def __iter__(self):
return self
for ele in CountDown(10):
print(ele)
上边的CountDown类生成了一个迭代器,用for循环取出元素时,会自动生成下一个元素,而不是像list直接将所有元素装入内存。(迭代器比较省内存)
为了更好地认识迭代器,用序列和迭代器实现同一个类Sentence,能够将字符串逐个输出。
先用序列实现
import reprlib # 可以使过长的字符串不全显示,中间的字符用...来代替
class Sentence:
def __init__(self, text):
self.text = text
self.words = self.text.split()
def __getitem__(self, item):
return self.words[item]
def __len__(self):
return len(self.words)
def __repr__(self):
return 'Sentence(%s)' % reprlib.repr(self.text)
# return 'Sentence(%s)' % self.text
s = Sentence("this is a big and delicious apple") # 生成一个序列对象
print(s)
for i in s:
print(i)
输出如下
Sentence('this is a bi...licious apple')
this
is
a
big
and
delicious
apple
将上边的类用迭代器实现
class Sentence:
def __init__(self, text):
self.text = text
self.words = self.text.split()
self.length = len(self.words)-1
self.counter = -1
def __next__(self):
if self.counter >= self.length :
raise StopIteration
self.counter += 1
return self.words[self.counter]
def __iter__(self):
return self
s = Sentence("this is a delicious apple")
print(s)
for word in s:
print(word)
输出如下
<__main__.Sentence object at 0x000001ED2A8E1F98>
this
is
a
delicious
apple
第一个类可以用下标进行访问,而第二个不可以,这意味着第二类的元素不像序列那样挨个存放,而是更加灵活地分开存放。
生成器
生成器,顾名思义是为了生成数据。为了更好地了解生成器,我们先回顾一下用递归生成斐波那契数列。
斐波那契数列
def fib(n):
if n == 1 or n == 2:
return 1
else:
return fib(n-1) + fib(n-2)
print(fib(100))
当运行程序时,会报出RecursionError: maximum recursion depth exceeded in comparison
错误,这说明fib()不能递归太多次。
下面常使用生成器的形式实现斐波那契数列
def fibbacci():
a, b = 0, 1
while True:
yield b
a, b = b, a+b
f = fibbacci()
for _ in range(1000):
print(next(f))
数据太多,只展示一下第一千个数
43466557686937456435688527675040625802564660517371780402481729089536555417949051890403879840079255169295922593080322634775209689623239873322471161642996440906533187938298969649928516003704476137795166849228875
说明生成器可以正常地生成数据,不受次数的限制。
总结:
- 其中的next方法会在yield关键字处停止,并返回yield后的值。
- 只要python函数的定义中有yield关键字,该函数就是生成器。
- 调用生成器函数时,会返回一个生成器对象。也就是说,生成器函数是用来生成生成器的。
- 一般函数使用return返回,而生成器是由yield返回数据。