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

发布于 2024-08-29 04:02:38 字数 360 浏览 3 评论 0原文

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

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

I've noticed that when an instance with an overloaded __str__ method is passed to the print function as an argument, it prints as intended. However, when passing a container that contains one of those instances to print, it uses the __repr__ method instead. That is to say, print(x) displays the correct string representation of x, and print(x, y) works correctly, but print([x]) or print((x, y)) prints the __repr__ representation instead.

First off, why does this happen? Secondly, is there a way to correct that behavior of print in this circumstance?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

紫南 2024-09-05 04:02:38

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

The problem with the container using the objects' __str__ would be the total ambiguity -- what would it mean, say, if print L showed [1, 2]? L could be ['1, 2'] (a single item list whose string item contains a comma) or any of four 2-item lists (since each item can be a string or int). The ambiguity of type is common for print of course, but the total ambiguity for number of items (since each comma could be delimiting items or part of a string item) was the decisive consideration.

无风消散 2024-09-05 04:02:38

我不确定为什么列表的__str__方法返回其中包含的对象的__repr__ - 所以我查了一下:< a href="http://mail.python.org/pipermail/python-3000/2008-May/013876.html" rel="noreferrer">[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(容器) 将会继续存在。

I'm not sure why exactly the __str__ method of a list returns the __repr__ of the objects contained within - so I looked it up: [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.

So it's more clear about what exactly is in the list (since the object's string representation could have commas, etc.). The behavior is not going away, per 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.


Now, there are two ways to resolve this issue for your code.

The first is to subclass list and implement your own __str__ method.

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)

And now to test it:

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

I personally think this is a terrible idea. Some functions - such as random.sample, as demonstrated - actually return list objects - even if you sub-classed lists. So if you take this route there may be a lot of result = strList(function(mylist)) calls, which could be inefficient. It's also a bad idea because then you'll probably have half of your code using regular list objects since you don't print them and the other half using strList objects, which can lead to your code getting messier and more confusing. Still, the option is there, and this is the only way to get the print function (or statement, for 2.x) to behave the way you want it to.

The other solution is just to write your own function strList() which returns the string the way you want it:

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

Both solutions require that you refactor existing code, unfortunately - but the behavior of str(container) is here to stay.

对风讲故事 2024-09-05 04:02:38

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

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

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

    __repr__ = __str__

当然,repr 应该返回一个字符串,该字符串可用作重新创建对象的代码,但您可以执行您想要的操作。

Because when you print the list, generally you're looking from the programmer's perspective, or debugging. If you meant to display the list, you'd process its items in a meaningful way, so repr is used.

If you want your objects to be printed while in containers, define repr

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

    __repr__ = __str__

Of course, repr should return a string that could be used as code to recreate your object, but you can do what you want.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文