gpt4 book ai didi

python - 将函数参数类型注释为派生自 Python 中的多个抽象基类

转载 作者:行者123 更新时间:2023-12-02 09:59:30 24 4
gpt4 key购买 nike

我正在尝试根据 PEP 484 在 Python 2 中输入注释函数。该函数接受一个容器,该容器应同时实现 __len____iter__。我想要添加此注释的原始代码非常复杂,因此请考虑一个示例函数,该函数返回容器 s 中所有 int 的乘积 if len (s) 为偶数,否则返回 1。

如果我想注释一个只​​需要 __len__ 的容器,我会将其注释为 type: (Sized) -> int。如果我想注释一个只​​需要 __iter__ 的容器,我会将其注释为 type: (Iterable[int]) -> int。但如何在需要两者的地方完美地注释容器呢?

我按照Piotr-Ćwiek尝试了这个的建议:

from __future__ import print_function
from typing import Sized, Iterable

class SizedIterable(Sized, Iterable[int]):
pass

def product2(numbers):
# type: (SizedIterable) -> int
if len(numbers)%2 == 1:
return 1
else:
p = 1
for n in numbers:
p*= n
return p

print(product2([1, 2, 3, 4]))
print(product2({1, 2, 3, 4}))

但是失败并出现以下错误:

prod2.py:17: error: Argument 1 to "product2" has incompatible type List[int]; expected "SizedIterable"
prod2.py:18: error: Argument 1 to "product2" has incompatible type Set[int]; expected "SizedIterable"

最佳答案

在 python 3.6 中,typing.Collection 几乎可以完美地适合您的用例(它也源自 Container,但实际上您想要使用的任何内容都可能有__contains__)。不幸的是,没有针对 python 2 的解决方案。

SizedIterable 不起作用的原因是,通过从 SizedIterable 派生它,您只是告诉 mypy 它是一个子类型这两种类型; mypy 确实断定任何 SizedIterable 子类型的类型也是 SizedIterable 的子类型。

Mypy 的逻辑完全符合逻辑;毕竟,您不希望此代码键入检查:

class A(Sized, Iterable[int]):
def g(self) -> None:
...

def f(x: A) -> None:
a.g()

# passes type check because [1, 2] is Sized and Iterable
# but fails in run-time
f([1, 2])

如果 mypy 仅仅因为类体是空的而以不同的方式对待你的类定义,那就太棘手了。

为了让 mypy 理解您的意图,mypy 需要向其类型系统添加新功能。

目前正在考虑此类功能的两个选项:

  • intersections (正如@PiotrĆwiek 所指出的);您要求的是 IterableSized
  • 的交集
  • structural typing ;这比一般的交集简单得多,但足以满足您的用例,因为您需要的只是让 numbers 参数具有 __len____iter__方法

模仿打字类定义或使用__instancecheck__将不起作用,因为(正如最近有人向我解释的那样)在任何情况下都不会mypy永远运行您编写的代码(即,它永远不会导入您的模块,永远不会调用您的函数等)。这是因为 mypy 是一个静态分析工具,它并不假设运行代码的环境在执行期间可用(例如 python 版本、库等)。

关于python - 将函数参数类型注释为派生自 Python 中的多个抽象基类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37328703/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com