使用__str__表示在Python中的容器中打印对象

Bob*_*bbs 9 python operator-overloading

我注意到,当一个带有重载__str__方法的实例print作为参数传递给函数时,它会按预期打印.但是,在将包含其中一个实例的容器传递给print它时,它会使用该__repr__方法.也就是说,print(x)显示正确的字符串表示x,并且print(x, y)正确地工作,但是print([x])或者print((x, y))打印__repr__表示.

首先,为什么会发生这种情况?其次,有没有办法纠正print这种情况下的行为?

Ale*_*lli 11

使用对象的容器的问题__str__将是完全模糊 - 如果print L显示它意味着什么[1, 2]L可以是['1, 2'](单个项目列表,其字符串项目包含逗号)或四个2项目列表中的任何一个(因为每个项目可以是字符串或int).类型的模糊性print当然是常见的,但是项目数量的总模糊度(因为每个逗号可以是分隔项目字符串项目的一部分)是决定性的考虑因素.


Dan*_*l G 5

我不确定为什么__str__列表的方法会返回其中__repr__包含的对象 - 所以我查了一下:[Python-3000] PEP:str(容器)应该调用str(item),而不是repr(item)

争论:

- 容器拒绝猜测用户想要在str(容器)上看到什么 - 环境,分隔符等等;

- repr(item)通常显示类型信息 - 字符串,类名等的撇号.

所以它更清楚列表中究竟是什么(因为对象的字符串表示可能有逗号等).根据Guido"BDFL"van Rossum的说法,这种行为并没有消失:

让我给大家节省很多时间并说我反对这种改变,并且我认为这会导致太多的干扰被接受这个接近beta.


现在,有两种方法可以解决您的代码问题.

第一个是子类化list并实现自己的__str__方法.

class StrList(list):
    def __str__(self):
        string = "["
        for index, item in enumerate(self):
            string += str(item)
            if index != len(self)-1:
                string += ", "
        return string + "]"

class myClass(object):
    def __str__(self):
        return "myClass"

    def __repr__(self):
        return object.__repr__(self)
Run Code Online (Sandbox Code Playgroud)

现在来测试一下:

>>> objects = [myClass() for _ in xrange(10)]
>>> print objects
[<__main__.myClass object at 0x02880DB0>, #...
>>> objects = StrList(objects)
>>> print objects
[myClass, myClass, myClass #...
>>> import random
>>> sample = random.sample(objects, 4)
>>> print sample
[<__main__.myClass object at 0x02880F10>, ...
Run Code Online (Sandbox Code Playgroud)

我个人认为这是一个糟糕的主意.某些功能 - 例如random.sample,如所示 - 实际上返回list对象 - 即使您对列表进行了分类.因此,如果您采用这种方式,可能会有很多result = strList(function(mylist))呼叫,这可能效率低下.这也是一个坏主意,因为那时你可能会有一半的代码使用常规list对象,因为你不打印它们而另一半使用strList对象,这可能会导致代码变得更加混乱和混乱.仍然,选项就在那里,这是使print函数(或语句,2.x)按照您希望的方式运行的唯一方法.

另一种解决方案就是编写自己的函数strList(),以你想要的方式返回字符串:

def strList(theList):
    string = "["
    for index, item in enumerate(theList):
        string += str(item)
        if index != len(theList)-1:
            string += ", "
    return string + "]"

>>> mylist = [myClass() for _ in xrange(10)]
>>> print strList(mylist)
[myClass, myClass, myClass #...
Run Code Online (Sandbox Code Playgroud)

不幸的str(container)是,这两种解决方案都要求您重构现有代码 - 但这种行为仍然存在.