python 通用类型提示 + 用户定义的容器 + 约束实现 __add__ 方法的类型

标签 python type-hinting abstract-data-type generic-type-argument

我想在 python 3.8 中以 Lisp 方式实现一个 Liste 类,其中包含 head 和 tail、car()、cdr() 和 nil。我想定义一个通用类型,接受 Liste 中类型 T 的对象。

from __future__ import annotations
from typing import TypeVar, Callable, Generic

T = TypeVar('T')
class Liste(Generic[T]):

    def __init__(self, h: T, t: Liste[T]) -> None:
        self.head = h
        self.tail = t

    @staticmethod
    def nil() -> Liste[T]:
        return Liste(None, None)

    def est_vide(self) -> bool:
        return (self.head is None) and (self.tail is None)
    def cdr(self)->Liste[T]:
        if self.tail is None: return Liste.nil()
        else: return  self.tail

    def sum(self)->T:
        if self.est_vide():
            return 0
        else:
            return self.head + self.cdr().sum()

我一直在类型提示方面度过了一段非常愉快的时光。但是mypy点了4个错误

liste_sof.py:13: error: Argument 1 to "Liste" has incompatible type "None"; expected "T"
liste_sof.py:13: error: Argument 2 to "Liste" has incompatible type "None"; expected "Liste[T]"
liste_sof.py:23: error: Incompatible return value type (got "int", expected "T")
liste_sof.py:25: error: Unsupported left operand type for + ("T")
Found 4 errors in 1 file (checked 1 source file)

问题 1 是能够指定我期望实现 __add__ 方法的 T 对象。我不知道该怎么做。

问题 2 是处理我的类中特殊的 Liste.nil() 空对象。

最佳答案

Mypy 正在提示,因为您需要使用 Optional如果你想要ht能够成为None ,否则,您是在暗示一切都必须是 None ,这不是通用的。

您可以使用 Protocol 的结构类型表达“有__add__”。

最后,没有干净的方法来获取“空对象”。对于内置类型,type(self)()可能可行,但老实说,我只是强制 API 采用初始值。

from __future__ import annotations
from typing import TypeVar, Callable, Generic, Protocol, Optional


T = TypeVar('T')

class SupportsAdd(Protocol[T]):
    def __add__(self: T, other: T) -> T:
        ...

A = TypeVar('A', bound=SupportsAdd)

class Liste(Generic[A]):
    def __init__(self, h: Optional[A], t: Optional[Liste[A]]) -> None:
        self.head = h
        self.tail = t

    @staticmethod
    def nil() -> Liste[A]:
        return Liste(None, None)

    def est_vide(self) -> bool:
        return (self.head is None) and (self.tail is None)

    def cdr(self)->Liste[A]:
        if self.tail is None: return Liste.nil()
        else: return  self.tail

    def sum(self, init: A) -> A:
        if self.head is None or self.tail is None:
            return init
        else:
            return self.head + self.cdr().sum(init)

正如我在评论中所说,这个类(class)非常学术化,你可能不应该实际使用它。这将是低效的。至少,您不应该对 sum 使用递归。 .

关于python 通用类型提示 + 用户定义的容器 + 约束实现 __add__ 方法的类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64141153/

相关文章:

python - 没有名为 'openai_secret_manager' 的模块

python - 从 numpy ndarray 中提取字典项

php - 声明类型提示时,PhpStorm是否允许跳过PHPDoc标记?

Python:未知类型提示不会因 __future__ import 引发异常

c - ADT、void 指针和 int - C 中几乎没有相关警告的问题

c++ - 不允许重复的功能? (C++)

python - 如何动态添加选项到optparse?

python - 从字典列表中获取最接近的元素

具有 "@"(矩阵乘法)的对象的 Python 类型提示

c - 如何使用 void* 数组作为数据结构将元素插入堆栈?