Python 中大小可迭代的类型提示 [英] Typehints for Sized Iterable in Python

查看:50
本文介绍了Python 中大小可迭代的类型提示的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个函数,它在其中一个参数上使用 len 函数并迭代该参数.现在我可以选择是使用 Iterable 还是使用 Sized 来注释类型,但两者都会在 mypy 中给出错误.

from 输入 import Sized, Iterabledef foo(some_thing: Iterable):打印(len(some_thing))参与 some_thing:打印(部分)

给予

error: Argument 1 to "len" 有不兼容的类型 "Iterable[Any]";预期的大小"

虽然

def foo(some_thing: Sized):...

给予

错误:预期可迭代错误:大小"没有属性__iter__"

因为没有这个问题Intersection> 我需要某种混合课程.

from abc import ABCMeta从输入导入大小,可迭代class SizedIterable(Sized, Iterable[str], metaclass=ABCMeta):经过def foo(some_thing: SizedIterable):打印(len(some_thing))参与 some_thing:打印(部分)foo(['a', 'b', 'c'])

这在将 foolist 一起使用时会出错.

错误:foo"的参数 1 具有不兼容的类型List[str]";预期的SizedIterable"

这并不奇怪,因为:

<预><代码>>>>SizedIterable.__subclasscheck__(list)错误的

所以我定义了一个 __subclasshook__(见 文档).

class SizedIterable(Sized, Iterable[str], metaclass=ABCMeta):@类方法def __subclasshook__(cls, subclass):返回 Sized.__subclasscheck__(subclass) 和 Iterable.__subclasscheck__(subclass)

然后子类检查工作:

<预><代码>>>>SizedIterable.__subclasscheck__(list)真的

但是 mypy 仍然抱怨我的 list.

错误:foo"的参数 1 具有不兼容的类型List[str]";预期的SizedIterable"

在同时使用 len 函数和迭代我的参数时如何使用类型提示?我认为转换 foo(cast(SizedIterable, ['a', 'b', 'c'])) 不是一个好的解决方案.

解决方案

从 Python3.6 开始,有一个名为 Collection 的新类型.请参阅此处.

I have a function that uses the len function on one of it's parameters and iterates over the parameter. Now I can choose whether to annotate the type with Iterable or with Sized, but both gives errors in mypy.

from typing import Sized, Iterable


def foo(some_thing: Iterable):
    print(len(some_thing))
    for part in some_thing:
        print(part)

Gives

error: Argument 1 to "len" has incompatible type "Iterable[Any]"; expected "Sized"

While

def foo(some_thing: Sized):
...

Gives

error: Iterable expected
error: "Sized" has no attribute "__iter__"

Since there is no Intersection as discussed in this issue I need to have some kind of mixed class.

from abc import ABCMeta
from typing import Sized, Iterable


class SizedIterable(Sized, Iterable[str], metaclass=ABCMeta):
    pass


def foo(some_thing: SizedIterable):
    print(len(some_thing))
    for part in some_thing:
        print(part)


foo(['a', 'b', 'c'])

This gives an error when using foo with a list.

error: Argument 1 to "foo" has incompatible type "List[str]"; expected "SizedIterable"

This is not too surprising since:

>>> SizedIterable.__subclasscheck__(list)
False

So I defined a __subclasshook__ (see docs).

class SizedIterable(Sized, Iterable[str], metaclass=ABCMeta):

    @classmethod
    def __subclasshook__(cls, subclass):
        return Sized.__subclasscheck__(subclass) and Iterable.__subclasscheck__(subclass)

Then the subclass check works:

>>> SizedIterable.__subclasscheck__(list)
True

But mypy still complains about my list.

error: Argument 1 to "foo" has incompatible type "List[str]"; expected "SizedIterable"

How can I use type hints when using both the len function and iterate over my parameter? I think casting foo(cast(SizedIterable, ['a', 'b', 'c'])) is not a good solution.

解决方案

Starting from Python3.6 there's a new type called Collection. See here.

这篇关于Python 中大小可迭代的类型提示的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆