[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