具有长度的对象的类型

drh*_*gen 7 python types

如何输入提示参数或isinstance检查必须可迭代且可使用的对象len?我假设几乎所有具有长度的对象都是可迭代的,所以这实际上是关于什么类型(如果有的话)代表实现__len__.

def n_and_list(x: ???):
    return len(x), [y for y in x]
Run Code Online (Sandbox Code Playgroud)

事实并非如此typing.Iterablecollections.Iterable因为对于没有长度的事物来说,这些都是正确的,例如zip.

In [1]: from typing import Iterable

In [2]: isinstance(zip([]), Iterable)
Out[3]: True

In [3]: from collections import Iterable

In [4]: isinstance(zip([]), Iterable)
Out[4]: True

In [5]: len(zip([]))
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-27-86d411a5426c> in <module>()
----> 1 len(zip([]))

TypeError: object of type 'zip' has no len()
Run Code Online (Sandbox Code Playgroud)

它不是typing.Sequenceor collections.Sequence,因为对于有长度的东西来说,这些是错误的,比如字典键和 numpy 数组。

In [6]: from typing import Sequence

In [7]: isinstance({}.keys(), Sequence)
Out[7]: False

In [8]: from numpy import asarray

In [9]: isinstance(asarray([]), Sequence)
Out[9]: False

In [10]: from collections import Sequence

In [11]: isinstance({}.keys(), Sequence)
Out[11]: False

In [12]: from numpy import asarray

In [13]: isinstance(asarray([]), Sequence)
Out[13]: False
Run Code Online (Sandbox Code Playgroud)

不是iterable,或者iter因为那些不是类型。事实并非如此list,或者tuple因为这些范围太窄了。

zwe*_*wer 4

为此collections.Sized

def n_and_list(x: collections.Sized):
    return len(x), [y for y in x]
Run Code Online (Sandbox Code Playgroud)

或者对于您的情况,因为您希望它具有__len__并且可迭代:

import typing
import collections

def n_and_list(x: typing.Union[collections.Sized, collections.Iterable]):
    return len(x), [y for y in x]
Run Code Online (Sandbox Code Playgroud)

遗憾的是,正如下面的评论所提到的,typing.Intersection目前还不能保证两者都存在。

  • `typing.Union` 是“或”,而不是“和”。 (3认同)