python - 如何使用结构模式匹配检测可散列类型?

标签 python protocols hashable hasattr structural-pattern-matching

使用结构模式匹配,如何编写匹配可散列类型实例的案例?

我试过:

for obj in [], (), set(), frozenset(), 10, None, dict():
    match obj:
        case object(__hash__=_):
            print('Hashable type:  ', type(obj))
        case _:
            print('Unhashable type: ', type(obj))

但是,这得到了错误的答案,因为每种类型都定义了 __hash__ 是否可散列:

Hashable type:   <class 'list'>
Hashable type:   <class 'tuple'>
Hashable type:   <class 'set'>
Hashable type:   <class 'frozenset'>
Hashable type:   <class 'int'>
Hashable type:   <class 'NoneType'>
Hashable type:   <class 'dict'>

最佳答案

Raymond Hettinger 的答案在有限的情况下有效,但它在像 list(类型对象本身)这样的输入上失败,即使 list.__hash__ 是 None,它也是可哈希的,和像 ([1, 2], [3, 4]) 这样的输入,即使 tuple.__hash__ 不是 None 也是不可散列的。

检测对象是否可哈希的最可靠方法始终是尝试对其进行哈希处理。如果您想在 match 语句中执行此操作,最简单的方法是编写一个守卫:

def hashable(x):
    try:
        hash(x)
    except TypeError:
        return False
    else:
        return True

match x:
    case _ if hashable(x):
        ...
    ...

这只是直接调用 hash(x) 并查看它是否有效,而不是尝试执行结构检查。

如果需要散列又想避免重复计算,可以保存hash(x)结果:

def try_hash(x):
    try:
        return hash(x)
    except TypeError:
        return None

match x:
    case _ if (x_hash := try_hash(x)) is not None:
        ...
    ...

关于python - 如何使用结构模式匹配检测可散列类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69848884/

相关文章:

swift - 如何跨多个 View Controller 引用同一个类的实例?

swift - swift4中的可散列协议(protocol)有什么用?

python - 将 Pandas DataFrame 转换为字典

python - Pandas .read_excel : Accessing the home directory

java - 带有 XML 消息的客户端服务器协议(protocol)

c - 用于文件传输的选择性重复协议(protocol)

swift - Set 的 contains 方法在不同的时间返回不同的值

python-3.x - 如何使包含 numpy 数组的元组可散列?

python - 如何在通用 View 中为同一请求使用不同的 Django Rest Framework 序列化程序?

python - 在 Python 中创建圆形饼图子图