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 检查的主要内容,如果未能解决你的问题,请参考以下文章

如何在python中检查可迭代的isinstance? [复制]

python isinstance函数

python:递归检查以确定字符串是不是为回文

python之面向对象进阶

Python说文解字_杂谈05

python中内建函数isinstance的用法