[英]Python typing for a subclass of list
I want to be able to define what the contents of a subclass of list have to be.我希望能够定义列表子类的内容。 The class would look like the following.该类将如下所示。
class A(list):
def __init__(self):
list.__init__(self)
I want to include typing such that the following would happen.我想包括打字,以便发生以下情况。
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
conveniently provides a generic version of collections.MutableSequence
, so something to the effect of: 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')
Now, mypy
gives the following errors:现在, 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"
There is some tricky aspects of typing __getitem__
etc because they accept slice
objects as well, but not terrible.输入__getitem__
等有一些棘手的方面,因为它们也接受slice
对象,但并不可怕。
Note, this is useful, because if you just try to do:请注意,这很有用,因为如果您只是尝试执行以下操作:
class HomogeneousList(collections.abc.MutableSequence, typing.Generic[T]):
....
MyPy, at least, doesn't throw an error for append.至少,MyPy 不会为追加引发错误。 AFAIKT you'd have to explicitly add:' AFAIKT 你必须明确添加:'
def append(self, item: T) -> None:
self._data.append(item)
Which sort of removes a lot of the utility of collections.abc.MutableSequence
to begin with.哪种类型的开头删除了collections.abc.MutableSequence
的许多实用程序。 Anyway, thankfully, typing provides generic versions of all of these out of the box!无论如何,幸运的是,打字提供了所有这些开箱即用的通用版本!
Note, you can use these generically, like I've show, but you can also do something like:请注意,您可以像我展示的那样一般地使用这些,但您也可以执行以下操作:
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
Prior to Python 3.9, you can use:在 Python 3.9 之前,您可以使用:
import typing
class A(typing.List[str]):
pass
This indicates to your type checker that elements of class A
should be of type str
.这向您的类型检查器表明A
类A
元素应该是str
类型。 At run-time, this behaves the same as creating a subclass of list
.在运行时,这与创建list
的子类的行为相同。 PEP 484 specifies how the typing system behaves. PEP 484指定了打字系统的行为方式。 In particular, the example in this section of the PEP does something similar to what you're asking, but with typing.Dict
instead of typing.List
.特别是, PEP 的这一部分中的示例执行的操作与您所要求的类似,但使用typing.Dict
而不是typing.List
。
In Python 3.9+, you can use the built-in type instead of importing from typing .在 Python 3.9+ 中,您可以使用内置类型而不是从输入中导入。 The class becomes:类变为:
class A(list[str]):
pass
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.