如何使用print()打印类的实例?

How to print instances of a class using print()?

提问人:Ashwin Nanjappa 提问时间:10/8/2009 最后编辑:Karl KnechtelAshwin Nanjappa 更新时间:5/22/2023 访问量:1346688

问:

当我尝试一个类的实例时,我得到如下输出:print

>>> class Test():
...     def __init__(self):
...         self.a = 'foo'
...
>>> print(Test())
<__main__.Test object at 0x7fc9a9e36d60>

我怎样才能使它显示一些自定义的东西(例如,包含属性值的东西)?也就是说,如何定义类的实例在打印时的显示方式(它们的字符串表示形式)?printa


请参阅如何为类本身(而不是类的实例)选择自定义字符串表示形式? 如果要定义类本身的行为(在本例中,以便 print(Test) 显示自定义内容,而不是 <class __main__。测试>或类似)。(事实上,该技术本质上是相同的,但应用起来更棘手。

Python 打印 对象

评论


答:

909赞 Chris Lutz 10/8/2009 #1
>>> class Test:
...     def __repr__(self):
...         return "Test()"
...     def __str__(self):
...         return "member of Test"
... 
>>> t = Test()
>>> t
Test()
>>> print(t)
member of Test

__str__ 方法是在打印它时调用它,而 __repr__ 方法是在使用 repr() 函数时(或使用交互式提示查看它时)发生的方法。

如果没有给出方法,Python 将打印结果。如果你定义但未定义,Python 将使用你在上面看到的 ,但仍用于打印。__str____repr____str____repr____repr____str__

评论

14赞 kender 10/8/2009
还有一个 unicode 方法,你可以用它来代替 Str ;请注意,它应该返回一个 Unicode 对象,而不是一个字符串(但如果你返回一个字符串,无论如何都会完成到 Unicode 的转换......
1赞 Chris Lutz 10/8/2009
@kender - 我不知道它,但回想起来,考虑到 Python 2.x 的 Unicode 处理中断,这是非常有意义的。
14赞 tnotstar 12/20/2012
我认为如果没有指向另一个答案的链接,就无法完成这个答案!
0赞 Viet 7/5/2013
救了我!但是,在重新实现方法 __repr__(self) 后,print 会误导用户。您知道这方面的任何最佳实践吗?
18赞 Janac Meena 7/19/2016
致 Java 程序员:__str__(self) 就像 python 世界的 toString()
185赞 dbr 10/8/2009 #2

正如 Chris Lutz 所解释的那样,这是由类中的方法定义的。__repr__

repr() 的文档中:

对于许多类型,此函数会尝试返回一个字符串,该字符串在传递给 时将生成具有相同值的对象,否则表示形式是用尖括号括起来的字符串,其中包含对象类型的名称以及其他信息,通常包括对象的名称和地址。类可以通过定义方法来控制此函数为其实例返回的内容。eval()__repr__()

给定以下类测试:

class Test:
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def __repr__(self):
        return f"<Test a:{self.a} b:{self.b}>"

    def __str__(self):
        return f"From str method of Test: a is {self.a}, b is {self.b}"

..它将在 Python shell 中按以下方式操作:

>>> t = Test(123, 456)
>>> t
<Test a:123 b:456>
>>> print(repr(t))
<Test a:123 b:456>
>>> print(t)
From str method of Test: a is 123, b is 456
>>> print(str(t))
From str method of Test: a is 123, b is 456

如果未定义任何方法,则 (或 ) 将改用__str__print(t)print(str(t))__repr__

如果未定义任何方法,则使用默认值,大致相当于__repr__

def __repr__(self):
    cls = self.__class__
    return f"<{cls.__module_}.{cls.__qualname__} object at {id(self)}>"

评论

0赞 Chris Lutz 10/8/2009
+1,但你的类代码与你给出的交互式 shell 结果不同。:P__str__
1赞 dbr 10/8/2009
呃,哎呀。.手动修改 REPL 输出永远不会有好结果。我可能应该对我的帖子进行文档测试:P
1赞 dbr 10/8/2009
字符串格式并未弃用,从 docs.python.org/whatsnew/2.6.html“% 运算符由更强大的字符串格式化方法 format() 补充”开始%
4赞 Ashwin Nanjappa 10/9/2009
Dbr:没错。请注意,“Python 3.0 中的新功能”文档还说“format() 方法 [...]我们的计划是最终使其成为字符串格式的唯一 API,并开始在 Python 3.1 中弃用 % 运算符。
1赞 Janusz Lenar 12/13/2011
皮蒂,非常方便。%
14赞 tnotstar 12/20/2012 #3

为了给@dbr的回答加上两分钱,以下是他引用的官方文档中如何实现这句话的例子:

"[...]返回一个字符串,该字符串在传递给 eval() 时将生成具有相同值的对象,[...]”

给定这个类定义:

class Test(object):
    def __init__(self, a, b):
        self._a = a
        self._b = b

    def __str__(self):
        return "An instance of class Test with state: a=%s b=%s" % (self._a, self._b)

    def __repr__(self):
        return 'Test("%s","%s")' % (self._a, self._b)

现在,可以很容易地序列化类的实例:Test

x = Test('hello', 'world')
print 'Human readable: ', str(x)
print 'Object representation: ', repr(x)
print

y = eval(repr(x))
print 'Human readable: ', str(y)
print 'Object representation: ', repr(y)
print

因此,运行最后一段代码,我们将得到:

Human readable:  An instance of class Test with state: a=hello b=world
Object representation:  Test("hello","world")

Human readable:  An instance of class Test with state: a=hello b=world
Object representation:  Test("hello","world")

但是,正如我在上一条评论中所说:更多信息就在这里

12赞 flow_chart 1/16/2013 #4

您需要使用 .这是一个标准函数,如 . 例如:__repr____init__

class Foobar():
    """This will create Foobar type object."""

    def __init__(self):
        print "Foobar object is created."

    def __repr__(self):
        return "Type what do you want to see here."

a = Foobar()

print a

评论

2赞 Eric Towers 7/12/2017
reprstr 具有不同的语义:repr 应该是 Python 源代码,它将(重新)创建相同的对象——这是它在代码中的 repr esentation;str 应该是对象的漂亮用户空间字符串化。
2赞 Stumpy 8/4/2015 #5

这个线程中已经有很多答案,但没有一个对我特别有帮助,我必须自己解决,所以我希望这个答案能提供更多信息。

你只需要确保你在课程结束时有括号,例如:

print(class())

下面是我正在处理的一个项目中的代码示例:

class Element:
    def __init__(self, name, symbol, number):
        self.name = name
        self.symbol = symbol
        self.number = number
    def __str__(self):
        return "{}: {}\nAtomic Number: {}\n".format(self.name, self.symbol, self.number

class Hydrogen(Element):
    def __init__(self):
        super().__init__(name = "Hydrogen", symbol = "H", number = "1")

为了打印我的氢类,我使用了以下方法:

print(Hydrogen())

请注意,如果没有 Hydrogen 末尾的括号,这将不起作用。它们是必要的。

希望这有帮助,如果您有其他问题,请告诉我。

82赞 user394430 9/18/2015 #6

可以应用于任何没有特定格式的类的通用方法可以按如下方式完成:

class Element:
    def __init__(self, name, symbol, number):
        self.name = name
        self.symbol = symbol
        self.number = number

    def __str__(self):
        return str(self.__class__) + ": " + str(self.__dict__)

然后

elem = Element('my_name', 'some_symbol', 3)
print(elem)

生产

__main__.Element: {'symbol': 'some_symbol', 'name': 'my_name', 'number': 3}
16赞 PeterM 5/20/2016 #7

对于 Python 3:

如果特定格式不重要(例如,用于调试),只需从下面的 Printable 类继承即可。无需为每个对象编写代码。

答案的启发

class Printable:
    def __repr__(self):
        from pprint import pformat
        return "<" + type(self).__name__ + "> " + pformat(vars(self), indent=4, width=1)

# Example Usage
class MyClass(Printable):
    pass

my_obj = MyClass()
my_obj.msg = "Hello"
my_obj.number = "46"
print(my_obj)

评论

0赞 kenyee 12/18/2021
当值有空格时,这看起来很时髦......
1赞 julian soro 10/5/2023
print(vars(obj))->对我来说已经足够好了,谢谢
21赞 Mike from PSG 3/14/2018 #8

更漂亮的 @user394430 回应版本

class Element:
    def __init__(self, name, symbol, number):
        self.name = name
        self.symbol = symbol
        self.number = number

    def __str__(self):
        return  str(self.__class__) + '\n'+ '\n'.join(('{} = {}'.format(item, self.__dict__[item]) for item in self.__dict__))

elem = Element('my_name', 'some_symbol', 3)
print(elem)

生成视觉上漂亮的名称和值列表。

<class '__main__.Element'>
name = my_name
symbol = some_symbol
number = 3

一个更高级的版本(感谢 Ruud)对项目进行了排序:

def __str__(self):
    return  str(self.__class__) + '\n' + '\n'.join((str(item) + ' = ' + str(self.__dict__[item]) for item in sorted(self.__dict__)))

评论

0赞 SleepyBoBos 3/4/2021
return ','.join(('{} = {}'.format(item, self.__dict__[item]) for item in self.__dict__)) .........把所有东西都放在一行上。我删除了类名,我只想打印值以进行调试
109赞 John 10/26/2018 #9

如果您遇到类似@Keith的情况,可以尝试:

print(a.__dict__)

这与我认为良好的风格背道而驰,但如果您只是想调试,那么它应该做您想要的。

评论

0赞 pranaygoyal02 2/4/2019
您知道如何知道 dict 键的值中是否有对象吗?
1赞 John 2/16/2019
@HadoopEvangelist 你是在问如何递归打印这些对象,还是只是确定是否存在对象?
4赞 Mohseen Mulla 11/11/2020
在快速调试方面,这是最好的答案之一。谢谢@John
0赞 sancho.s ReinstateMonicaCellio 11/22/2021
stackoverflow.com/a/32635523/2707864 基本相同
1赞 Sachin Dangol 3/28/2023
print(self.__dict__)也有效。在调试代码时特别有用,而没有 和 由类作者定义。__repr____str__
19赞 Alon 1/28/2021 #10

简单。在打印中,执行以下操作:

print(foobar.__dict__)

只要构造函数是

__init__

评论

0赞 NeronLeVelu 5/29/2022
部分有趣。它速度快且“内置”,但仅限于基本值类型。里面的新类对象将显示类类型,而不是内容。如此有用和有趣,使用,但与str_repr 所做的请求相比并不详尽。
9赞 minker 3/13/2021 #11

__repr__并且已经在许多答案中提到过。我只想补充一点,如果你懒得将这些魔术函数添加到你的类中,你可以使用 objprint。一个简单的装饰器将帮助您将方法添加到您的类中,您可以将其用于实例。当然,如果你愿意,你也可以使用库中的函数,以人类可读的格式打印任何任意对象。__str__@add_objprint__str__printobjprint

from objprint import add_objprint

class Position:
    def __init__(self, x, y):
        self.x = x
        self.y = y

@add_objprint
class Player:
    def __init__(self):
        self.name = "Alice"
        self.age = 18
        self.items = ["axe", "armor"]
        self.coins = {"gold": 1, "silver": 33, "bronze": 57}
        self.position = Position(3, 5)

print(Player())

输出是这样的

<Player
  .name = 'Alice',
  .age = 18,
  .items = ['axe', 'armor'],
  .coins = {'gold': 1, 'silver': 33, 'bronze': 57},
  .position = <Position
    .x = 3,
    .y = 5
  >
>
6赞 dheinz 8/24/2022 #12

尽管这是一篇较旧的帖子,但在数据类中也引入了一种非常方便的方法(从 Python 3.7 开始)。除了其他特殊函数(如 和)之外,它还为类属性提供了函数。那么你的例子将是:__eq____hash____repr__

from dataclasses import dataclass, field
@dataclass
class Test:
    a: str = field(default="foo")
    b: str = field(default="bar")

t = Test()
print(t) 
# prints Test(a='foo', b='bar')

如果要隐藏某个属性的输出,可以将字段装饰器参数设置为:reprFalse

@dataclass
class Test:
    a: str = field(default="foo")
    b: str = field(default="bar", repr=False)

t = Test()
print(t) 
# prints Test(a='foo')