python 3.7.0 mypy 0.641 使用 UserList 扩展 pythons' 列表?

python 3.7.0 mypy 0.641 extending pythons' list with UserList?

我正在尝试使用一些自定义方法来扩展 pythons' list,为此我 正在创建一个 class 继承自 UserList.

我不确定什么是正确的方法,我想 mypyUserList.

很好

我查阅了cpython UserList docs并在mypy里面搜索了 UserList 但找不到任何东西。

使用:

这是我想要实现的目标的一个最小示例

from collections import UserList
from typing import List, Optional, Union


class A:
    ...


class B:
    ...


class C:
    ...


TMessage = Union[A, B, C]


class MyList(UserList):
    """Minimal example"""

    def __init__(self, data: Optional[List[TMessage]] = None) -> None:
        self.data: List[TMessage] = []
        if data:
            self.data = data[:]

    def get_last(self) -> TMessage:
        return self.data[-1]

    # other methods to be added ...


some_data = [A(), B(), C(), C(), B(), A()]
my_list_a = MyList(some_data)
my_list_b = MyList(some_data)

my_list_b = my_list_a[3:]

Mypy报错如下

~/tmp ❯❯❯ mypy mypy_userlist.py

mypy_userlist.py:34: error: Argument 1 to "MyList" has incompatible type "List[object]"; expected "Optional[List[Union[A, B, C]]]"
mypy_userlist.py:35: error: Argument 1 to "MyList" has incompatible type "List[object]"; expected "Optional[List[Union[A, B, C]]]"
mypy_userlist.py:37: error: Incompatible types in assignment (expression has type "MutableSequence[Any]", variable has type "MyList")

我可以将 # type: ignore 添加到冲突行,但我想 避免这种情况。

使用自定义方法扩展 python 列表的正确方法是什么 让 mypy 开心?

我是 MyPy 的新手,但我认为您有两个问题。首先是列表是可变的,因此尽管您的列表对象 some_data 满足代码中所需的结构,但没有理由不属于 ABC 之后无法添加,意思是在编译 tile 时,Mypy 无法确保

my_list_a = MyList(some_data) 

是一个有效的分配。 (查看 Mypy 文档的常见问题部分 here 以获得更多讨论)

您可以通过显式注释 some_data:

来解决这个问题
some_data : List[TMessage] = [A(), B(), C(), C(), B(), A()]

当您修复此问题时,当您尝试使用切片分配两个列表时,会弹出第二个问题。 MyPy 不会知道您的切片函数 return 并且会抱怨不兼容的类型。

要解决此问题,您可以在 class 中明确实现切片功能。

def __getitem__(self, slice_indices) -> 'MyList':
     return self.data[slice_indices]