【问题标题】:How to judge an object is hashable or unhashable in python? [duplicate]python中如何判断一个对象是hashable还是unhashable? [复制]
【发布时间】:2021-02-02 15:49:21
【问题描述】:

我用这段代码来判断对象在python中是否可以散列:

#hashable
number1 = 1.2 #float
number2 = 5 #int
str1 = '123' #str
tuple1 = (1,2,3) #tuple

# unhashable
list1 = [1,2,3] #list
print(hash(list1)) #TypeError: unhashable type: 'list'
set1 = {1,2,3} #set
print(hash(set1)) #TypeError: unhashable type: 'set'
dict1 = {'a':1,'b':2,'c':3} #dict
print(hash(dict1)) #TypeError: unhashable type: 'dict'

def HashableOrUnhashable(obj):
    '''
    This function will return True or False, the object can be hashed or not be hashed.
    '''
    try:
        hash(obj)
        return True
    except Exception as ex:
        return False


result = HashableOrUnhashable(someObj) #Can be str,int,float,list,tuple,set,dict or others.
if result:
    print('This object can be hashed.')
else:
    print('This object can not be hashed.')

我觉得我在函数HashableOrUnhashable写的不好。

那么应该如何判断一个对象是否可以hash呢?

【问题讨论】:

  • 致电hash 正是您应该检查的方式。 (不要相信那些告诉你使用 collections.abc.Hashabletyping.Hashable 的人 - 在 (1, [2]) 这样的输入上失败。)
  • 嗨,这很有帮助。
  • 我认为你需要给你的函数一个输入参数...
  • 可以,但是输入对象可以是任何东西。
  • @August。这就是为什么它需要一个输入参数。

标签: python


【解决方案1】:

你的函数是正确的。以下是一些一般准则:

  • 不是容器的基本内置类型是可散列的。
  • 不可变容器(如 frozensettuple)在(且仅当)所有它们包含的项目也是可散列的。
  • 用户定义的类通常是可散列的。
  • 可变的内置容器是不可散列的。

另请参阅Python glossary

【讨论】:

  • 这很有帮助。
【解决方案2】:

Hashable in Python 表示对象可以被哈希 && 两个对象的相同哈希值表示两个对象相等。

这里是一个用户定义的类,它通过重写 hash dunder 方法被故意调整。 现在这个类的对象返回相同的名称,即使它们的 id 不同。

class A:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __hash__(self):
        return id(self)

    def __eq__(self, b):
        return self.name == b.name

if __name__ == '__main__':
    a = A('testuser', 30)
    print(f'hash is: {hash(a)}')
    print(id(a))
    b = A('testuser', 40)
    print(f'hash is: {hash(b)}')
    print(id(b))
    print (a==b)

此类对象将为您返回一个哈希对象,因为 x==y 即使 hash(x)!=hash(y) 也是不可哈希的

因此,请查看您的对象类定义,以确保它们是可散列的。

如果它们不覆盖 hash 和 eq dunder 方法,它们是可散列的。

【讨论】:

  • 我同意文档说明了您所说的内容,但我认为人们可能会想到特殊情况,您可能希望在保持更细粒度的等价/等价关系的同时保持更多对最终身份的严格定义反映在散列中。例如您可能拥有与比较无关的元数据,但您可能希望在键控方面唯一地保留这些元数据。这似乎并不是一个严格的规则,例如“在创建对象后不要更改哈希值”,似乎更像是使用“需求”一词的建议。只是我的看法。
  • 我希望 OP 正在寻找一种纯粹的编程方式来确定哈希性。因此,虽然我明白你在说什么,并且我同意,但我认为你所说的不适用于这个问题。我认为 OP 只需要假设任何“可以散列”的对象也是“正确可散列的”,如果这对他们很重要的话。
  • 我向OP询问了用例,但似乎问题出在老板身上,没有明确的指示。所以我想告知,当涉及到用户定义的类时,默认情况下行为是可散列的(不要覆盖任何东西并获得可散列的类对象作为回报)但应该小心,以免以后被烧毁。
  • @MattMiguel 如果a == b 不暗示hash(a) == hash(b) 那么您可能会遇到难以重现的别名错误,具体取决于字典查找的具体实现。我想说文档在这里使用“必需”这个词是有充分理由的。
猜你喜欢
  • 2011-11-28
  • 1970-01-01
  • 1970-01-01
  • 2018-09-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-01
相关资源
最近更新 更多