Как распечатать экземпляры класса, используя print ()?

539

Я изучаю веревки в Python. Когда я пытаюсь напечатать объект класса, Foobarиспользуя print()функцию, я получаю вывод, подобный этому:

<__main__.Foobar instance at 0x7ff2a18c>

Есть ли способ, которым я могу установить поведение печати (или строковое представление ) класса и его объектов ? Например, когда я вызываю print()объект класса, я хотел бы напечатать его элементы данных в определенном формате. Как этого добиться в Python?

Если вы знакомы с классами C ++, то для стандарта можно достичь выше ostream, добавив friend ostream& operator << (ostream&, const Foobar&)метод для класса.

Эшвин Нанджаппа
источник

Ответы:

629
>>> 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()функцию (или , если смотреть на него с интерактивной подсказкой). Если это не самый Pythonic метод, я прошу прощения, потому что я все еще учусь - но это работает.

Если __str__метод не указан, Python выведет результат __repr__вместо. Если вы определили, __str__но нет __repr__, Python будет использовать то, что вы видите выше __repr__, но все еще будете использовать __str__для печати

Крис Лутц
источник
11
есть также метод Unicode , который вы можете использовать вместо Str ; обратите внимание, что он должен возвращать объект Unicode, а не строку (но если вы вернете строку, преобразование в Unicode будет выполнено в любом случае ...)
kender
@kender - я не знал об этом, но в ретроспективе это имеет смысл, учитывая неработающую обработку Unicode в Python 2.x.
Крис Латс
11
Я думаю, что этот ответ не может быть завершен без ссылки на этот другой !
tnotstar
Спас меня! Однако после повторной реализации метода __repr __ (self) print введет пользователей в заблуждение. Знаете ли вы о каких-либо лучших практиках вокруг этого?
Viet
10
Для программистов на Java: __str __ (self) похож на toString () мира питонов
Janac Meena
134

Как упоминал Крис Латс , это определяется __repr__методом в вашем классе.

Из документации repr():

Для многих типов эта функция пытается вернуть строку, которая при передаче в объект выдаст объект с тем же значением eval(), в противном случае представление представляет собой строку, заключенную в угловые скобки, которая содержит имя типа объекта вместе с дополнительной информацией. часто в том числе название и адрес объекта. Класс может управлять тем, что эта функция возвращает для своих экземпляров, определяя __repr__()метод.

Дан следующий класс Test:

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)

..it будет действовать следующим образом в оболочке Python:

>>> 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))
DBR
источник
+1, но код вашего класса __str__отличается от результатов интерактивной оболочки, которые вы даете. : P
Крис Лутц
1
Ой, упс .. ручное изменение вывода REPL никогда не заканчивается хорошо. Я, вероятно, должен проверить мои сообщения: P
dbr
1
%Строка форматирования не рекомендуется, от docs.python.org/whatsnew/2.6.html «оператор% будет дополнен более мощным строки метод, формат (форматирование)»
DBR
4
Dbr: Это правда. Обратите внимание, что в документе «Что нового в Python 3.0» также написано «метод format () [...] В конечном итоге планируется сделать этот API-интерфейс единственным для форматирования строк и начать исключать оператор% в Python 3.1».
Эшвин Нанджаппа
1
Питти, %было очень удобно.
Януш Ленар
52

Общий способ, который можно применить к любому классу без специального форматирования, можно сделать следующим образом:

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}
user394430
источник
23

Если вы находитесь в такой ситуации, как @Keith, вы можете попробовать:

print a.__dict__

Это идет вразрез с тем, что я считаю хорошим стилем, но если вы просто пытаетесь отлаживать, тогда он должен делать то, что вы хотите.

Джон
источник
Вы знаете, как узнать, имеет ли ключ dict объекты в своих значениях?
pranaygoyal02
1
@HadoopEvangelist Вы спрашиваете, как рекурсивно печатать эти объекты, или просто определить, есть ли объекты?
Джон
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)

Теперь легко сериализовать экземпляр 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")

Но, как я сказал в своем последнем комментарии: больше информации только здесь !

tnotstar
источник
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
flow_chart
источник
2
магнезии и ул имеют различную семантику: магнезии должны быть Python источником , который будет (перо) создать один и тот же объект - это его магнезия esentation в коде; str должен быть симпатичной пользовательской странификацией объекта.
Эрик Тауэрс
12

Более симпатичная версия ответа от @ 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

Еще более модная версия (спасибо Рууду) сортирует предметы:

def __str__(self):
    return  str(self.__class__) + '\n' + '\n'.join((str(item) + ' = ' + str(self.__dict__[item]) for item in sorted(self.__dict__)))
MikeyB
источник
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)
PeterM
источник
1

В этой ветке уже есть много ответов, но ни один из них мне особо не помог, мне пришлось самому решать их, поэтому я надеюсь, что этот будет немного более информативным.

Вы просто должны убедиться, что у вас есть скобки в конце вашего класса, например:

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

Обратите внимание, что это не будет работать без скобок в конце водорода. Они необходимы.

Надеюсь, это поможет, дайте мне знать, если у вас есть еще вопросы.

приземистый
источник