在Python中使用str\uuu表示打印容器中的对象

2024-04-24 09:04:55 发布

您现在位置:Python中文网/ 问答频道 /正文

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

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


Tags: 实例方法函数字符串情况容器printstr
3条回答

我不确定为什么列表的__str__方法会返回包含在其中的对象的__repr__所以我查找了它:[Python-3000] PEP: str(container) should call str(item), not repr(item)

Arguments for it:

-- containers refuse to guess what the user wants to see on str(container) - surroundings, delimiters, and so on;

-- repr(item) usually displays type information - apostrophes around strings, class names, etc.

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

Let me just save everyone a lot of time and say that I'm opposed to this change, and that I believe that it would cause way too much disturbance to be accepted this close to 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)

现在来测试一下:

>>> 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)的行为仍然存在。

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

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

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

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

    __repr__ = __str__

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

相关问题 更多 >