python泛型类型提示+;用户定义的容器+;对实现_添加_方法的类型的约束

python泛型类型提示+;用户定义的容器+;对实现_添加_方法的类型的约束,python,type-hinting,abstract-data-type,generic-type-argument,Python,Type Hinting,Abstract Data Type,Generic Type Argument,我想在Python3.8中实现一个Liste类,它采用Lisp方式,带有head和tail、car()、cdr()和nil。我想在列表中定义一个接受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]

我想在Python3.8中实现一个Liste类,它采用Lisp方式,带有head和tail、car()、cdr()和nil。我想在列表中定义一个接受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是能够指定实现
\uuuuu添加\uuuu
方法的T对象。我不知道怎么做

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


谢谢你的建议。

Mypy抱怨是因为如果你想
h
t
能够
None
,你就需要使用
可选的
,否则,你就意味着一切都必须是
None
,这不是通用的

您可以使用带有
协议的结构化键入来表示“has
\uuuuu add\uuuu

最后,没有干净的方法来获取“空对象”。对于内置类型,
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

使用递归,问题3是找到实现
\uuuuuuuuuuu添加\uuuuuuuu
方法的类t的空对象。对于str,我想要“”,对于int或float,0将是单独的问题。对于
t
h
,您需要使用
可选
,并且您可以使用协议来描述结构类型“supports add”。对于所有支持add的类型,没有干净的方法可以找到“空对象”。因此,您可以对想要支持的类型使用受限typevar,而不是通用协议。老实说,这个类将非常学术化。例如,
sum
的实现对于大型列表不起作用。Python不是Lisp,它们是完全不同的语言。在python中,应该使用迭代而不是递归来实现这一点。另外,您不希望支持
str
,因为这只会创建一个隐藏的二次时间算法,而在Pythonit中,用于连接
str
对象的线性时间算法是微不足道的,这实际上是一个学术性的算法,并且还没有考虑到效率。谢谢你的回答!我猜是
类列表(Generic[A]):
而不是
类列表(Generic[T]):
在你的命题中?还是我遗漏了什么?@smeden大叫。对