如何使用 python 的结构模式匹配来测试内置类型?

How to use python's Structural Pattern Matching to test built in types?

我正在尝试使用 SPM 来确定某个 类型 int 还是 str

以下代码:

from typing import Type

def main(type_to_match: Type):
    match type_to_match:
        case str():
            print("This is a String")
        case int():
            print("This is an Int")
        case _:
            print("\nhttps://en.meming.world/images/en/0/03/I%27ve_Never_Met_This_Man_In_My_Life.jpg")

if __name__ == "__main__":
    test_type = str
    main(test_type)

returns https://en.meming.world/images/en/0/03/I%27ve_Never_Met_This_Man_In_My_Life.jpg

我找到的大部分文档都在讨论如何测试某个变量是否是某个类型的实例。但不是如何测试一个类型是否属于某种类型。

关于如何让它发挥作用有什么想法吗?

如果你只是直接传递一个类型,它会认为这是一个“名称捕获”而不是“值捕获”。您可以通过导入 builtins 模块并使用点分符号检查类型来强制它使用值捕获。

import builtins
from typing import Type


def main(type_: Type):
    match (type_):
        case builtins.str:  # it works with the dotted notation
            print(f"{type_} is a String")
        case builtins.int:
            print(f"{type_} is an Int")
        case _:
            print("\nhttps://en.meming.world/images/en/0/03/I%27ve_Never_Met_This_Man_In_My_Life.jpg")

if __name__ == "__main__":
    main(type("hello"))  # <class 'str'> is a String
    main(str)  # <class 'str'> is a String
    main(type(42))  # <class 'int'> is an Int
    main(int)  # <class 'int'> is an Int

顾名思义,结构模式匹配更适合匹配模式,而不是值(就像其他语言中的经典switch/case)。例如,它使得检查列表或字典的不同可能结构变得非常容易,但是对于值,与简单的 if/else 结构相比并没有太多优势:

if type_to_match == str:
    print("This is a String")
elif type_to_match == int:
    print("This is an Int")
else:
    print("\nhttps://en.meming.world/images/en/0/03/I%27ve_Never_Met_This_Man_In_My_Life.jpg")

但如果你真的想使用 SPM,你可以使用 the guard feature along with issublcass 来检查一个类型是否是任何其他类型的子类型:

match type_to_match:
    case s if issubclass(type_to_match, str):
        print(f"{s} - This is a String")
    case n if issubclass(type_to_match, int):
        print(f"{n} - This is an Int")
    case _:
        print("\nhttps://en.meming.world/images/en/0/03/I%27ve_Never_Met_This_Man_In_My_Life.jpg")