[pyar] o bien __get_item__ apesta o yo no entiendo algo

Claudio Freire klaussfreire en gmail.com
Mie Mayo 7 17:12:09 ART 2014


2014-05-07 16:35 GMT-03:00 Felipe Lerena <felipelerena en gmail.com>:
> Estaba laburando una feature de Ojota y me acordé de algo que ya me topé una
> vez y que me habia parecido horriblemente mal manejado por python: cuando
> hago un override de __get_item__ puedo recibir 2 tipos diferenetes como el
> segundo parametro: o bien un int o un objeto slice...
>
> el resultado de un slice no es un Item sinó una serie de items que
> seguramente serán de un tipo diferente del que devuelvo cuando devuelvo uno
> solo, por lo que el método recibe 2 tipos de parámetros y devuelve 2 tipos
> de parámetros según el contexto
>
>
> el codigo de cada vez que haces esto queda quedando algo asi como:
>
>     def __getitem__(self, indexes):
>          # de movida no sabes como ponerle al parametro, si no sabes qué
> nombre ponerle hay algo mal

El parámetro por convención se llama "key"

>          if isinstance(indexes, slice):
>             list_ = self._list[indexes]
>             ret = OjotaSet(self.ojota_class, list_)
>
>
>             #aca devuelvo un objeto del mismo tipo que estoy sliceando, como
> una lista que devuelve otra lista en el slice
>
>          else:
>             ret = self.ojota_class(**self._list[indexes])
>             # pero aca devuelvo un objeto de tipo Ojota de los cuales
> OjotaSet es un conjunto de los mismos
>         return ret
...

> esto es horrible o soy yo que soy un hinchapelotas? Hay alguna mejor manera
> de manejar esto? como que no hay un __get_slice__? lo fixearon en python 3?

Para hacer más copada esta distinción, anteriormente se usaba __getslice__.

Pero __getslice__ no soporta slices extendidos, ni indexación
multidimensional, y al momento de extenderlos decidieron reusar
__getitem__, que es lo más natural sintácticamente.

Una idea de cuál es el problema con separar las funciones, las podés
encontrar en el thread[0] que uno encuentra googleando "__getslice__
deprecation rationale".

Podés implementar dispatch invertido de la forma estándard en python:

def __getitem__(self, indexes):
    return getattr(self, '__getitem_%s__' % (type(indexes).__name__,))(indexes)

def __getitem_int__(self, index):
    return self.ojota_class(**self._list[indexes])

def __getitem_slice__(self, slice_):
    return type(self)(self._list[slice_]) # o self.__class__(...) si
es una clase old-style

Si sólo te interesa slicear con iterables o no, podés hacer:

def __getitem__(self, indexes):
    return getattr(self, '__getitem_%s__' %
(('scalar','iterable')[hasattr(indexes, '__iter__')],))(indexes)

def __getitem_scalar__(self, index):
    return self.ojota_class(**self._list[indexes])

def __getitem_iterable__(self, indexes):
    return type(self)(map(self._list.__getitem__, indexes)) # o
self.__class__(...) si es una clase old-style



[0] https://mail.python.org/pipermail/python-list/2004-December/262826.html


More information about the pyar mailing list