Python: 递归 isinstance 检查
Python: recursive isinstance checking
如何检查嵌套抽象的完整类型签名 class?在这个例子中
In [4]: from typing import Sequence
In [5]: IntSeq = Sequence[int]
In [6]: isinstance([1], IntSeq)
Out[6]: True
In [7]: isinstance([1.0], IntSeq)
Out[7]: True
我希望最后一个 isinstance
调用实际上是 return False
,而它只检查参数是 Sequence
。我考虑过递归检查类型,但是 IntSeq
没有存储嵌套类型的 public 属性:
In [8]: dir(IntSeq)
Out[8]:
['__abstractmethods__',
'__class__',
'__delattr__',
'__dict__',
'__dir__',
'__doc__',
'__eq__',
'__extra__',
'__format__',
'__ge__',
'__getattribute__',
'__gt__',
'__hash__',
'__init__',
'__le__',
'__len__',
'__lt__',
'__module__',
'__ne__',
'__new__',
'__origin__',
'__parameters__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__slots__',
'__str__',
'__subclasshook__',
'__weakref__',
'_abc_cache',
'_abc_negative_cache',
'_abc_negative_cache_version',
'_abc_registry']
所以获取嵌套类型似乎并不简单。我在文档中找不到相关信息。
P.S。
我需要这个来实现多重调度。
更新
感谢 Alexander Huszagh 和 Blender 的反馈,我们现在知道 Python 3.5(可能)中的抽象 classes 有两个存储嵌套类型的属性:__parameters__
和__args__
。前者在 Linux (Ubuntu) 和 Darwin (OS X) 下都存在,尽管在 Linux 的情况下它是空的。后者仅在 Linux 下可用,并存储类型,如 __parameters__
在 OS X 下所做的那样。这个实现细节增加了混乱。
我看到您正在尝试使用仍然是临时的模块来实现一些东西;如果你这样做,你一定会遇到不断变化的界面。
Blender 注意到 __parameters__
参数保存了类型的参数;直到我相信 3.5.1
之前都是如此。在我最新版本的 Python (3.6.0a4+
) 的 git 克隆中,__parameters__
再次包含一个空元组,__args__
包含参数并且 __origin__
是其 __bases__
属性中的第一个条目:
>>> intSeq = typing.Sequence[int]
>>> intSeq.__args__
(<class 'int'>,)
>>> intSeq.__parameters__
()
>>> intSeq.__origin__
typing.Sequence<+T_co>
因为 3.6
是在输入时,根据我从 PEP 411
的理解,离开临时并进入稳定状态,这是您应该使用的版本来实现您的功能。
如何检查嵌套抽象的完整类型签名 class?在这个例子中
In [4]: from typing import Sequence
In [5]: IntSeq = Sequence[int]
In [6]: isinstance([1], IntSeq)
Out[6]: True
In [7]: isinstance([1.0], IntSeq)
Out[7]: True
我希望最后一个 isinstance
调用实际上是 return False
,而它只检查参数是 Sequence
。我考虑过递归检查类型,但是 IntSeq
没有存储嵌套类型的 public 属性:
In [8]: dir(IntSeq)
Out[8]:
['__abstractmethods__',
'__class__',
'__delattr__',
'__dict__',
'__dir__',
'__doc__',
'__eq__',
'__extra__',
'__format__',
'__ge__',
'__getattribute__',
'__gt__',
'__hash__',
'__init__',
'__le__',
'__len__',
'__lt__',
'__module__',
'__ne__',
'__new__',
'__origin__',
'__parameters__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__slots__',
'__str__',
'__subclasshook__',
'__weakref__',
'_abc_cache',
'_abc_negative_cache',
'_abc_negative_cache_version',
'_abc_registry']
所以获取嵌套类型似乎并不简单。我在文档中找不到相关信息。
P.S。 我需要这个来实现多重调度。
更新
感谢 Alexander Huszagh 和 Blender 的反馈,我们现在知道 Python 3.5(可能)中的抽象 classes 有两个存储嵌套类型的属性:__parameters__
和__args__
。前者在 Linux (Ubuntu) 和 Darwin (OS X) 下都存在,尽管在 Linux 的情况下它是空的。后者仅在 Linux 下可用,并存储类型,如 __parameters__
在 OS X 下所做的那样。这个实现细节增加了混乱。
我看到您正在尝试使用仍然是临时的模块来实现一些东西;如果你这样做,你一定会遇到不断变化的界面。
Blender 注意到 __parameters__
参数保存了类型的参数;直到我相信 3.5.1
之前都是如此。在我最新版本的 Python (3.6.0a4+
) 的 git 克隆中,__parameters__
再次包含一个空元组,__args__
包含参数并且 __origin__
是其 __bases__
属性中的第一个条目:
>>> intSeq = typing.Sequence[int]
>>> intSeq.__args__
(<class 'int'>,)
>>> intSeq.__parameters__
()
>>> intSeq.__origin__
typing.Sequence<+T_co>
因为 3.6
是在输入时,根据我从 PEP 411
的理解,离开临时并进入稳定状态,这是您应该使用的版本来实现您的功能。