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

2024-11-20 08:44:00
admin
原创
7
摘要:问题描述:当我尝试print某个类的实例时,我得到了如下输出:>>> class Test(): ... def __init__(self): ... self.a = 'foo' ... >>> print(Test()) <__main_...

问题描述:

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

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

我怎样才能使它显示print自定义内容(例如包含属性值的内容a)?也就是说,我怎样才能定义类的实例在打印时将如何显示(它们的字符串表示)?


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


解决方案 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()

如果没有__str__指定方法,Python 将打印 的结果__repr__。如果您定义了__str__但没有定义__repr__,Python 将使用上面看到的__repr__,但仍使用__str__进行打印。

解决方案 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)}>"

解决方案 3:

如果你处于像@Keith这样的情形你可以尝试:

print(a.__dict__)

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

解决方案 4:

可以应用于任何类且不需要特定格式的通用方法如下:

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}

解决方案 5:

@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__) + '
'+ '
'.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__) + '
' + '
'.join((str(item) + ' = ' + str(self.__dict__[item]) for item in sorted(self.__dict__)))

解决方案 6:

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

print(foobar.__dict__)

只要构造函数是

__init__

解决方案 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)

解决方案 8:

我只是想对@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")

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

解决方案 9:

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

解决方案 10:

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

解决方案 11:

虽然这是一篇较旧的文章,但dataclasses中也引入了一种非常方便的方法(从 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')

解决方案 12:

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

您只需确保在课程末尾有括号,例如:

print(class())

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

class Element:
    def __init__(self, name, symbol, number):
        self.name = name
        self.symbol = symbol
        self.number = number
    def __str__(self):
        return "{}: {}
Atomic Number: {}
".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 末尾没有括号,则此操作无效。它们是必需的。

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

解决方案 13:

以上答案都对我没用。就我而言,我必须确保 myr 类末尾有括号,例如:

print(class())

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

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

class Hydrogen(Element):
    def __init__(self):
        super().__init__(name = "Hydrogen", symbol = "H", number = "1")
相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用