Reemplazar __str__ método en lista de objetos en Python
-
06-09-2019 - |
Pregunta
Esta parece que debería ser simple:
quiero un list
como cualquier otro list
, excepto que tiene un método .__str__
diferente.
- Tratar de establecer resultados
object.__str__ = foo
en un error de sólo lectura - Tratando de subclase
list
significa que necesita alguna manera de convertir unlist
existente a una instancia de la subclase. Esto requiere o bien copiar todos los atributos manualmente (un enorme dolor), o de alguna manera de copiar todos ellos de forma automática, lo que no sé cómo hacerlo. - tratando de escribir una envoltura alrededor del objeto
list
significa que tengo que encontrar alguna manera de enviar todos los mensajes al objeto envuelto excepto.__str__
la que yo manejo mi propio método. No sé cómo hacer esto.
Cualquier alternativas o soluciones # 2 o # 3 apreciado considerablemente. Gracias!
Solución
Esta solución funciona sin envoltura. Y funciona si se une a dos listas por el complemento. Cualquier operación que modifique la lista en sí funcionará como se espera. Sólo las funciones que devuelven una copia de la lista como: ordenados, reveresed devolverá la lista de Python nativo que está muy bien. clasificar y revertir, por otra parte operan en la lista en sí y mantendrán el tipo.
class myList(list):
def __new__(cls, data=None):
obj = super(myList, cls).__new__(cls, data)
return obj
def __str__(self):
return 'myList(%s)' % list(self)
def __add__(self, other):
return myList(list(self) + list(other))
>>> l = myList(range(5))
>>> print l
myList([0, 1, 2, 3, 4])
>>> print l + [1, 2]
myList([0, 1, 2, 3, 4, 1, 2])
>>> l.sort()
>>> print l
myList([0, 1, 2, 3, 4])
Otros consejos
Si desea para anular __str__
para otros recipientes (por ejemplo, tuple
), se puede tomar ventaja de la herencia múltiple:
class PrettyStr(object):
def __str__(self):
ret = ''
if isinstance(self, (list, tuple)):
ret = ''.join(str(elem) for elem in self)
else:
pass # handle other types here
return ret
class MyList(PrettyStr, list):
pass
class MyTuple(PrettyStr, tuple):
pass
if __name__ == "__main__":
print MyList([1, 2, 3, 4])
print MyTuple((1, 2, 3, 4))
Se puede extender la clase lista y anularlo:
class myList(list):
def __str__(self):
# do something
return "something"
Edit:. Eliminado una parte incorrecta de la respuesta que sugería dinámicamente reemplazando __str__
en el objeto de lista, que no está permitido en la aplicación de listas de Python
Soy un programador de Java, pero creo que es lo que quiere (probado con Python 2.6):
>>> class myList(list):
... def __str__(self):
... return "aaa"
...
>>> def myListWrapper(list):
... return myList(list)
...
>>> a = [1, 2, 3]
>>> type(a)
<type 'list'>
>>> b = myListWrapper(a)
>>> type(b)
<class '__main__.myList'>
>>> print(a)
[1, 2, 3]
>>> print(b)
aaa
class MyList(list):
def __str__(self):
return "foo"
str(MyList([1, 2, 3]))
foo
str(MyList(list([1, 2, 3])))
foo
Mis comentarios anteriores como una respuesta. Como se puede ver MyList acepta cualquier secuencia en su constructor.
Lo que plantea la pregunta: ¿por qué quieres reemplazar el método __str__
No sería mejor crear una clase para encapsular el objeto?
class MyContainer(object):
def __init__(self, list):
self.containedList = list
def __str__(self):
print('All hail Python')
De esta manera usted no tiene que preocuparse por la conversión de su objeto, o copiar los atributos, o sea. (Por cierto, lo caro que es Mi lista (longlist)? ¿Es una copia inteligente, o un tonto "vamos a volver a crear un objeto de lista de un iterable?")
Si, en algún momento, se ve complicado de hacer lo que estás tratando de hacer, podría significar que usted está haciendo mal: p
¿Qué hay de envolver la lista?
>>> class StrList(object):
def __init__(self, data=None):
self._data = data or []
def __str__(self):
return "StrList!"
def __getattr__(self, attr):
if attr == "_data":
return self.__dict__[attr]
return getattr(self._data, attr)
def __setattr__(self, key, val):
if key == "_data":
self.__dict__[key] = val
else:
setattr(self._data, key, val)
def __getitem__(self, index):
return self._data[index]
def __setitem__(self, index, value):
self._data[index] = value
>>> l = StrList(range(3))
>>> print l
StrList!
>>> l[0]
0
>>> for x in l:
print x
0
1
2
>>> l[0] = "spam"
>>> l.append("egg")
>>> print list(l)
['spam', 1, 2, 'egg']
>>>
Ex = ["a", 2, 4] #our_list
Ex(-1) = "xuxu_beleza" #the_name_of_your_list(index) = new_item
Print(Ex)
["a", 2, "xuxu_beleza"] #our_new_list
**list[index] = new_item**