[英]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 正在抱怨,因為如果您希望h
或t
能夠是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.