简体   繁体   English

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

[英]Replace __str__ method on list object in Python

This seems like it should be simple: 这看起来应该很简单:

I want a list like any other list , except it has a different .__str__ method. 我想要一个像任何其他list一样的list ,除了它有一个不同的.__str__方法。

  1. Trying to set object.__str__ = foo results in a read-only error 尝试设置object.__str__ = foo导致只读错误
  2. Trying to subclass list means you need some way to convert an existing list to an instance of the subclass. 尝试子类list意味着您需要某种方法将现有list转换为子类的实例。 This requires either copying all attributes manually (a huge pain), or somehow copying them all automatically, which I don't know how to do. 这需要手动复制所有属性(一个巨大的痛苦),或以某种方式自动复制它们,我不知道该怎么做。
  3. Trying to write a wrapper around the list object means I have to figure out some way to send all messages to the wrapped object except .__str__ which I handle with my own method. 试图在list对象周围编写一个包装器意味着我必须找出一些方法将所有消息发送到包装对象,除了.__str__ ,我用自己的方法处理。 Don't know how to do this. 不知道该怎么做。

Any alternatives, or solutions #2 or #3 greatly appreciated. 任何替代方案,或解决方案#2或#3非常感谢。 Thanks! 谢谢!

This solution works without a wrapper. 此解决方案无需包装即可运行。 And works if you join two lists by add. 如果您通过添加加入两个列表,则可以使用。 Any operation that modify the list itself will work as expected. 任何修改列表本身的操作都将按预期工作。 Only functions that return a copy of the list like: sorted, reveresed will return the native python list which is fine. 只有返回列表副本的函数如:sorted,reveresed将返回本机python列表,这很好。 sort and reverse on the other hand operate on the list itself and will keep the type. 另一方面,排序和反向操作列表本身并保持类型。

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

You could extend the list class and override it: 您可以扩展列表类并覆盖它:

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

Edit: removed an incorrect part of the answer which suggested dynamically replacing __str__ on the list object, which is not allowed in the implementation of Python lists. 编辑:删除了答案的错误部分,建议动态替换列表对象上的__str__ ,这在Python列表的实现中是不允许的。

If you would like to override __str__ for other containers (eg, tuple ), you can take advantage of multiple inheritance: 如果要为其他容器(例如, tuple )覆盖__str__ ,则可以利用多重继承:

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

I'm a Java programmer but I think that is what you want (tested with python 2.6): 我是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]))

'foo' “富”

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

'foo' “富”

My earlier comments as an answer. 我之前的评论作为答案。 As you can see MyList accepts any sequence in its constructor. 如您所见,MyList接受其构造函数中的任何序列。

Which raises the question: why do you want to override the __str__ method? 提出了一个问题:为什么要覆盖__str__方法?

Wouldnt it be better to create a class to encapsulate your object? 创建一个类来封装你的对象不是更好吗?

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

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

This way you don't have to worry about converting your object, or copying the attributes, or whatsoever. 这样您就不必担心转换对象或复制属性,或者无论如何。 (by the way, how expensive is MyList(longlist)? Is it an intelligent copy, or a dumb "let's recreate a list object from an iterable?") (顺便说一句,MyList(longlist)有多贵?是智能副本,还是愚蠢的“让我们从迭代中重新创建一个列表对象?”)

If, at some point, it looks complicated to do what you're trying to do, it might mean that you're doing it wrong :p 如果在某些时候,做你正在做的事情看起来很复杂,那可能意味着你做错了:p

How about wrapping the list? 如何包装清单?

>>> 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 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM