一、定制序列(容器类型)
- 协议(Protocols)与其他编程语言中的接口很相似,它规定你哪些方法必须要定义。然而,在Python中的协议就显得不那么正式。事实上,在Python中,协议更像是一种指南。
- 定制容器的协议
- 如果你希望定制的容器是不可变的话,你只需要定义__len__()和__getitem__()方法 (str、tuple)
- 如果你希望定制的容器是可变的话,你需要定义_len__()、__getitem__()、__setitem__()和__delitem__()方法 (list)
- 例:编写一个不可变的自定义列表,要求记录列表中每个元素被访问的次数
-
1 class CountList(): 2 def __init__(self, *args): 3 self.l = [x for x in args] 4 self.count = {}.fromkeys(range(len(self.l)), 0) 5 6 def __len__(self): 7 return len(self.l) 8 9 def __getitem__(self, index): 10 self.count[index] += 1 11 return self.l[index]
二、迭代
- 定义:迭代就类似循环,每一次重复的过程称为一次迭代的过程,每一次迭代的结果将作为下一次迭代的初始值
- 提供迭代方法的容器称为迭代器,如:list,字符串,字典
- 通常用for i in “xx”,用于触发迭代操作;while循环实现for
- iter()——容器对象调用iter()就得到它的迭代器
- next()——调用next()迭代其就会返回下一个值,如果没有值可以返回了python就会抛出一个叫做StopIteration
-
In [105]: s = "fichc" In [106]: it = iter(s) In [107]: next(it) Out[107]: 'f' In [108]: next(it) Out[108]: 'i'
- __iter__()——返回迭代器本身(对应iter()方法)
- __next__()——决定迭代器的规则(对应next()方法)
- Fibs数列(下一个值是前两个的和):
1 class Fibs():
2 def __init__(self, a, b):
3 self.a = a
4 self.b = b
5 def __iter__(self):
6 return self
7 def __next__(self):
8 self.a, self.b = self.b, self.a + self.b
9 return self.a
In [128]: a = test.Fibs(1, 2)
In [129]: it = iter(a)
In [130]: next(it)
Out[130]: 2
In [131]: next(it)
Out[131]: 3
In [121]: a = test.Fibs(1, 2)
In [122]: for each in a:
...: if each < 20: #也可以把判断放到__next__(self),通过if xxx: raise StopIteration
...: print(each)
...: else:
...: break
...:
2
3
5
8
13
三、乱入:生成器generator
- 迭代器和生成器是python引入的最强大的概念
- 生成器是迭代器的一种实现,因为定义生成器需要写个类,生成器只需要一个yield
- 生成器的发明使得python模仿协同程序的概念得以实现。协同程序就是可以运行的独立函数调用,函数可以暂停或者挂起,并在需要的时候从程序离开的地方继续或者重新开始
- 像一个会暂停,又能回来的return
- 可以使用next()一次执行一回,也可以用for循环一次去不打印
-
1 #coding:utf8 2 def myGen(): 3 print('生成器被执行') 4 yield 1 5 yield 2 In [137]: myG = test.myGen() In [138]: next(myG) 生成器被执行 Out[138]: 1 #在yield1暂停 In [139]: next(myG) Out[139]: 2 #在yield暂停 In [140]: next(myG) --------------------------------------------------------------------------- StopIteration Traceback (most recent call last) <ipython-input-140-bf2e9b04d728> in <module>() ----> 1 next(myG) StopIteration: 斐波那契数列也可以用到yield def libs(): a = 0 b = 1 while True: a, b = b, a + b yield a
- 列表推倒式
-
a = [i for i in range(100) if not (i % 2) and i % 3] [2, 4, 8, 10, 14, 16, 20, 22, 26, 28, 32, 34, 38, 40, 44, 46, 50, 52, 56, 58, 62, 64, 68, 70, 74, 76, 80, 82, 86, 88, 92, 94, 98]
-
python3还有字典推导式
-
b = {i:i % 2 == 0 for i in range(10)} {0: True, 1: False, 2: True, 3: False, 4: True, 5: False, 6: True, 7: False, 8: True, 9: False}
- 集合set推导式
-
In [154]: {i for i in [1,2,1,3]} Out[154]: {1, 2, 3}
- 生成器推导式,可以next(e),作为函数的参数时,可以省略最外边的括号。
-
In [156]: e = (i for i in range(10)) Out[156]: <generator object <genexpr> at 0x7fa1635bb518>
生成器推到式若果作为函数的参数,可以直接写推导式,不用写圆括号;也可以加上
-
>>> sum(i for i in range(100) if i %2) 2500
- 没有元组推导式,元组推导式其实得到的就是生成器推导式;没有字符串推导式