【问题标题】:How to print instances of a class using print()?如何使用 print() 打印类的实例?
【发布时间】:2022-01-03 06:27:48
【问题描述】:

我正在学习 Python 的诀窍。当我尝试使用 print() 函数打印 Foobar 类的对象时,我得到如下输出:

<__main__.Foobar instance at 0x7ff2a18c>

有没有办法可以设置及其对象打印行为(或字符串表示) /em>?例如,当我在一个类对象上调用print() 时,我想以某种格式打印它的数据成员。如何在 Python 中实现这一点?

如果您熟悉 C++ 类,则可以通过为该类添加 friend ostream&amp; operator &lt;&lt; (ostream&amp;, const Foobar&amp;) 方法为标准 ostream 实现上述目标。

【问题讨论】:

    标签: python class printing object


    【解决方案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__ 进行打印。

    【讨论】:

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

    As Chris Lutz mentioned,这是由您类中的__repr__ 方法定义的。

    来自repr()的文档:

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

    给定以下类测试:

    class Test:
        def __init__(self, a, b):
            self.a = a
            self.b = b
    
        def __repr__(self):
            return "<Test a:%s b:%s>" % (self.a, self.b)
    
        def __str__(self):
            return "From str method of Test: a is %s, b is %s" % (self.a, 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):
        return "<%s instance at %s>" % (self.__class__.__name__, id(self))
    

    【讨论】:

    • +1 但您的类代码 __str__ 与您提供的交互式 shell 的结果不同。 :P
    • Err,哎呀.. 手动修改 REPL 输出永远不会结束。我可能应该对我的帖子进行 doctest :P
    • % 字符串格式不被弃用,来自docs.python.org/whatsnew/2.6.html "% 运算符由更强大的字符串格式方法 format()补充"跨度>
    • Dbr:确实如此。请注意,“Python 3.0 中的新增功能”文档还说“format() 方法 [...] 计划最终使其成为字符串格式化的唯一 API,并开始弃用 Python 3.1 中的 % 运算符。”
    • 皮蒂,% 已经很方便了。
    【解决方案3】:

    一种可以应用于任何类而无需特定格式的通用方法可以如下完成:

    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}
    

    【讨论】:

      【解决方案4】:

      如果你遇到@Keith 这样的情况,你可以试试:

      print(a.__dict__)
      

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

      【讨论】:

      • 您知道如何知道 dict 键的值中是否包含对象吗?
      • @HadoopEvangelist 您是在问如何递归地打印这些对象还是仅仅确定是否有对象?
      • 这是关于快速调试的最佳答案之一。谢谢@约翰
      【解决方案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__) + '\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__)) ...... ..把everyting放在一条线上。我删除了类名,我只是想打印值以进行调试
      【解决方案6】:

      只是为了在@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

      【讨论】:

        【解决方案7】:

        对于 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)
        

        【讨论】:

        • 当值有空格时,这看起来很时髦......
        【解决方案8】:

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

        【讨论】:

        • reprstr 具有不同的语义:repr 应该是 Python 源,可以(重新)创建相同的object - 这是它在代码中的 representation ; str 应该是对象的漂亮用户态字符串化。
        【解决方案9】:

        简单。在打印中,执行:

        print(foobar.__dict__)
        

        只要构造函数是

        __init__
        

        【讨论】:

          【解决方案10】:

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

          你只需要确保在你的类的末尾有括号,例如:

          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 末尾的括号,这将不起作用。它们是必要的。

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

          【讨论】:

            【解决方案11】:

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

            【讨论】:

              猜你喜欢
              • 2021-08-02
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多