在Python中替换list对象上的__str__方法

时间:2009-05-31 09:06:53

标签: python

这似乎应该很简单:

我希望list与其他任何list一样,除非它有不同的.__str__方法。

  1. 尝试设置object.__str__ = foo会导致只读错误
  2. 尝试子类list意味着您需要某种方法将现有的list转换为子类的实例。这需要手动复制所有属性(一个巨大的痛苦),或以某种方式自动复制它们,我不知道该怎么做。
  3. 尝试在list对象周围编写一个包装器意味着我必须找出一些方法将所有消息发送到包裹的对象,除了.__str__,我用自己的方法处理。不知道该怎么做。
  4. 任何替代品或解决方案#2或#3非常感谢。谢谢!

8 个答案:

答案 0 :(得分:8)

此解决方案无需包装即可运行。如果您通过添加加入两个列表,则可以使用。任何修改列表本身的操作都将按预期工作。只有返回列表副本的函数如: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])

答案 1 :(得分:4)

您可以扩展列表类并覆盖它:

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

编辑:删除了答案的错误部分,建议动态替换列表对象上的__str__,这在Python列表的实现中是不允许的。

答案 2 :(得分: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))

答案 3 :(得分:2)

我是一名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

答案 4 :(得分:2)

class MyList(list):
     def __str__(self):
             return "foo"

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

'富'

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

'富'

我之前的评论作为答案。如您所见,MyList接受其构造函数中的任何序列。

答案 5 :(得分:1)

提出了一个问题:为什么要覆盖__str__方法?

创建一个封装对象的类不是更好吗?

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

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

这样您就不必担心转换对象或复制属性,或者无论如何。 (顺便说一句,MyList(longlist)有多贵?是智能副本,还是愚蠢的“让我们从迭代中重新创建一个列表对象?”)

如果在某些时候,做你想做的事情看起来很复杂,那可能意味着你做错了:p

答案 6 :(得分:0)

如何包装清单?

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

答案 7 :(得分:-1)

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**