ChatGPT解决这个技术问题 Extra ChatGPT

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

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

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

如何定义类及其实例的打印行为(或字符串表示)?例如,参考上面的代码,如何修改 Test 类以使 print 实例显示 a 值?


B
Boris Verkhovskiy
>>> 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() 函数(或当您使用交互式提示查看它时)发生的事情。

如果没有给出 __str__ 方法,Python 将改为打印 __repr__ 的结果。如果您定义 __str__ 但未定义 __repr__,Python 将使用您在上面看到的 __repr__,但仍使用 __str__ 进行打印。


还有一个 unicode 方法,您可以使用它来代替 Str ;请注意,它应该返回一个 unicode 对象,而不是一个字符串(但如果您返回一个字符串,无论如何都会完成到 unicode 的转换......)
@kender - 我不知道,但回想起来,鉴于 Python 2.x 的 Unicode 处理不完善,这非常有意义。
我认为如果没有指向 this other one 的链接,这个答案就无法完成!
救了我!但是重新实现__repr__(self)方法后,print会误导用户。你知道这方面的任何最佳实践吗?
对 Java 程序员:__str__(self) 就像 Python 世界的 toString()
K
Karl Knechtel

As Chris Lutz explains,这是由您的类中的 __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__ 方法,则使用默认值,其中 is roughly equivalent 用于:

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

+1,但您的类代码的 __str__ 与您提供的交互式 shell 的结果不同。 :P
错误,哎呀.. 手动修改 REPL 输出永远不会结束。我可能应该对我的帖子进行 doctest:P
% 字符串格式未被弃用,来自 docs.python.org/whatsnew/2.6.html“% 运算符由更强大的字符串格式方法 format()补充
Dbr:这是真的。请注意,“Python 3.0 中的新增功能”文档还说“format() 方法 [...] 计划最终使其成为字符串格式化的唯一 API,并开始弃用 Python 3.1 中的 % 运算符。”
皮蒂,% 很方便。
u
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__) + ": " + str(self.__dict__)

接着,

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

生产

__main__.Element: {'symbol': 'some_symbol', 'name': 'my_name', 'number': 3}

J
John

如果您处于 @Keith 这样的情况,您可以尝试:

print(a.__dict__)

它违背了我认为好的风格,但如果你只是想调试,那么它应该做你想做的事。


您知道如何知道 dict 键的值中是否包含对象吗?
@HadoopEvangelist您是在问如何递归地打印这些对象还是只是确定是否有对象?
当涉及到快速调试时,这是最好的答案之一。谢谢@约翰
M
Mike from PSG

@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__)))

return ','.join(('{} = {}'.format(item, self.__dict__[item]) for item in self.__dict__)) .........将所有内容放在一行上。我删除了类名,我只是想打印值以进行调试
C
Community

对于 Python 3:

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

this答案启发

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)

当值有空格时,这看起来很时髦......
C
Community

只是将我的两分钱添加到@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")

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


A
Alon

简单的。在打印中,执行:

print(foobar.__dict__)

只要构造函数是

__init__

部分有趣。它快速且“内置”,但仅限于基本值类型。内部的新类对象将显示类类型而不是内容。与 str_ 和 repr 之类的请求相比,使用起来非常有用且有趣,但并不详尽。
R
Robᵩ

您需要使用 __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

repr 和 str 具有不同的语义: repr 应该是 Python 源代码,它将(重新)创建相同的对象——这是它在代码中的表示; str 应该是对象的漂亮用户态字符串化。
m
minker

__repr____str__ 已在许多答案中提及。我只是想补充一点,如果你懒得在你的类中添加这些神奇的功能,你可以使用 objprint。一个简单的装饰器 @add_objprint 将帮助您将 __str__ 方法添加到您的类中,您可以将 print 用于实例。当然,如果您愿意,也可以使用库中的 objprint 函数以人类可读的格式打印任意对象。

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

S
Stumpy

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

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

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")

为了打印我的 Hydrogen 课程,我使用了以下内容:

print(Hydrogen())

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

希望这会有所帮助,如果您还有问题,请告诉我。