Pthon魔术方法(Magic Methods)-hash
作者:尹正杰
版权声明:原创作品,谢绝转载!否则将追究法律责任。
一.hash方法
__hash__:
内建函数hash()调用的返回值,返回一个整数。如果定义这个方法该类的实例就可hash。
__eq__:
对应"=="操作符,判断两个对象内容是否相等,返回bool值。
定义了这个方法,如果不提供"__hash__"方法,那么实例将不可hash了。
"__hash__"方法只是返回一个hash值作为set的key,但是去重还需要"__eq__"来判断两个对象是否相等。
hash值相同,只是hash冲突,不能说明两个对象是相等的。因此一半来说提供"__hash__"方法是为了作为set或者dict的key,如果去重同时要提供"__eq__"方法。
温馨提示:
不可hash对象isinstance(p1,collections.Hashable)一定为False。
去重需要提供"__eq__"方法。
二.案例展示
1 #!/usr/bin/env python 2 #_*_conding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie 5 6 """ 7 设计二维坐标类Point,使其成为可hash类型,并比较2个坐标的实例是否相等。 8 """ 9 10 from collections import Hashable 11 12 class Point: 13 def __init__(self,x,y): 14 self.x = x 15 self.y = y 16 17 def __hash__(self): 18 return hash((self.x,self.y)) 19 20 def __eq__(self, other): 21 if self is other: 22 return True 23 else: 24 return self.x == other.x and self.y == other.y 25 26 def __repr__(self): 27 return "{}:{}".format(self.x,self.y) 28 29 p1 = Point(10,20) 30 p2 = Point(10,20) 31 32 print(hash(p1)) 33 print(hash(p2)) 34 35 print(p1 is p2) 36 print(p1 == p2) 37 print(hex(id(p1)),hex(id(p2))) 38 print(set((p1,p2))) 39 print(isinstance(p1,Hashable)) 40 41 42 43 #以上代码执行结果如下: 44 3713074054217192181 45 3713074054217192181 46 False 47 True 48 0x137152b7888 0x137152b9348 49 {10:20} 50 True
三.小时牛刀
1>.list类实例为什么不可hash?
1 class list(object): 2 """ 3 Built-in mutable sequence. 4 5 If no argument is given, the constructor creates a new empty list. 6 The argument must be an iterable if specified. 7 """ 8 def append(self, *args, **kwargs): # real signature unknown 9 """ Append object to the end of the list. """ 10 pass 11 12 def clear(self, *args, **kwargs): # real signature unknown 13 """ Remove all items from list. """ 14 pass 15 16 def copy(self, *args, **kwargs): # real signature unknown 17 """ Return a shallow copy of the list. """ 18 pass 19 20 def count(self, *args, **kwargs): # real signature unknown 21 """ Return number of occurrences of value. """ 22 pass 23 24 def extend(self, *args, **kwargs): # real signature unknown 25 """ Extend list by appending elements from the iterable. """ 26 pass 27 28 def index(self, *args, **kwargs): # real signature unknown 29 """ 30 Return first index of value. 31 32 Raises ValueError if the value is not present. 33 """ 34 pass 35 36 def insert(self, *args, **kwargs): # real signature unknown 37 """ Insert object before index. """ 38 pass 39 40 def pop(self, *args, **kwargs): # real signature unknown 41 """ 42 Remove and return item at index (default last). 43 44 Raises IndexError if list is empty or index is out of range. 45 """ 46 pass 47 48 def remove(self, *args, **kwargs): # real signature unknown 49 """ 50 Remove first occurrence of value. 51 52 Raises ValueError if the value is not present. 53 """ 54 pass 55 56 def reverse(self, *args, **kwargs): # real signature unknown 57 """ Reverse *IN PLACE*. """ 58 pass 59 60 def sort(self, *args, **kwargs): # real signature unknown 61 """ Stable sort *IN PLACE*. """ 62 pass 63 64 def __add__(self, *args, **kwargs): # real signature unknown 65 """ Return self+value. """ 66 pass 67 68 def __contains__(self, *args, **kwargs): # real signature unknown 69 """ Return key in self. """ 70 pass 71 72 def __delitem__(self, *args, **kwargs): # real signature unknown 73 """ Delete self[key]. """ 74 pass 75 76 def __eq__(self, *args, **kwargs): # real signature unknown 77 """ Return self==value. """ 78 pass 79 80 def __getattribute__(self, *args, **kwargs): # real signature unknown 81 """ Return getattr(self, name). """ 82 pass 83 84 def __getitem__(self, y): # real signature unknown; restored from __doc__ 85 """ x.__getitem__(y) <==> x[y] """ 86 pass 87 88 def __ge__(self, *args, **kwargs): # real signature unknown 89 """ Return self>=value. """ 90 pass 91 92 def __gt__(self, *args, **kwargs): # real signature unknown 93 """ Return self>value. """ 94 pass 95 96 def __iadd__(self, *args, **kwargs): # real signature unknown 97 """ Implement self+=value. """ 98 pass 99 100 def __imul__(self, *args, **kwargs): # real signature unknown 101 """ Implement self*=value. """ 102 pass 103 104 def __init__(self, seq=()): # known special case of list.__init__ 105 """ 106 Built-in mutable sequence. 107 108 If no argument is given, the constructor creates a new empty list. 109 The argument must be an iterable if specified. 110 # (copied from class doc) 111 """ 112 pass 113 114 def __iter__(self, *args, **kwargs): # real signature unknown 115 """ Implement iter(self). """ 116 pass 117 118 def __len__(self, *args, **kwargs): # real signature unknown 119 """ Return len(self). """ 120 pass 121 122 def __le__(self, *args, **kwargs): # real signature unknown 123 """ Return self<=value. """ 124 pass 125 126 def __lt__(self, *args, **kwargs): # real signature unknown 127 """ Return self<value. """ 128 pass 129 130 def __mul__(self, *args, **kwargs): # real signature unknown 131 """ Return self*value. """ 132 pass 133 134 @staticmethod # known case of __new__ 135 def __new__(*args, **kwargs): # real signature unknown 136 """ Create and return a new object. See help(type) for accurate signature. """ 137 pass 138 139 def __ne__(self, *args, **kwargs): # real signature unknown 140 """ Return self!=value. """ 141 pass 142 143 def __repr__(self, *args, **kwargs): # real signature unknown 144 """ Return repr(self). """ 145 pass 146 147 def __reversed__(self, *args, **kwargs): # real signature unknown 148 """ Return a reverse iterator over the list. """ 149 pass 150 151 def __rmul__(self, *args, **kwargs): # real signature unknown 152 """ Return value*self. """ 153 pass 154 155 def __setitem__(self, *args, **kwargs): # real signature unknown 156 """ Set self[key] to value. """ 157 pass 158 159 def __sizeof__(self, *args, **kwargs): # real signature unknown 160 """ Return the size of the list in memory, in bytes. """ 161 pass 162 163 __hash__ = None
2>.functools.lru_cache使用到的functools.HashedSeq类继承自list,为什么可hash?
1 class _HashedSeq(list): 2 """ This class guarantees that hash() will be called no more than once 3 per element. This is important because the lru_cache() will hash 4 the key multiple times on a cache miss. 5 6 """ 7 8 __slots__ = 'hashvalue' 9 10 def __init__(self, tup, hash=hash): 11 self[:] = tup 12 self.hashvalue = hash(tup) 13 14 def __hash__(self): 15 return self.hashvalue