如何解决python通用类型提示+用户定义的容器+限制为实现__add__方法的类型
我想在python 3.8中实现带有头和尾,car(),cdr()和nil的Lisp方式的Liste类。我想在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()
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
或h
成为t
,则需要使用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)
正如我在评论中所述,该课程非常学术,您可能不应该实际使用它。这将是低效的。至少,您不应该对sum
使用递归。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。