繁体   English   中英

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

[英]Using __str__ representation for printing objects in containers in Python

我注意到,当一个带有重载__str__方法的实例作为参数传递给print函数时,它会按预期打印。 但是,当将包含这些实例之一的容器传递给print ,它会改用__repr__方法。 也就是说, print(x)显示器的正确字符串表示x ,和print(x, y)工作正常,但print([x])print((x, y))打印__repr__表示来代替。

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

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

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

其论据:

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

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

所以更清楚列表中的确切内容(因为对象的字符串表示可能有逗号等)。 根据 Guido "BDFL" van Rossum 的说法,这种行为不会消失:

让我为大家节省很多时间,并说我反对这种更改,并且我相信它会引起太多的干扰,以至于在接近测试版时被接受。


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

第一个是子类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)

现在来测试一下:

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

我个人认为这是一个可怕的想法。 一些函数 - 例如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 #...

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

因为当您打印列表时,通常您是从程序员的角度来看的,或者说是调试。 如果您打算显示列表,您将以有意义的方式处理其项目,因此使用 repr。

如果您希望在容器中打印对象,请定义 repr

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

    __repr__ = __str__

当然, repr 应该返回一个字符串,该字符串可以用作重新创建对象的代码,但是您可以随心所欲。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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