Python:递归 isinstance 检查
Posted
技术标签:
【中文标题】Python:递归 isinstance 检查【英文标题】:Python: recursive isinstance checking 【发布时间】:2016-12-29 13:10:23 【问题描述】:如何检查嵌套抽象类的完整类型签名?在这个例子中
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
调用实际返回False
,而它只检查参数是否为Sequence
。我想过递归检查类型,但IntSeq
没有存储嵌套类型的公共属性:
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']
因此,获得嵌套类型似乎并不容易。我在文档中找不到相关信息。
附: 我需要这个来实现多分派。
更新
感谢 Alexander Huszagh 和 Blender 的反馈,我们现在知道 Python 3.5 中的抽象类(可能)有两个存储嵌套类型的属性:__parameters__
和 __args__
。前者在 Linux (Ubuntu) 和 Darwin (OS X) 下都存在,但在 Linux 的情况下它是空的。后者仅在 Linux 下可用,并存储像 __parameters__
在 OS X 下所做的类型。这种实现细节增加了混乱。
【问题讨论】:
我希望接近投票者解释他的选择“有太多可能的答案,或者对于这种格式,好的答案太长了。请添加详细信息以缩小答案集或隔离一个可以在几段中回答的问题”。isinstance(["hello"], int_seq)
也是True
。您确定在尝试使用打字而不是简单的类型检查时,您不会产生比解决更大的问题吗?
@DmitryTorba 我正在尝试在 Python 中实现真正的多重分派,因此我需要分派器能够检查完整的类型签名。
@blender 帮我找到了找到序列类型的答案:Sequence[int].__args__
。 Sequence[int].__parameters__
似乎是特定于实现的。您可以将他现在删除的答案应用到相同的工作流程中。
你可能会发现这个模块很有用:github.com/fabiommendes/pygeneric
【参考方案1】:
我看到您正在尝试使用仍然是临时的模块来实现某些东西;如果你这样做,你一定会遇到一个不断变化的界面。
Blender 注意到 __parameters__
参数保存了类型的参数;这是真的,直到我相信3.5.1
。在我最新版本 Python (3.6.0a4+
) 的 git clone 中,__parameters__
再次持有一个空元组,__args__
持有参数,__origin__
是其__bases__
属性中的第一个条目:
>>> intSeq = typing.Sequence[int]
>>> intSeq.__args__
(<class 'int'>,)
>>> intSeq.__parameters__
()
>>> intSeq.__origin__
typing.Sequence<+T_co>
由于3.6
是在键入时,根据我从PEP 411
的理解,离开临时并进入稳定状态,这是您应该使用的版本来实现您的功能。
【讨论】:
感谢您的澄清。我在 PEP 411 中没有找到对typing
的引用。你知道 +T_co
在 __origin__
属性中的含义吗?
是的,PEP 411 不会谈论哪些模块是临时的,这是在 PEP 0484 的摘要中介绍了该模块:-)。 +T_co
表示参数是协变的,您可以在同一 PEP 中阅读更多相关信息(covariance and contravariance 部分)。以上是关于Python:递归 isinstance 检查的主要内容,如果未能解决你的问题,请参考以下文章