Python 键入列表的子类
Python typing for a subclass of list
我希望能够定义列表的子class 的内容必须是什么。 class 如下所示。
class A(list):
def __init__(self):
list.__init__(self)
我想包括输入,以便发生以下情况。
import typing
class A(list: typing.List[str]): # Maybe something like this
def __init__(self):
list.__init__(self)
>> a = A()
>> a.append("a") # No typing error
>> a.append(1) # Typing error
typing
方便地提供了 collections.MutableSequence
的通用版本,因此效果如下:
import typing
T = typing.TypeVar('T')
class HomogeneousList(typing.MutableSequence[T]):
def __init__(self, iterable: typing.Iterable[T]=()) -> None:
self._data: typing.List[T] = []
self._data.extend(iterable)
@typing.overload
def __getitem__(self, index: int) -> T: ...
@typing.overload
def __getitem__(self, index: slice) -> HomogeneousList[T]: ...
def __getitem__(self, index):
return self._data[index]
@typing.overload
def __setitem__(self, index: int, item: T) -> None: ...
@typing.overload
def __setitem__(self, index: slice, item: typing.Iterable[T]) -> None: ...
def __setitem__(self, index, item):
self._data[index] = item
def __delitem__(self, index: typing.Union[int, slice]) -> None:
del self._data[index]
def __len__(self) -> int:
return len(self._data)
def insert(self, index: int, item: T) -> None:
self._data.insert(index, item)
string_list = HomogeneousList[str]()
string_list.append('foo')
string_list.append(42)
int_list = HomogeneousList[int]()
int_list.append(42)
int_list.append('foo')
现在,mypy
出现以下错误:
test.py:36: error: Argument 1 to "append" of "MutableSequence" has incompatible type "int"; expected "str"
test.py:41: error: Argument 1 to "append" of "MutableSequence" has incompatible type "str"; expected "int"
输入 __getitem__
等有一些棘手的方面,因为它们也接受 slice
对象,但并不可怕。
请注意,这很有用,因为如果您只是尝试这样做:
class HomogeneousList(collections.abc.MutableSequence, typing.Generic[T]):
....
MyPy,至少,不会抛出追加错误。 AFAIKT 你必须明确添加:'
def append(self, item: T) -> None:
self._data.append(item)
从一开始就删除了 collections.abc.MutableSequence
的很多实用程序。无论如何,值得庆幸的是,键入提供了所有这些开箱即用的通用版本!
请注意,您可以像我展示的那样通用地使用这些,但您也可以执行以下操作:
class StringList(HomogeneousList[str]):
pass
mylist = StringList([1,2,3]) # mypy error
mylist = StringList('abc') # no error
mylist.append('foo') # no error
mylist.append(42) # mypy error
在Python3.9之前,您可以使用:
import typing
class A(typing.List[str]):
pass
这向您的类型检查器表明 class A
的元素应该是 str
类型。在 运行 时,这与创建 list
的子 class 相同。 PEP 484 specifies how the typing system behaves. In particular, the example in this section of the PEP 做的事情与您的要求类似,但使用 typing.Dict
而不是 typing.List
。
在 Python 3.9+ 中,您可以 use the built-in type instead of importing from typing。 class 变为:
class A(list[str]):
pass
我希望能够定义列表的子class 的内容必须是什么。 class 如下所示。
class A(list):
def __init__(self):
list.__init__(self)
我想包括输入,以便发生以下情况。
import typing
class A(list: typing.List[str]): # Maybe something like this
def __init__(self):
list.__init__(self)
>> a = A()
>> a.append("a") # No typing error
>> a.append(1) # Typing error
typing
方便地提供了 collections.MutableSequence
的通用版本,因此效果如下:
import typing
T = typing.TypeVar('T')
class HomogeneousList(typing.MutableSequence[T]):
def __init__(self, iterable: typing.Iterable[T]=()) -> None:
self._data: typing.List[T] = []
self._data.extend(iterable)
@typing.overload
def __getitem__(self, index: int) -> T: ...
@typing.overload
def __getitem__(self, index: slice) -> HomogeneousList[T]: ...
def __getitem__(self, index):
return self._data[index]
@typing.overload
def __setitem__(self, index: int, item: T) -> None: ...
@typing.overload
def __setitem__(self, index: slice, item: typing.Iterable[T]) -> None: ...
def __setitem__(self, index, item):
self._data[index] = item
def __delitem__(self, index: typing.Union[int, slice]) -> None:
del self._data[index]
def __len__(self) -> int:
return len(self._data)
def insert(self, index: int, item: T) -> None:
self._data.insert(index, item)
string_list = HomogeneousList[str]()
string_list.append('foo')
string_list.append(42)
int_list = HomogeneousList[int]()
int_list.append(42)
int_list.append('foo')
现在,mypy
出现以下错误:
test.py:36: error: Argument 1 to "append" of "MutableSequence" has incompatible type "int"; expected "str"
test.py:41: error: Argument 1 to "append" of "MutableSequence" has incompatible type "str"; expected "int"
输入 __getitem__
等有一些棘手的方面,因为它们也接受 slice
对象,但并不可怕。
请注意,这很有用,因为如果您只是尝试这样做:
class HomogeneousList(collections.abc.MutableSequence, typing.Generic[T]):
....
MyPy,至少,不会抛出追加错误。 AFAIKT 你必须明确添加:'
def append(self, item: T) -> None:
self._data.append(item)
从一开始就删除了 collections.abc.MutableSequence
的很多实用程序。无论如何,值得庆幸的是,键入提供了所有这些开箱即用的通用版本!
请注意,您可以像我展示的那样通用地使用这些,但您也可以执行以下操作:
class StringList(HomogeneousList[str]):
pass
mylist = StringList([1,2,3]) # mypy error
mylist = StringList('abc') # no error
mylist.append('foo') # no error
mylist.append(42) # mypy error
在Python3.9之前,您可以使用:
import typing
class A(typing.List[str]):
pass
这向您的类型检查器表明 class A
的元素应该是 str
类型。在 运行 时,这与创建 list
的子 class 相同。 PEP 484 specifies how the typing system behaves. In particular, the example in this section of the PEP 做的事情与您的要求类似,但使用 typing.Dict
而不是 typing.List
。
在 Python 3.9+ 中,您可以 use the built-in type instead of importing from typing。 class 变为:
class A(list[str]):
pass