2024-09-29 17:12:33 发布
网友
我的函数需要接受一个对象,从中可以通过索引提取数据,即。一个List或具有已定义的__getitem__方法的实例。在
List
__getitem__
我可以使用哪种类型来暗示此参数?在
更新: 据我所知,目前还没有这样的类型,我试着自己做一个:
class IndexableContainer(Generic[int, ReturnType]): def __getitem__(self, key: int) -> ReturnType: ...
但我得到了以下错误:
我该怎么做?在
有几种不同的方法可以做到这一点。在
如果您可以只使用自定义类(您可以编写)作为可索引容器,那么您只需调整代码并删除“int”类型参数:
class IndexableContainer(Generic[ReturnType]): def __getitem__(self, key: int) -> ReturnType: ... class MyCustomContainer(IndexableContainer[ReturnType]): def __getitem__(self, key: int) -> ReturnType: # Implementation here def requires_indexable_container(container: IndexableContainer[ReturnType]) -> ReturnType: # Code using container here
当然,问题是,如果您想将一个普通的旧列表传递到函数中,那么您将无法这样做,因为list没有您的自定义类型的子类。在
我们可以通过巧妙地使用@overload修饰符和联合来对某些输入进行特殊处理,但是还有另一种方法,尽管是实验性的,称为Protocols。在
@overload
协议基本上允许您使用类型提示以一种理智的方式表示“duck typing”:基本思想是我们可以调整IndexableContainer,使其成为一个协议。现在,任何使用适当的签名实现__getitem__方法的对象都被视为有效的IndexableContainer,不管它们是否是该类型的子类。在
唯一需要注意的是,协议目前是实验性的,(afaik)只有mypy支持。计划是最终将协议添加到一般的Python生态系统中,具体建议请参见PEP 544,但我没有跟踪讨论/不知道这是什么状态。在
在任何情况下,要使用协议,请使用pip安装typing_extensions模块。然后,可以执行以下操作:
typing_extensions
似乎我们能得到的最接近的是:
Mapping[int, Any]
虽然这不是我想要的,但已经够近了。在
有几种不同的方法可以做到这一点。在
如果您可以只使用自定义类(您可以编写)作为可索引容器,那么您只需调整代码并删除“int”类型参数:
当然,问题是,如果您想将一个普通的旧列表传递到函数中,那么您将无法这样做,因为list没有您的自定义类型的子类。在
我们可以通过巧妙地使用
@overload
修饰符和联合来对某些输入进行特殊处理,但是还有另一种方法,尽管是实验性的,称为Protocols。在协议基本上允许您使用类型提示以一种理智的方式表示“duck typing”:基本思想是我们可以调整IndexableContainer,使其成为一个协议。现在,任何使用适当的签名实现
__getitem__
方法的对象都被视为有效的IndexableContainer,不管它们是否是该类型的子类。在唯一需要注意的是,协议目前是实验性的,(afaik)只有mypy支持。计划是最终将协议添加到一般的Python生态系统中,具体建议请参见PEP 544,但我没有跟踪讨论/不知道这是什么状态。在
在任何情况下,要使用协议,请使用pip安装
^{pr2}$typing_extensions
模块。然后,可以执行以下操作:似乎我们能得到的最接近的是:
虽然这不是我想要的,但已经够近了。在
相关问题 更多 >
编程相关推荐