简体   繁体   English

Python:递归isinstance检查

[英]Python: recursive isinstance checking

How can one check a complete type signature of a nested abstract class? 如何检查嵌套抽象类的完整类型签名? In this example 在这个例子中

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

I want the last isinstance call to actually return False , while it only checks that the argument is a Sequence . 我希望最后一个isinstance调用实际返回False ,而它只检查参数是否为Sequence I thought about recursively checking the types, but IntSeq has no public attributes that store the nested type(s): 我想过以递归方式检查类型,但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']

So it doesn't seem to be straightforward to get nested types. 因此,获取嵌套类型似乎并不简单。 I can't find relevant information in the docs. 我在文档中找不到相关信息。

PS I need this for a multiple dispatch implementation. PS我需要这个用于多个调度实现。

Update 更新

Thanks to the feedback from Alexander Huszagh and Blender we now know that abstract classes in Python 3.5 (might) have two attributes that store the nested types: __parameters__ and __args__ . 感谢Alexander Huszagh和Blender的反馈,我们现在知道Python 3.5中的抽象类(可能)有两个存储嵌套类型的属性: __parameters____args__ The former is there under both Linux (Ubuntu) and Darwin (OS X), though it is empty in case of Linux. 前者存在于Linux(Ubuntu)和Darwin(OS X)之下,但在Linux的情况下它是空的。 The later is only available under Linux and stores the types like __parameters__ does under OS X. This implementation details add up to the confusion. 后者仅在Linux下可用,并且在OS X下存储像__parameters__这样的类型。这种实现细节加起来很混乱。

I see you're trying to implement something using a module that is still provisional; 我看到你正在尝试使用仍然是临时的模块来实现某些功能; you're bound to encounter a changing interface if you do this. 如果你这样做,你将遇到一个不断变化的界面。

Blender noticed that the __parameters__ argument holds the parameters to the type; Blender注意到__parameters__参数保存了类型的参数; this was true until, I believe 3.5.1 . 这是真的,直到,我相信3.5.1 In my git clone of the most recent version of Python ( 3.6.0a4+ ) __parameters__ again holds an empty tuple, __args__ holds the argument and __origin__ is the first entry in its __bases__ attribute: 在我最新版本的Python( 3.6.0a4+ )的git克隆中, 3.6.0a4+ __parameters__再次保存一个空元组, __args__保存参数, __origin__是其__bases__属性中的第一个条目:

>>> intSeq = typing.Sequence[int]
>>> intSeq.__args__
(<class 'int'>,)
>>> intSeq.__parameters__
()
>>> intSeq.__origin__
typing.Sequence<+T_co>

Since 3.6 is when typing will, from what I understand from PEP 411 , leave provisional and enter a stable state, this is the version you should be working with to implement your functionality. 因为3.6是打字的时候,根据我从PEP 411理解,保留临时状态并进入稳定状态,这是你应该用来实现你的功能的版本。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM