请问类的实例可以作为字典的key吗?

请问类的实例可以作为字典的key吗?

写了一个类,实例化之后作为一个dic的key,但是出现 TypeError: unhashable instance。
我记得看过Learning Python中说过,甚至类的实例也可以作为字典的键,请问有什么特殊要求吗?
The object must be immutable
"And class instance objects (discussed in Part VI) can be used as keys too, as long as they have the proper protocol methods;roughly, they need to tell Python that their values won't change, or else they would be useless as fixed keys."
上面是Learning Python中说的,请问怎么告诉python我这个类的实例是不变的呢?
我试了一下没有问题。你的代码是什么,可能是别的错误。

>;>;>; class A:
...     pass
   
>;>;>; a=A()
>;>;>; b={a:1}
>;>;>; b[a]
1
你试着定义一个__init__,然后定义两个成员变量再试试呢?
class ip:
    "A Ip class for finding user's area"
    def __init__(self, low_ip, up_ip):
            self.low_ip = low_ip
            self.up_ip = up_ip
#   def printip(self):
#       print "Low: %d; Up: %d" % (self.low_ip,self.up_ip)
    def __cmp__(self,ip):
        if( ip>;=low_ip and ip<=up_ip ):
            return 0
        elif( ip<low_ip ):
            return -1
        else: return 1

ip_map[ip(ip1,ip2)] = text
这样是不行的~


QUOTE:
原帖由 "Rcfeng"]p2)] 这样是不行的~[/quote 发表:


不使用内置的__cmp__方法就行了

[Copy to clipboard] [ - ]
CODE:
class ip:
   "A Ip class for finding user's area"
   def __init__(self, low_ip, up_ip):
       self.low_ip = low_ip
       self.up_ip = up_ip
   def __str__(self):
       return "Low: %d; Up: %d" % (self.low_ip,self.up_ip)
   def cmpare(self,ip):
       if( ip>;=low_ip and ip<=up_ip ):
           return 0
       elif( ip<low_ip ):
           return -1
       else: return 1

可能是有了__cmp__就认为是可变的了
Python文档里找到这么一句
[quote]Instances of a class normally compare as non-equal unless the class defines the __cmp__() method.

__cmp__( self, other)

Called by comparison operations if rich comparison (see above) is not defined. Should return a negative integer if self < other, zero if self == other, a positive integer if self >; other. If no __cmp__(), __eq__() or __ne__() operation is defined, class instances are compared by object identity (``address''). See also the description of __hash__() for some important notes on creating objects which support custom comparison operations and are usable as dictionary keys. (Note: the restriction that exceptions are not propagated by __cmp__() has been removed since Python 1.5.)

看了__hash__的介绍,终于明白了

QUOTE:
__hash__( self)

Called for the key object for dictionary operations, and by the built-in function hash(). Should return a 32-bit integer usable as a hash value for dictionary operations. The only required property is that objects which compare equal have the same hash value; it is advised to somehow mix together (e.g., using exclusive or) the hash values for the components of the object that also play a part in comparison of objects. If a class does not define a __cmp__() method it should not define a __hash__() operation either; if it defines __cmp__() or __eq__() but not __hash__(), its instances will not be usable as dictionary keys. If a class defines mutable objects and implements a __cmp__() or __eq__() method, it should not implement __hash__(), since the dictionary implementation requires that a key's hash value is immutable (if the object's hash value changes, it will be in the wrong hash bucket).

If a class does not define a __cmp__() method it should not define a __hash__() operation either; if it defines __cmp__() or __eq__() but not __hash__(), its instances will not be usable as dictionary keys.
我的初衷是想拦截ip_map[ip(ip1,ip2)] = text 这个dic的get方法,让他从完全匹配到,只要在low_ip和up_ip这个范围即匹配,不知道这个实现思想是不是正确呢?请版主指点。
  def __cmp__(self,ip):
       if( ip>;=self.low_ip and ip<=self.up_ip ):
           return 0
       elif( ip<self.low_ip ):
           return -1
       else: return 1

ip_map.get(ip3)
如果ip3在ip1和ip2的范围之内就相当于匹配,去除后面text中的描述
根据文档里的讲解,用__cmp__也可以,再实现__hash__就行了

我随便试了一下

[Copy to clipboard] [ - ]
CODE:
def __hash__(self):
        return hash(self.low_ip + self.up_ip)

是可以的,只是不知道这样hash会不会有问题
你可以这样做

不过要想用dict的话,就得自己实现__hash__方法,保证low_ip和up_ip值都一样的ip的instance其hash值一样,这样就可以做dict的key了

不知道说得对不对,呵呵
真是多谢啦,我试试先~