Pthon魔术方法(Magic Methods)-hash

              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
class list(object):(源码解析)

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
class _HashedSeq(list):源码解析

 

posted @ 2019-07-21 00:14  尹正杰  阅读(446)  评论(0编辑  收藏  举报