python中字典的key要求

前记
    python中什么对象不能作为字典的key:有__hash__方法可以做字典的key,没有则不能作为字典的key;
    除了list、dict、set和内部至少带有上述三种类型之一的tuple之外,其余对象均可作为字典的key;


一、list做key示例:
    a = [1,2,3]
    d = {a:a}

    报错:
    TypeError: unhashable type: 'list'
    报错信息,list类型不可哈希;

    查看源码object对象定义了__hash__方法,list、set、dict把__hash__赋值为None;
    通过help(list/set/dict)也可看到__hash__赋值为None;
    # 部分源码
 
    class object:
        """ The most base type """
     
        def __hash__(self, *args, **kwargs):  # real signature unknown
            """ Return hash(self). """
            pass
     
    class list(object):
        __hash__ = None
     
    class set(object):
        __hash__ = None
     
    class dict(object):
        __hash__ = None


二、实验
    修改__hash__方法;
    class Mylist(list):
    def __hash__(self):
        return hash(self[0])

    l1=Mylist([1,2])
    d={l1:"can?"}
    print(d)
    l1.append(3)
    print(d)
    print(d[l1])
    输出:
    {[1, 2]: 'can?'}
    {[1, 2, 3]: 'can?'}
    can?

    结论:一个对象是否可以作为字典的key,取决于其有没有__hash__方法。所以python自带类型中,除了list/set/dict和内部带有以上三种类型的tuple之外,其余对象都可以作为字典的key;


三、0号元素的hash值为1,用相同hash值的对象赋值;
    class Mylist(list):
    def __hash__(self):
        print("hash(self(0)) = ",hash(self[0]))
        return hash(self[0])

    l1 = Mylist([1,2])
    d = {}
    d[l1] = l1
    print(d)
    d[1] = 1
    print(d)
    输出:
    hash(self(0)) =  1
    {[1, 2]: [1, 2]}
    {[1, 2]: [1, 2], 1: 1}

    结论:没有修改而是新增一个键值对,而hash(self[0])是1,重写__eq__方法;
    class Mylist(list):
    def __hash__(self):
        print("hash(self(0)) = ",hash(self[0]))
        return hash(self[0])

    def __eq__(self,other):
        return self[0] == other

    l1 = Mylist([1,2])
    d = {}
    d[l1] = l1
    print(d)
    d[1] = 1
    print(d)
    输出:
    {[1, 2]: [1, 2]}
    {[1, 2]: 1}

    结论:__hash__返回值相等,且__eq__判断也相等,才认为是同一键。先后顺序?

    class Mylist(list):
    def __hash__(self):
        print("hash(self(0)) = ",hash(self[0]))
        print("hash running.")
        return hash(self[0])

    def __eq__(self,other):
        print("eq running.")
        return self[0] == other

    l1 = Mylist([1,2])
    d = {}
    d[1] = 1
    print(d)
    d[l1] = l1
    print(d)
    输出:
    {1: 1}
    hash(self(0)) =  1
    hash running.
    eq running.
    {1: [1, 2]}

    结论:__hash__先执行,找到对应的内存,没有值直接写入;有值,判断新来的键和原来的键是否相等,相等则认为是一个键,更新值,不相等开辟空间,自增键值对。

 

注:如有错误,请指正! 

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值