簡體   English   中英

python 通用類型提示 + 用戶定義的容器 + 限制實現 __add__ 方法的類型

[英]python Generic Type Hints + user-defined container + constraining to Types implementing __add__ method

我想在 python 3.8 中實現一個 Liste 類的 Lisp 方式,頭部和尾部,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 正在抱怨,因為如果您希望ht能夠是None ,則需要使用Optional ,否則,您暗示一切都必須是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)

正如我在評論中所說,這門課非常學術,你可能不應該實際使用它。 這將是低效的。 至少,您不應該對sum使用遞歸。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM