迭代
如何判断一个对象是可迭代对象呢?
方法是通过collections.abc模块的Iterable类型判断:
- >>> from collections.abc import Iterable
- >>> isinstance('abc', Iterable) # str是否可迭代
- True
- >>> isinstance([1,2,3], Iterable) # list是否可迭代
- True
- >>> isinstance(123, Iterable) # 整数是否可迭代
- False
将list对象转换成可迭代对象,进行对下标运算
- >>> for i, value in enumerate(['A', 'B', 'C']):
- ... print(i, value)
- ...
- 0 A
- 1 B
- 2 C
上面的for循环里,同时引用了两个变量,在Python里是很常见的,比如下面的代码:
- >>> for x, y in [(1, 1), (2, 4), (3, 9)]:
- ... print(x, y)
- ...
- 1 1
- 2 4
- 3 9
利用列表函数进行生成
- >>> [x * x for x in range(1, 11)]
- [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
还可以使用两层循环,可以生成全排列:
- >>> [m + n for m in 'ABC' for n in 'XYZ']
- ['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']
if和else写法
正确
- >>> [x for x in range(1, 11) if x % 2 == 0]
- [2, 4, 6, 8, 10]
错误,我们不能在最后的if加上else
- >>> [x for x in range(1, 11) if x % 2 == 0 else 0]
- File "
" , line 1 - [x for x in range(1, 11) if x % 2 == 0 else 0]
- ^
- SyntaxError: invalid syntax
在一个列表生成式中,for前面的if ... else是表达式,而for后面的if是过滤条件,不能带else
例:
- >>> [x if x % 2 == 0 else -x for x in range(1, 11)]
- [-1, 2, -3, 4, -5, 6, -7, 8, -9, 10]
-
- #等价于
-
- for x in range(1,11):
- if x % 2==0:
- x
- else:
- -x
- >>> L1 = ['Hello', 'World', 18, 'Apple', None]
- >>> [s.lower() if isinstance(s, str) else s for s in L1 if s!=None]
-
-
- #等价于
-
- for s in L1:
- if s!=None:# 过滤条件
- if isinstance(s, str):
- s.lower()
- else:
- s
生成器
列表生成器的缺陷:将数据全部生成浪费内存
通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。
方法一:将列表生成式的[]改成()
- >>> L = [x * x for x in range(10)]
- >>> L
- [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
- >>> g = (x * x for x in range(10))
- >>> g
- <generator object <genexpr> at 0x1022ef630>
通过next()函数获得generator的下一个返回值:
- >>> next(g)
- 0
- >>> next(g)
- 1
- >>> next(g)
- 4
- >>> next(g)
- 9
- >>> next(g)
- 16
- >>> next(g)
- 25
- >>> next(g)
- 36
- >>> next(g)
- 49
- >>> next(g)
- 64
- >>> next(g)
- 81
- >>> next(g)
- Traceback (most recent call last):
- File "
" , line 1, in <module> - StopIteration
generator保存的是算法,每次调用next(g),就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。
可以使用for进行调用
- >>> g = (x * x for x in range(10))
- >>> for n in g:
- ... print(n)
- ...
- 0
- 1
- 4
- 9
- 16
- 25
- 36
- 49
- 64
- 81
另一种写法:yield关键字
考虑斐波拉契数
- def fib(max):
- n, a, b = 0, 0, 1
- while n < max:
- print(b)
- a, b = b, a + b
- n = n