Sostituire __str__ metodo su oggetto lista in Python
-
06-09-2019 - |
Domanda
Questo sembra che dovrebbe essere semplice:
voglio un list
come qualsiasi altro list
, eccetto che ha un metodo .__str__
diverso.
- Il tentativo di impostare i risultati
object.__str__ = foo
in un solo errore di lettura - Il tentativo di creare una sottoclasse
list
significa che è necessario un modo per convertire unlist
esistente a un'istanza della sottoclasse. Questo richiede o la copia di tutti gli attributi manualmente (un dolore enorme), o in qualche modo la copia di tutti automaticamente, che non so come fare. - Il tentativo di scrivere un wrapper per l'oggetto
list
significa che devo capire un modo per inviare tutti i messaggi per l'oggetto avvolto tranne.__str__
che gestisco con mio metodo. Non so come fare questo.
Le eventuali alternative o soluzioni # 2 o # 3 molto apprezzato. Grazie!
Soluzione
Questa soluzione funziona senza un involucro. E funziona se si uniscono due liste da add. Qualsiasi operazione che modifica la lista stessa funzionerà come previsto. Solo le funzioni che restituiscono una copia della lista come: ordinato, reveresed restituirà la lista di pitone nativa che va bene. ordinamento e invertire dall'altro operano nella lista stessa e manterrà il 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])
Altri suggerimenti
Se si desidera sovrascrivere __str__
per altri contenitori (ad esempio, tuple
), è possibile usufruire di ereditarietà multipla:
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))
Si potrebbe estendere la classe lista e ignorarlo:
class myList(list):
def __str__(self):
# do something
return "something"
Modifica:. Rimuovere una parte non corretta della risposta che ha suggerito in modo dinamico la sostituzione __str__
sull'oggetto lista, che non è consentita nella realizzazione di liste Python
Sono un programmatore Java, ma penso che è ciò che si vuole (testato 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'
I miei precedenti commenti come una risposta. Come si può vedere MyList accetta qualsiasi sequenza nel suo costruttore.
Il che solleva la questione: perché vuoi sovrascrivere il metodo __str__
Non sarebbe meglio creare una classe per incapsulare il vostro oggetto?
class MyContainer(object):
def __init__(self, list):
self.containedList = list
def __str__(self):
print('All hail Python')
In questo modo non c'è bisogno di preoccuparsi di convertire l'oggetto, o copiare gli attributi, o qualunque. (A proposito, quanto costoso è MyList (longlist)? E 'una copia intelligente, o uno stupido "cerchiamo di ricreare un oggetto elenco da un iterabile?")
Se, ad un certo punto, sembra complicato per fare quello che stai cercando di fare, potrebbe significare che si sta facendo male: p
Come su avvolgendo 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**