Python __str__和列表


107

在Java中,如果我调用List.toString(),它将自动在List内的每个对象上调用toString()方法。例如,如果我的列表包含对象o1,o2和o3,则list.toString()看起来像这样:

"[" + o1.toString() + ", " + o2.toString() + ", " + o3.toString() + "]"

有没有办法在Python中获得类似的行为?我在类中实现了__str __()方法,但是当我打印出对象列表时,请使用:

print 'my list is %s'%(list)

它看起来像这样:

[<__main__.cell instance at 0x2a955e95f0>, <__main__.cell instance at 0x2a955e9638>, <__main__.cell instance at 0x2a955e9680>]

如何让python自动为列表中的每个元素(或dict)调用__str__?


Answers:


133

在python列表上调用string会调用__repr__内部每个元素的方法。对于一些项目,__str__并且__repr__是相同的。如果您想要这种行为,请执行以下操作:

def __str__(self):
    ...
def __repr__(self):
    return self.__str__()

7
通常,使用进行标识__str__Python数据模型__repr__不一致,因此@ daniel-lew提出的列表理解解决方案更具有Python风格。
Ioannis Filippidis 2014年

2
没有争论 我按要求回答了这个问题,这通常是python的新手如何思考这个问题,但这并不意味着这是最好的回答方式。
David Berger

1
Python应该与它自己的数据模型保持一致,并对所有基元和聚合执行相同的操作。
Terrence Brannon

2
我认为python列表的默认行为是错误的。我希望str()在返回str()的每个内部元素列表上都有。
SuperGeo

21

您可以使用列表推导自动生成一个带有每个str()项目的新列表:

print([str(item) for item in mylist])

6
或者只是print(map(str, mylist))-短一点点
-anula

4
这一个问题是,如果在MYLIST的项目也可能是一个列表
Breandán道尔顿

7

您可以做两个简单的事情,使用map函数或理解。

但这会为您提供字符串列表,而不是字符串。因此,您还必须将字符串连接在一起。

s= ",".join( map( str, myList ) )

要么

s= ",".join( [ str(element) for element in myList ] )

然后,您可以打印此复合字符串对象。

print 'my list is %s'%( s )

4

根据您要使用该输出的目的,也许__repr__更合适:

import unittest

class A(object):
    def __init__(self, val):
        self.val = val

    def __repr__(self):
        return repr(self.val)

class Test(unittest.TestCase):
    def testMain(self):
        l = [A('a'), A('b')]
        self.assertEqual(repr(l), "['a', 'b']")

if __name__ == '__main__':
    unittest.main()

3

我同意先前关于使用列表推导来执行此操作的答案,但是如果您的想法浮出水面,则可以将其隐藏在函数后面。

def is_list(value):
    if type(value) in (list, tuple): return True
    return False

def list_str(value):
    if not is_list(value): return str(value)
    return [list_str(v) for v in value]

只是为了好玩,我递归地使list_str()str()包含在列表中的所有内容。


在实现时1这是有用的__str__,并__repr__分别
文森特庄严,


0

这样就足够了。

在打印列表以及其他容器类时,将使用来打印包含的元素__repr__,因为__repr__它打算用于内部对象表示。如果我们致电:help(object.__repr__)它会告诉我们:

Help on wrapper_descriptor:

__repr__(self, /)
    Return repr(self).

如果我们调用help(repr)它将输出:

Help on built-in function repr in module builtins:

repr(obj, /)
    Return the canonical string representation of the object.

    For many object types, including most builtins, eval(repr(obj)) == obj.

如果__str__为一个对象实现了if ,__repr__则not repr(obj)输出默认的输出,就像print(obj)没有实现时一样。

因此,唯一的方法是__repr__为您的课程实施。一种可行的方法是:

class C:           
    def __str__(self):
        return str(f"{self.__class__.__name__} class str ")

C.__repr__=C.__str__       
ci = C()    


print(ci)       #C class str 
print(str(ci))  #C class str 
print(repr(ci)) #C class str 

-3

您得到的输出只是对象的模块名称,类名称,然后是十六进制的内存地址,因为__repr__函数不会被覆盖。

__str__在使用print时用于对象的字符串表示。但是,由于要打印对象列表,而不是遍历该列表str以为每个项目调用方法,因此它会打印出对象表示形式。

__str__调用该函数,您需要执行以下操作:

'my list is %s' % [str(x) for x in myList]

如果您覆盖此__repr__功能,则可以像以前一样使用打印方法:

class cell:
    def __init__(self, id):
        self.id = id
    def __str__(self):
        return str(self.id) # Or whatever
    def __repr__(self):
        return str(self) # function invoked when you try and print the whole list.

myList = [cell(1), cell(2), cell(3)]
'my list is %s' % myList

然后,您将获得“ my list is [1, 2, 3]”作为输出。


这个答案似乎是在回答一个完全不相关的问题。您确定将其放在正确的位置吗?
Blckknght

是的,Blckknght我想给我的答案的页面有另一个帖子的链接。因此它在这里引导了我,我在这里回答,假设提出问题的人将再次来到这里并看到我的答案。不便之处!!!
panagiwtis koligas

如果另一个问题作为该问题的重复而被关闭,则可以认为此处的现有答案应该已经解决了另一个问题。如果不是这种情况,那么您应该标记为重新打开该问题,而不是在此处发布一个无法理解的答案,几乎可以肯定地将其删除。现在,您可能有话要说,但这里没有其他8个答案之一,但是您需要在此页面的背景下使您的答案有意义,因为您要回答的是这个问题。并且不要发布两个相同的答案!
Blckknght

1
哦,尽管现在我再看一遍,似乎@charliebeckwith已将您的帖子编辑为完全不同的帖子,出于某种无法解释的原因,而不是发布自己的答案。那通常不是编辑工作的方式……
Blckknght

@blckknght我开始编辑它,然后才意识到答案有多糟糕。完全无法解释我为什么继续前进。
charliebeckwith19年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.