larken

勤奋的人生才有价值

导航

hashable/iterable与orderable

  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)]

 

posted on 2019-03-21 01:36  larken  阅读(249)  评论(0编辑  收藏  举报