#!/usr/bin/env python
# coding:UTF-8


"""
@version: python3.x
@author:曹新健
@contact: 617349013@qq.com
@software: PyCharm
@file: hashable协议.py
@time: 2018/11/6 13:48
"""

"""
1、一个对象能被称为hashable(可哈希运算的),它必须有个hash值(哈希值),这个值在整个运行时刻均不会变化,
   而且必须可以进行相等比较。具体来说,一个对象能被称为hashable,它必须实现__hash__()与__eq__()方法。
2、可以对一个对象使用hash()获取hash值
3、对于python内建类,创建之后状态就无法变动的类型,它的实例都是hashable,而可变动类型的实例都是
   unhashable类型
4、一个自定义的类创建的实例默认也是hashable的,其__hash__()的实现基本上根据id()计算而来,而__eq__()
   的实现默认使用is来比较,因此两个分别创建的实例hash()值必然不同,而且相等性对比一定不成立。
5、很多时候自定义类默认hashable并不合适,比如自定义坐标实例p1=(1,2,3)和p2=(1,2,3),默认情况下这两个实
   例不相等,实际上代表同一个坐标。所以需要自定义__hash__()与__eq__()方法。
6、当集合判断新加入的对象与已经包含的某个对象hash值相同,而且相等性比较也成立时,就会丢弃已包含的对象,
   并将新的对象加入。
7、集合判断是否重复是在对象加入时,当对象已经在集合中了,我们又用其他方式改变了对象状态,就会造成集合
   数据重复,所以hashable要求对象建议状态不可变动,必要时,加一些存取限制。
8、两个对象若相等性比较成立,那么也必须有相同的hash值,然而hash值相同,两个对象的相等性比较不一定是成
   立的。
"""

class Point:
    def __init__(self,x,y,z):
        self.x = x
        self.y = y
        self.z = z

    def __hash__(self):
        return 100 * self.z + 10 * self.y + self.x

    def __eq__(self, other):
        if hasattr(other,"x") and hasattr(other,"y") and hasattr(other,"z"):
            return self.x == other.x and self.y == other.y and self.z == other.z
        return False

    def __str__(self):
        return "Point({x},{y},{z})".format(**vars(self))

    def __repr__(self):
        return self.__str__()

if __name__ == "__main__":
    p1 = Point(1,2,3)
    p2 = Point(3,3,3)
    p3 = Point(1,2,3)
    pset = {p1,p2,p3}
    print(pset)     #打印{Point(1,2,3), Point(3,3,3)}
    p2.x = 1
    p2.y = 2
    print(pset)     #打印{Point(1,2,3), Point(1,2,3)}

 

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐