Saltar al contenido

Escritura de Python para una subclase de lista

Revisamos de forma cada artículo en nuestro espacio con el objetivo de mostrarte en todo momento información con la mayor veracidad y actualizada.

Solución:

typing convenientemente proporciona una versión genérica de collections.MutableSequence, así que algo en el sentido de:

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')

Ahora, mypyda los siguientes errores:

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"

Hay algunos aspectos complicados de escribir __getitem__ etc porque aceptan slice objetos también, pero no terribles.

Tenga en cuenta que esto es útil, porque si solo intenta hacer:

class HomogeneousList(collections.abc.MutableSequence, typing.Generic[T]):
    ....

MyPy, al menos, no arroja un error para agregar. AFAIKT, tendrías que agregar explícitamente: ‘

def append(self, item: T) -> None:
    self._data.append(item)

Lo que elimina gran parte de la utilidad de collections.abc.MutableSequence para empezar. De todos modos, afortunadamente, ¡escribir proporciona versiones genéricas de todos estos listos para usar!

Tenga en cuenta que puede usarlos de forma genérica, como he mostrado, pero también puede hacer algo como:

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

Antes de Python 3.9, puede usar:

import typing

class A(typing.List[str]):
    pass

Esto le indica a su verificador de tipos que los elementos de la clase A debe ser de tipo str. En tiempo de ejecución, esto se comporta igual que crear una subclase de list. PEP 484 especifica cómo se comporta el sistema de tipeo. En particular, el ejemplo en esta sección del PEP hace algo similar a lo que estás preguntando, pero con typing.Dict en vez de typing.List.

En Python 3.9+, puede usar el tipo incorporado en lugar de importar desde la escritura. La clase se convierte en:

class A(list[str]):
    pass

Si te sientes impulsado, puedes dejar una noticia acerca de qué le añadirías a este post.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *