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

在Python中使用_str__表示在容器中打印对象,python,operator-overloading,Python,Operator Overloading,我注意到,当带有重载\uu str\uu方法的实例作为参数传递给print函数时,它会按预期进行打印。但是,当将包含其中一个实例的容器传递给print时,它将使用\uuuu repr\uuu方法。也就是说,print(x)显示x的正确字符串表示形式,print(x,y)工作正常,但是print([x])或print((x,y))打印\u repr\u表示形式 首先,为什么会发生这种情况?第二,在这种情况下,有没有办法纠正print的行为?因为当你打印列表时,通常你是从程序员的角度看的,或者是从调

我注意到,当带有重载
\uu str\uu
方法的实例作为参数传递给
print
函数时,它会按预期进行打印。但是,当将包含其中一个实例的容器传递给
print
时,它将使用
\uuuu repr\uuu
方法。也就是说,
print(x)
显示
x
的正确字符串表示形式,
print(x,y)
工作正常,但是
print([x])
print((x,y))
打印
\u repr\u
表示形式


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

因为当你打印列表时,通常你是从程序员的角度看的,或者是从调试的角度看的。如果您想显示列表,您应该以一种有意义的方式处理它的项目,因此使用repr

如果要在容器中打印对象,请定义repr

class MyObject:
    def __str__(self): return ""

    __repr__ = __str__

当然,repr应该返回一个字符串,该字符串可以用作重新创建对象的代码,但是您可以做任何您想做的事情。

使用对象的容器的问题是完全不明确——比如说,如果
print L
显示
[1,2]
,这意味着什么
L
可以是
['1,2']
(字符串项包含逗号的单个项列表)或四个两项列表中的任何一个(因为每个项都可以是字符串或int)。当然,
print
的类型歧义是常见的,但项目数量的总歧义(因为每个逗号都可以分隔项目或字符串项目的一部分)是决定性的考虑因素。

我不确定列表的
\uuuuu str\uuuuu
方法返回其中包含的对象的
\uuu repr\uuuu
的确切原因-因此我查找了它:

理由如下:

--容器拒绝猜测用户希望在str(容器)上看到什么——环境、分隔符等等

--repr(item)通常显示类型信息——字符串、类名等周围的撇号

因此,更清楚地知道列表中到底是什么(因为对象的字符串表示可以有逗号等)。按照Guido“BDFL”van Rossum的说法,这种行为不会消失:

让我帮大家省下很多钱 时间和说我反对这个 改变,我相信它 会引起太多的干扰 在接近测试版时被接受


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

第一个是子类化
列表
,并实现您自己的
\uuu str\uu
方法

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)
现在来测试一下:

>>> 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>, ...

不幸的是,这两种解决方案都需要重构现有代码,但是
str(container)
的行为将继续存在。

答案很好。我只想指出,有一种更惯用的方式来表达您为
\uuuuu str\uuuuuu
编写的代码:
def\uuuu str\uuuuuuuuuu(self):items=“,”。join([str(item)表示self中的item]);返回“[{0}]”。格式化(项)
(显然,分割成多行)。要点是,
join
是在列表中的每个项目之间插入
(或其他字符串)的首选方法。
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 #...