Заменить метод __str__ на объект списка в Python
Кажется, что это должно быть просто:
Я хочу list
как и любой другой list
, за исключением того, что он имеет другой метод .__str__
.
- Попытка установить
object.__str__ = foo
приводит к ошибке только для чтения
- Попытка подкласса
list
означает, что вам нужно каким-то образом преобразовать существующий list
в экземпляр подкласса. Для этого требуется либо копирование всех атрибутов вручную (огромная боль), либо их копирование автоматически, что я не знаю, как это сделать.
- Попытка написать обертку вокруг объекта
list
означает, что мне нужно выяснить способ отправки всех сообщений в обернутый объект, кроме .__str__
, который я обрабатываю с помощью собственного метода. Не знаю, как это сделать.
Любые альтернативы, или решения № 2 или № 3, получили высокую оценку. Спасибо!
Ответы
Ответ 1
Это решение работает без обертки. И работает, если вы присоедините два списка, добавив. Любая операция, которая модифицирует сам список, будет работать должным образом. Только функции, возвращающие копию списка, например: sorted, reveresed, возвращают собственный список python, который является прекрасным. sort и reverse, с другой стороны, работают с самим списком и сохраняют тип.
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])
Ответ 2
Вы можете расширить класс списка и переопределить его:
class myList(list):
def __str__(self):
# do something
return "something"
Изменить: удалена некорректная часть ответа, которая предложила динамически заменить __str__
на объект списка, что недопустимо при реализации списков Python.
Ответ 3
Если вы хотите переопределить __str__
для других контейнеров (например, tuple
), вы можете воспользоваться множественным наследованием:
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))
Ответ 4
Я программист на Java, но я думаю, что это то, что вы хотите (протестировано с помощью 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
Ответ 5
class MyList(list):
def __str__(self):
return "foo"
str(MyList([1, 2, 3]))
'Foo'
str(MyList(list([1, 2, 3])))
'Foo'
Мои предыдущие комментарии в качестве ответа. Как вы можете видеть, MyList принимает любую последовательность в своем конструкторе.
Ответ 6
Что вызывает вопрос: почему вы хотите переопределить метод __str__?
Не было бы лучше создать класс для инкапсуляции вашего объекта?
class MyContainer(object):
def __init__(self, list):
self.containedList = list
def __str__(self):
print('All hail Python')
Таким образом, вам не нужно беспокоиться о преобразовании вашего объекта или копировании атрибутов или вообще. (кстати, насколько дорогим является MyList (longlist)? Это интеллектуальная копия или немой "позволяет воссоздать объект списка из итерабельного?" )
Если в какой-то момент вам будет сложно делать то, что вы пытаетесь сделать, это может означать, что вы делаете это неправильно: p
Ответ 7
Как насчет обертывания списка?
>>> 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']
>>>
Ответ 8
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**