Заменить метод __str__ на объект списка в Python

StackOverflow https://stackoverflow.com/questions/931699

  •  06-09-2019
  •  | 
  •  

Вопрос

Кажется, что это должно быть просто:

Я хочу, чтобы list как и любой другой list, за исключением того , что у него другой .__str__ способ.

  1. Пытаюсь установить object.__str__ = foo приводит к ошибке, доступной только для чтения
  2. Попытка создать подкласс list означает, что вам нужен какой-то способ преобразовать существующий list к экземпляру подкласса.Для этого требуется либо скопировать все атрибуты вручную (огромная боль), либо каким-то образом скопировать их все автоматически, что я не знаю, как сделать.
  3. Пытаюсь написать оболочку вокруг list объект означает, что я должен придумать какой-то способ отправки всех сообщений обернутому объекту, за исключением .__str__ с которым я справляюсь своим собственным методом.Не знаю, как это сделать.

Любые альтернативы или решения №2 или №3 высоко ценятся.Спасибо!

Это было полезно?

Решение

Это решение работает без оболочки.И работает, если вы объединяете два списка с помощью add.Любая операция, изменяющая сам список, будет работать должным образом.Только функции, которые возвращают копию списка, например:sorted, reveresed вернет собственный список python, который в порядке.сортировка и реверсирование, с другой стороны, работают с самим списком и сохраняют тип.

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])

Другие советы

Если вы хотите переопределить __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))

Вы могли бы расширить класс list и переопределить его:

class myList(list):
  def __str__(self):
    # do something
    return "something"

Редактировать:удалена неправильная часть ответа, в которой предлагалась динамическая замена __str__ на объекте list, который не разрешен в реализации списков Python.

Я программист на 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
class MyList(list):
     def __str__(self):
             return "foo"

str(MyList([1, 2, 3]))

"фу"

str(MyList(list([1, 2, 3])))

"фу"

Мои предыдущие комментарии в качестве ответа.Как вы можете видеть, myList принимает любую последовательность в своем конструкторе.

В связи с чем возникает вопрос:почему вы хотите переопределить метод __str__?

Не лучше ли было бы создать класс для инкапсуляции вашего объекта?

class MyContainer(object):
    def __init__(self, list):
        self.containedList = list

    def __str__(self):
        print('All hail Python')

Таким образом, вам не нужно беспокоиться о преобразовании вашего объекта, копировании атрибутов или о чем-либо еще.(кстати, насколько дорог myList (длинный список)?Это интеллектуальная копия или тупое "давайте воссоздадим объект списка из итерируемого?")

Если в какой-то момент то, что вы пытаетесь сделать, покажется сложным, это может означать, что вы делаете это неправильно: p

Как насчет того, чтобы завершить список?

>>> 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**
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top