如何在运行时判断对象是否为Numpy的ArrayLike类型?
如何在运行时判断对象是否为Numpy的ArrayLike类型?
Numpy提供了类型提示ArrayLike,它涵盖了几乎所有可转换为Numpy数组的对象(比如列表、实现__array__方法的对象等),可以像普通类型提示一样使用:
from numpy.typing import ArrayLike def some_func(a : ArrayLike): print(a)
但在运行时想要判断一个对象是否属于ArrayLike类型时,常规的判断方法都不生效:
def some_func(a): if type(a) == ArrayLike: # 无法生效 print(a) if issubclass(a, ArrayLike): # 会抛出错误 print(a) if isinstance(a, ArrayLike): # 会抛出错误 print(a)
那能不能通过ArrayLike实现这种运行时判断?还是应该用其他方法?
最小可复现示例:
import numpy as np from numpy.typing import ArrayLike class MyArrayLike: def __array__(self, dtype = None): return np.asarray([0, 1]) def some_func(a : ArrayLike): if type(a) == ArrayLike: print(a) # if issubclass(a, ArrayLike): # print(a) # if isinstance(a, ArrayLike): # print(a) a = MyArrayLike() some_func(a)
解答
首先要明确:ArrayLike是仅用于静态类型检查的类型提示,它本质是一个类型别名,不是运行时可直接用于判断的实体类型,所以直接用type()、issubclass()、isinstance()都会失效或报错。
想要在运行时判断一个对象是否可转换为Numpy数组(即符合ArrayLike的定义),推荐以下两种方法:
方法一:用numpy.asarray()尝试转换并捕获异常
这是最稳妥的方式,因为ArrayLike的核心定义就是"可被转换为Numpy数组的对象",直接尝试转换即可验证:
import numpy as np def is_array_like(obj): try: np.asarray(obj) return True except (TypeError, ValueError): return False
测试示例:
class MyArrayLike: def __array__(self, dtype=None): return np.asarray([0, 1]) print(is_array_like([1,2,3])) # True print(is_array_like(MyArrayLike())) # True print(is_array_like("not array like")) # True(字符串会被转为字符数组,若需排除可额外判断) print(is_array_like({"key": "value"})) # False
如果需要排除字符串(有时我们不希望将字符串视为ArrayLike),可修改函数:
def is_array_like(obj): if isinstance(obj, str): return False try: np.asarray(obj) return True except (TypeError, ValueError): return False
方法二:检查对象是否符合ArrayLike的特征
根据Numpy对ArrayLike的定义,它包含:
- 所有Numpy数组类型
- 列表、元组等序列类型
- 实现了
__array__方法的对象 - 标量值
可以手动检查这些特征,但这种方法不如np.asarray()全面,因为Numpy内部可能有更多兼容逻辑:
import numpy as np from collections.abc import Sequence def is_array_like(obj): # 排除字符串 if isinstance(obj, str): return False # 检查是否是numpy数组或标量 if isinstance(obj, (np.ndarray, np.generic)): return True # 检查是否是序列类型或实现了__array__方法 return isinstance(obj, Sequence) or hasattr(obj, "__array__")
内容的提问来源于stack exchange,提问作者502E532E
相关产品推荐
相关产品推荐

