python 迭代器、生成器、递归
生成器
通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。这时生成器的优势就出来了,他只会依次一个的取出数据,而非一次性全部生成。
>>> l = [ x for x in range(10)] #列表生成 >>> l [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> m = (x for x in range(10)) #生成器 >>> m <generator object <genexpr> at 0x0000000000D44048> >>> next(m) 0 >>> next(m) 1 >>> next(m) 2 ... >>> next(m) #取到最后,报错 Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration
l和m的区别在于l是一个列表,而m是一个generator对象,需要使用next方法(迭代器)去一个一个取出数据,而不会一次性全部返回。同时,生成器也可以使用一次行遍历出所有数据
>>> m = (x for x in range(10)) >>> for i in m: ... print(i) ... 0 1 2 3 4 5 6 7 8 9 >>>
生成器可以使用于算法推导,如著名的斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到
>>> def f(max): ... n,a,b = 0,0,1 ... while n < max: ... yield b ... a,b = b,a+b ... n = n+1 ... >>> f <function f at 0x0000000000D3BD08> >>> m = f(6) >>> next(m) 1 >>> next(m) 1 >>> next(m) 2
迭代器:
迭代器:是访问集合元素的一种方式。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
优点:对于原生支持随机访问的数据结构(如tuple、list),迭代器和经典for循环的索引访问相比并无优势,反而丢失了索引值(可以使用内建函数enumerate()找回这个索引值)。但对于无法随机访问的数据结构(比如set)而言,迭代器是唯一的访问元素的方式。
另外,迭代器的一大优点是不要求事先准备好整个迭代过程中所有的元素。迭代器仅仅在迭代到某个元素时才计算该元素,而在这之前或之后,元素可以不存在或者被销毁。这个特点使得它特别适合用于遍历一些巨大的或是无限的集合,比如几个G的文件,或是斐波那契数列等等。
>>> m = (x for x in range(10)) #生成器 >>> m <generator object <genexpr> at 0x0000000000D44048> >>> next(m) #next则为迭代器的一个方法 0 >>> next(m) 1 >>> next(m) 2 ... >>> next(m) #取到最后,报错 Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration
迭代器,遇到yield就记录当前位置,下次从当前位置开始
>>> def f(): ... print(111) ... yield 0 ... print(222) ... yield 1 ... print(333) ... yield 2 ... >>> ret = f() >>> r1 = ret.__next__() 111 >>> print(r1) 0 >>> r1 = ret.__next__() 222 >>> r1 = ret.__next__() 333 >>> r1 = ret.__next__() Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration
递归
递归,直接或间接调用自身的一种方法。一个函数在内部调用自身本身,这个函数就是递归函数。
>>> def f(n): ... if n == 1: ... return 1 ... return n * f(n-1) ... >>> ret = f(5) >>> print(ret) 120 >>>
浙公网安备 33010602011771号