如何在Python 3中判断变量是否为类或可用于isinstance的类型
如何判断变量是否可安全用于isinstance的第二个参数
问题背景
我不是Python专家,现在遇到个问题:需要判断一个变量是否适合作为类或类型,能安全地用在isinstance(my_object_instance, supposedly_the_expected_class_or_type)中。
比如合法的使用场景:
$ python3 Python 3.12.9 (main, Feb 21 2025, 21:28:59) [GCC 12.4.0] on cygwin >>> from typing import Sequence >>> my_object_instance = (1, 2) >>> supposedly_the_expected_class_or_type = Sequence >>> print(isinstance(my_object_instance, supposedly_the_expected_class_or_type)) True
要避免的错误场景:
>>> from typing import Sequence >>> my_object_instance = (1, 2) >>> supposedly_the_expected_class_or_type = "Sequence" >>> print(isinstance(my_object_instance, supposedly_the_expected_class_or_type)) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: isinstance() arg 2 must be a type, a tuple of types, or a union
直接用isinstance(Sequence, type)检测无效,返回False;用typing._SpecialGenericAlias检测又依赖非公开内部API,不符合标准。我需要一个标准的is_class_or_type函数,当参数是类/类型时返回True,否则返回False,用于如下场景:
def get_forced_type_value(value_elem: tuple, expected_value_class_or_type): my_type: str = get_type(value_elem) my_value = get_value(value_elem) my_assert(is_class_or_type(expected_value_class_or_type), \ f'Expected a type in: value_elem_type = "{expected_value_class_or_type}"') my_assert(isinstance(my_value, expected_value_class_or_type), \ f'Value not of expected type: "{expected_value_class_or_type}", for value_elem: "{value_elem}"') my_assert(expected_value_class_or_type.__name__ == my_type, \ f'''The expected type name: "{expected_value_class_or_type.__name__}" did not coincide with the value_elem type: "{value_elem}"''') return my_value
解决方案
最稳妥且符合Python标准的实现方式,是复用isinstance本身的校验逻辑——如果参数不合法,它会抛出TypeError。我们可以封装一个函数,通过捕获异常判断合法性:
def is_class_or_type(obj): try: # 用任意对象(比如None)测试isinstance调用是否合法 isinstance(None, obj) return True except TypeError: return False
验证示例
测试各种合法与非法输入:
>>> from typing import Sequence, List >>> is_class_or_type(int) True >>> is_class_or_type(Sequence) True >>> is_class_or_type(List[int]) True >>> is_class_or_type((int, str)) # 支持类型元组 True >>> is_class_or_type("Sequence") False >>> is_class_or_type(123) False
原理说明
Python官方定义中,isinstance的第二个参数允许以下类型:
- 原生类/类型(比如
int、str) typing模块的抽象类型(比如Sequence、Mapping)- 泛型类型(比如
List[int]) - 上述类型组成的元组
- 类型联合(比如
Union[int, str],Python 3.10+可用int | str)
通过尝试调用isinstance(None, obj),我们直接复用了Python内置的校验逻辑,无需依赖任何非公开API,完全符合标准。
内容的提问来源于stack exchange,提问作者Francisco Javier Rojas
相关产品推荐
相关产品推荐

