1 ################
2 # hashable协议 #
3 ################
4
5 # 一个对象能被称为hashable,它必须实现__hash__与_eq__方法:
6 >>>{[1,2,3]} # TypeError: unhashable type: 'list'
7 >>>{{'Justin':123456}} # TypeError: unhashable type: 'dict'
8 >>>{{1,2,3}} # TypeError: unhashable type: 'set'
9
10 # 虽然p1与p3代表的是相同的坐标,但是集合中两个都收纳了,这是因为p1和p3使用默认的__hash__()获取的hash值不同
11 class Point:
12 def __init__(self,x,y):
13 self.x=x
14 self.y=y
15 def __repr__(self):
16 return 'Point({},{})'.format(self.x,self.y)
17 p1=Point(1,1)
18 p2=Point(2,2)
19 p3=Point(1,1)
20 ps={p1,p2,p3}
21 print(ps) # 显示{Point(1,1), Point(2,2), Point(1,1)}
22
23 # 如果想让集合能提出代表相同坐标的Point对象,必须自行实现__eq__()与__hash__()方法
24 class Point:
25 def __init__(self,x,y):
26 self.x=x
27 self.y=y
28 def __eq__(self, other):
29 if hasattr(other,'x') and hasattr(other,'y'):
30 return self.x == other.x and self.y ==other.y
31 return False
32 def __hash__(self):
33 return 41 * (41+self.x)+self.y
34 def __str__(self):
35 return self.__repr__()
36 def __repr__(self):
37 return 'Point({},{})'.format(self.x,self.y)
38 p1=Point(1,1)
39 p2=Point(2,2)
40 p3=Point(1,1)
41 ps={p1,p2,p3}
42 print(ps) # 显示{Point(1,1), Point(2,2)}
43
44 ################
45 # iterable协议 #
46 ################
47
48 # 具有__iter__()方法的对象,就是一个iterable(可迭代的)对象
49 # 生成器也是一种迭代器,对于大部分的迭代需求,使用yield语句创建生成器会比较简单和直接
50 def cycle(elems):
51 while True:
52 for elem in elems:
53 yield elem
54 abcd_gen=cycle(('abcd'))
55 print(next(abcd_gen))
56 print(next(abcd_gen))
57 print(next(abcd_gen))
58 print(next(abcd_gen))
59 print(next(abcd_gen))
60
61 # 实现__iter__()
62 class Repeat:
63 def __init__(self,elem,n):
64 self.elem=elem
65 self.n=n
66 def __iter__(self):
67 elem=self.elem
68 n=self.n
69 class _Iter:
70 def __init__(self):
71 self.count=0
72 def __next__(self):
73 if self.count < n:
74 self.count += 1
75 return elem
76 else:
77 raise StopIteration
78 def __iter__(self):
79 return self
80 return _Iter()
81 for elem in Repeat('A',5):
82 print(elem,end=' ')
83
84 # 使用itertools模块
85 # 在Python标准链接库中提供了itertools模块,当中有许多函数可以谢谢胡创建迭代器和生成器
86 import itertools
87 print(list(itertools.repeat('A',10))) #['A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A']
88 print(list(itertools.accumulate([1,2,3,4,5]))) # [1, 3, 6, 10, 15]
89 print(list(itertools.accumulate([1,2,3,4,5],int.__mul__))) # [1, 2, 6, 24, 120]
90 print((list(itertools.chain('ABC',[1,2,3])))) # ['A', 'B', 'C', 1, 2, 3]
91 print(list(itertools.chain.from_iterable(['ABC',[1,2,3]]))) # ['A', 'B', 'C', 1, 2, 3]
92 print(list(itertools.chain.from_iterable([[9,8,6],[1,2,3]]))) #[ 9, 8, 6, 1, 2, 3]
93 print(list(itertools.dropwhile(lambda x:x < 5,[1,4,6,4,1]))) # [6, 4, 1]
94 print(list(itertools.takewhile(lambda x:x < 5,[1,4,6,4,1]))) # [1, 4]
95 print(list(itertools.filterfalse(lambda x:x % 2,[1,2,3,4]))) # [2, 4]
96
97 # 有时候可能需要按某个键进行分类,可以使用itertools的groupby函数:
98 name=['Justin','Monica','Irene','Pika','caterpillar']
99 group_by_name=itertools.groupby(name,lambda name:len(name))
100 for length,group in group_by_name:
101 print(length,list(group))
102 # 6 ['Justin', 'Monica']
103 # 5 ['Irene']
104 # 4 ['Pika']
105 # 11 ['caterpillar']
106
107 ################
108 # orderable协议 #
109 ################
110
111 # 如果希望使用自定义类型的sorted()或者使用列表的sort()时有默认的排序定义,那么必须实现__lt__()方法
112 class Customer:
113 def __init__(self,name,symbol,age):
114 self.name=name
115 self.symbol=symbol
116 self.age=age
117 def __lt__(self, other):
118 return self.name < other.name
119 def __str__(self):
120 return "Customer('{name}','{symbol}'".format(**vars(self))
121 def __repr__(self):
122 return self.__str__()
123 customers=[
124 Customer('Justin','A',40),
125 Customer('Irene','C',8),
126 Customer('Monica','B',37),
127 ]
128 print(sorted(customers)) # [Customer('Irene','C', Customer('Justin','A', Customer('Monica','B']
129
130 # opertor模块的itemgetter和attrgetter,前者可以针对具有索引的结构,后者可以针对对象的属性
131 # 下面是使用itemgetter的示范:
132 from operator import itemgetter
133 custormers=[('Justin','A',40),('Irene','C',8),('Monica','B',37),]
134 print(sorted(custormers,key=itemgetter(0))) # [('Irene', 'C', 8), ('Justin', 'A', 40), ('Monica', 'B', 37)]
135 print(sorted(custormers,key=itemgetter(1))) # [('Justin', 'A', 40), ('Monica', 'B', 37), ('Irene', 'C', 8)]
136 print(sorted(custormers,key=itemgetter(2))) # [('Irene', 'C', 8), ('Monica', 'B', 37), ('Justin', 'A', 40)]
137
138 # 下面是使用attrgetter的示范:
139 from operator import attrgetter
140 class Customer:
141 def __init__(self,name,symbol,age):
142 self.name=name
143 self.symbol=symbol
144 self.age=age
145 def __repr__(self):
146 return "Customer('{name}','{symbol}',{age})".format(**vars(self))
147 customers=[
148 Customer('Justin','A',40),
149 Customer('Irene','C',8),
150 Customer('Monica','B',37),
151 ]
152 print(sorted(customers,key=attrgetter('name')))
153 # [Customer('Irene','C',8), Customer('Justin','A',40), Customer('Monica','B',37)]
154 print(sorted(customers,key=attrgetter('symbol')))
155 # [Customer('Justin','A',40), Customer('Monica','B',37), Customer('Irene','C',8)]
156 print(sorted(customers,key=attrgetter('age')))
157 # [Customer('Irene','C',8), Customer('Monica','B',37), Customer('Justin','A',40)]