切片
-
我理解的切片主要是为了方便选用 list 或者 tuple 或者 str 等类型数据的部分元素。
-
常见的对于单个元素的使用,直接通过索引选取即可,如选取 L 中的第 2 个元素 L[1]。
-
对于指定范围内的索引操作,就显得效率很低,如选取L中的第 2 到第 4 个元素,L[1],L[2],L[3],这种方式太笨拙了,需要手动一个一个地选取,如果要选取一万个呢?难道要一个一个输入?
-
切片通过指定索引皆就可以方便取出,选取L中的第 2 到第 4 个元素,L[1:4]。
-
可以通过切片生成 list
>>> L = list(range(100)) >>> L [0, 1, 2, 3, ..., 99] -
倒数第一个元素的索引是 -1 ,正数第一个元素的索引是0
>>> L[-2:] [98, 99] -
取某个范围内的元素
>>> L[10:20] [10, 11, 12, 13, 14, 15, 16, 17, 18, 19] -
每两个取一个
>>> L[:10:2] # “:”表示从 0 开始遍历 [0, 2, 4, 6, 8] -
tuple 也是一种 list,唯一区别是 tuple 不可变。因此, tuple 也可以用切片操作,只是操作的结果仍是 tuple:
>>> (0, 1, 2, 3, 4, 5)[:3] (0, 1, 2) -
字符串也可以看成是一种 list ,每个元素就是一个字符。因此,字符串也可以用切片操作,只是操作结果仍是字符串。
迭代
-
如果给定一个 list 或 tuple 或者 str 或者 dict 等类型,我们可以通过 for 循环来遍历,这种遍历我们称为迭代(Iteration)。在 Python 中只要是可迭代对象,无论有无下标,都可以迭代。
-
如何判断一个对象是可迭代对象呢?方法是通过 collections 模块的 Iterable 类型判断:
>>> from collections import Iterable >>> isinstance('abc', Iterable) # str是否可迭代 True >>> isinstance([1,2,3], Iterable) # list是否可迭代 True >>> isinstance(123, Iterable) # 整数是否可迭代 False -
Python 内置的 enumerate 函数可以把一个 list 变成索引-元素对,这样就可以在 for 循环中同时迭代索引和元素本身。
>>> for i, value in enumerate(['A', 'B', 'C']): ... print(i, value) 0 A 1 B 2 C -
默认情况下,dict 迭代的是 key。如果要迭代 value,可以用 for value in d.values(),如果要同时迭代 key 和value ,可以用 for k, v in d.items()。
-
同时引用了两个变量,在 Python 里是很常见的
>>> for x, y in [(1, 1), (2, 4), (3, 9)]: ... print(x, y) ... 1 1 2 4 3 9
列表生成式
-
列表生成式即 List Comprehensions,是 Python 内置的非常简单却强大的可以用来创建 list 的生成式,生成复杂的 list ,可以用此方法。
-
如求平方数,并做偶数判断
>>> [x * x for x in range(1, 11) if x % 2 == 0] [4, 16, 36, 64, 100] -
使用两层循环
>>> [m + n for m in 'ABC' for n in 'XYZ'] ['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ'] -
列表生成式也可以使用两个变量来生成list
>>> d = {'x': 'A', 'y': 'B', 'z': 'C' } >>> [k + '=' + v for k, v in d.items()] ['y=B', 'x=A', 'z=C']
生成器
-
受到内存限制,通过列表生成式生成的列表容量肯定是有限的。生成大量的元素时候,如果我们仅仅需要访问前面几个元素,那很多其他元素占用的空间都浪费了。所以,按照某种算法一边循环一边计算的机制,称为生成器:generator 。
-
第一种创建方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator。
>>> L = [x * x for x in range(5)] >>> L [0, 1, 4, 9, 16] >>> g = (x * x for x in range(5)) >>> g <generator object <genexpr> at 0x11fb91bf8> -
第二种创建方法是在函数中包含 yield 关键字,那么这个函数就不再是一个普通函数,而是一个 generator。
-
如果要一个一个打印出来,可以通过 next() 函数获得generator的下一个返回值,但是一般情况下是不会用的,因为一个一个输出,这种做法太笨拙了,而且容易报错。
def odd(): print('step 1') yield 1 print('step 2') yield(3) print('step 3') yield(5) >>> o = odd() >>> next(o) step 1 1 >>> next(o) step 2 3 >>> next(o) step 3 5 >>> next(o) Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration -
正确的方法是使用for循环,因为 generator 也是可迭代对象。并且不需要关心因为 next() 方法而引起的 StopIteration 的错误。
def fib(max): n, a, b = 0, 0, 1 while n < max: yield b a, b = b, a + b n = n + 1 return 'done' >>> for n in fib(6): ... print(n) ... 1 1 2 3 5 8 -
如果想要拿到返回值,必须捕获 StopIteration 错误,返回值包含在 StopIteration 的value中。
>>> g = fib(6) >>> while True: ... try: ... x = next(g) ... print('g:', x) ... except StopIteration as e: ... print('Generator return value:', e.value) ... break ... g: 1 g: 1 g: 2 g: 3 g: 5 g: 8 Generator return value: done
迭代器
-
凡是可作用于for循环的对象都是 Iterable 类型;
-
凡是可作用于 next() 函数的对象都是 Iterator 类型,它们表示一个惰性计算的序列;
-
集合数据类型如 list、dict、str 等是 Iterable 但不是 Iterator,不过可以通过 iter() 函数获得一个 Iterator 对象。
-
因为 Python 的 Iterator 对象表示的是一个数据流,Iterator 对象可以被 next() 函数调用并不断返回下一个数据,直到没有数据时抛出 StopIteration 错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过 next() 函数实现按需计算下一个数据,所以 Iterator 的计算是惰性的,只有在需要返回下一个数据时它才会计算。
本文参考:
廖雪峰:www.liaoxuefeng.com/wiki/101695…
一分不嫌少,一分也有爱
支付宝