如何使用print()打印类的对象?

Ash*_*ppa 489 python printing class object

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

<__main__.Foobar instance at 0x7ff2a18c>
Run Code Online (Sandbox Code Playgroud)

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

如果您熟悉C++类,则可以通过为类ostream添加friend ostream& operator << (ostream&, const Foobar&)方法来实现上述标准.

Chr*_*utz 565

>>> class Test:
...     def __repr__(self):
...         return "Test()"
...     def __str__(self):
...         return "member of Test"
... 
>>> t = Test()
>>> t
Test()
>>> print(t)
member of Test
Run Code Online (Sandbox Code Playgroud)

__str__方法是在打印时发生的,并且该__repr__方法是在使用该repr()函数时(或者当您使用交互式提示查看它时).如果这不是最恐怖的方法,我道歉,因为我还在学习 - 但它有效.

如果没有__str__给出方法,Python将打印出结果__repr__.如果您定义__str__但不是__repr__,Python将使用您在上面看到的内容__repr__,但仍然__str__用于打印.

  • 我认为如果没有[另一个]链接(http://stackoverflow.com/a/2626364/68269),这个答案就无法完成! (11认同)
  • 还有一个__unicode__方法,你可以使用它而不是__Str__; 请注意它应该返回一个unicode对象,而不是一个字符串(但如果你返回一个字符串,无论如何都会转换为unicode ...) (10认同)
  • 对Java程序员来说:__str __(self)就像是python世界的toString() (10认同)

dbr*_*dbr 123

正如Chris Lutz所提到的,这是由__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)
Run Code Online (Sandbox Code Playgroud)

..it将在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
Run Code Online (Sandbox Code Playgroud)

如果没有__str__方法被定义,print(t)(或print(str(t)))将使用的结果__repr__,而不是

如果没有__repr__定义方法,则使用默认值,这几乎相当于..

def __repr__(self):
    return "<%s instance at %s>" % (self.__class__.__name__, id(self))
Run Code Online (Sandbox Code Playgroud)

  • Dbr:那是真的.请注意,"Python 3.0中的新功能"文档还说"format()方法[...]计划最终使其成为字符串格式化的唯一API,并开始在Python 3.1中弃用%运算符." (4认同)

use*_*430 43

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

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__)
Run Code Online (Sandbox Code Playgroud)

然后,

elem = Element('my_name', 'some_symbol', 3)
print(elem)
Run Code Online (Sandbox Code Playgroud)

产生

__main__.Element: {'symbol': 'some_symbol', 'name': 'my_name', 'number': 3}
Run Code Online (Sandbox Code Playgroud)


Alo*_*lon 20

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

print(foobar.__dict__)
Run Code Online (Sandbox Code Playgroud)

只要构造函数是

__init__
Run Code Online (Sandbox Code Playgroud)


Joh*_*ohn 18

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

print a.__dict__
Run Code Online (Sandbox Code Playgroud)

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

  • 当涉及到快速调试时,这是最好的答案之一。谢谢@约翰 (5认同)

Ant*_*dez 13

只是将我的两分钱加到@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)
Run Code Online (Sandbox Code Playgroud)

现在,很容易序列化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
Run Code Online (Sandbox Code Playgroud)

所以,运行最后一段代码,我们将得到:

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")
Run Code Online (Sandbox Code Playgroud)

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


小智 12

你需要使用__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
Run Code Online (Sandbox Code Playgroud)

  • __repr__和__str__具有不同的语义:__repr__应该是将(重新)创建相同对象的Python源-这是其在代码中的* repr *表示;__str__应该是对象的漂亮用户字符串。 (2认同)

Mik*_*eyB 9

@ 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)
Run Code Online (Sandbox Code Playgroud)

生成视觉上很好的名称和值列表.

<class '__main__.Element'>
name = my_name
symbol = some_symbol
number = 3
Run Code Online (Sandbox Code Playgroud)

一个更加漂亮的版本(感谢Ruud)对这些项目进行排序:

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


min*_*ker 9

__repr__ and __str__ are already mentioned in many answers. I just want to add that if you are too lazy to add these magic functions to your class, you can use objprint. A simple decorator @add_objprint will help you add the __str__ method to your class and you can use print for the instance. Of course if you like, you can also use objprint function from the library to print any arbitrary objects in human readable format.

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())
Run Code Online (Sandbox Code Playgroud)

The output is like

<Player
  .name = 'Alice',
  .age = 18,
  .items = ['axe', 'armor'],
  .coins = {'gold': 1, 'silver': 33, 'bronze': 57},
  .position = <Position
    .x = 3,
    .y = 5
  >
>
Run Code Online (Sandbox Code Playgroud)


Pet*_*erM 8

对于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)
Run Code Online (Sandbox Code Playgroud)


dhe*_*inz 6

尽管这是一篇较旧的文章,但数据类中还引入了一种非常方便的方法(从 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')
Run Code Online (Sandbox Code Playgroud)

如果你想隐藏某个属性不被输出,你可以将字段装饰器参数设置reprFalse

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

t = Test()
print(t) 
# prints Test(a='foo')
Run Code Online (Sandbox Code Playgroud)