Como imprimir instâncias de uma classe usando print ()?

539

Estou aprendendo as cordas em Python. Quando tento imprimir um objeto de classe Foobarusando a print()função, recebo uma saída como esta:

<__main__.Foobar instance at 0x7ff2a18c>

Existe uma maneira de definir o comportamento de impressão (ou a representação de cadeias ) de uma classe e seus objetos ? Por exemplo, quando eu chamo print()um objeto de classe, gostaria de imprimir seus membros de dados em um determinado formato. Como conseguir isso em Python?

Se você estiver familiarizado com as classes C ++, é possível obter o padrão acima ostreamadicionando um friend ostream& operator << (ostream&, const Foobar&)método para a classe.

Ashwin Nanjappa
fonte

Respostas:

629
>>> class Test:
...     def __repr__(self):
...         return "Test()"
...     def __str__(self):
...         return "member of Test"
... 
>>> t = Test()
>>> t
Test()
>>> print(t)
member of Test

O __str__método é o que acontece quando você o imprime, e o __repr__método é o que acontece quando você usa a repr()função (ou quando a analisa com o prompt interativo). Se esse não é o método mais pitonico , peço desculpas, porque ainda estou aprendendo também - mas funciona.

Se nenhum __str__método for fornecido, o Python imprimirá o resultado __repr__. Se você definir, __str__mas não o __repr__, o Python usará o que você vê acima como o __repr__, mas ainda o utilizará __str__para impressão.

Chris Lutz
fonte
11
há também um método unicode , que você pode usar em vez de Str ; Note-se que ele deve retornar um objeto unicode, não uma string (mas se você retornar uma string, a conversão para Unicode será feito de qualquer maneira ...)
kender
@kender - Eu não sabia disso, mas, em retrospecto, faz todo o sentido dado o tratamento Unicode quebrado do Python 2.x.
8263 Chris Lutz
11
Penso que esta resposta não pode ser concluída sem um link para esta outra !
Tnotstar
Me salvou! No entanto, após reimplementar o método __repr __ (próprio), a impressão enganará os usuários. Você está ciente das melhores práticas para isso?
Viet
10
Para programadores Java: __str __ (self) é como o toString () do mundo do python
Janac Meena
134

Como Chris Lutz mencionou , isso é definido pelo __repr__método em sua classe.

A partir da documentação de repr():

Para muitos tipos, essa função tenta retornar uma sequência que daria origem a um objeto com o mesmo valor quando transmitida eval(); caso contrário, a representação é uma sequência entre colchetes angulares que contém o nome do tipo do objeto juntamente com informações adicionais geralmente incluindo o nome e o endereço do objeto. Uma classe pode controlar o que essa função retorna para suas instâncias, definindo um __repr__()método.

Dada a seguinte classe Teste:

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 agirá da seguinte maneira no shell 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

Se nenhum __str__método é definido, print(t)(ou print(str(t))) vai usar o resultado de __repr__, em vez

Se nenhum __repr__método for definido, o padrão será usado, o que é praticamente equivalente a ..

def __repr__(self):
    return "<%s instance at %s>" % (self.__class__.__name__, id(self))
dbr
fonte
+1, mas o código da sua classe __str__é diferente dos resultados do shell interativo que você fornece. : P
Chris Lutz
1
Err, opa .. modificar manualmente a saída REPL nunca termina bem. Provavelmente eu deveria doctest minhas postagens: P
dbr
1
A %formatação da string não está obsoleta, de docs.python.org/whatsnew/2.6.html "o operador% é complementado por um método mais poderoso de formatação de string, format ()"
dbr
4
Dbr: Isso é verdade. Observe que o documento "O que há de novo no Python 3.0" também diz "método format () [...] O plano é tornar essa a única API para formatação de string e começar a descontinuar o operador% no Python 3.1".
Ashwin Nanjappa 9/10/09
1
Pitty, tem %sido muito conveniente.
Janusz Lenar
52

Uma maneira genérica que pode ser aplicada a qualquer classe sem formatação específica pode ser feita da seguinte maneira:

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

E depois,

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

produz

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

Se você estiver em uma situação como @Keith, tente:

print a.__dict__

Isso vai contra o que eu consideraria um bom estilo, mas se você estiver apenas tentando depurar, deve fazer o que quiser.

John
fonte
Você saberia se a chave dict tem objetos em seus valores?
precisa saber é o seguinte
1
@HadoopEvangelist Você está perguntando como imprimir recursivamente esses objetos ou apenas determinar se existem objetos?
João
13

Apenas para adicionar meus dois centavos à resposta do @ dbr, a seguir está um exemplo de como implementar esta frase a partir da documentação oficial que ele citou:

"[...] retornar uma string que produziria um objeto com o mesmo valor quando passado para eval (), [...]"

Dada esta definição de classe:

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)

Agora, é fácil serializar a instância da Testclasse:

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

Então, executando o último pedaço de código, obteremos:

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

Mas, como eu disse no meu último comentário: mais informações estão aqui !

tnotstar
fonte
12

Você precisa usar __repr__. Esta é uma função padrão como __init__. Por exemplo:

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
fonte
2
repr e str têm semânticas diferentes: repr deve ser uma fonte Python que (re) criaria o mesmo objeto - essa é sua representação no código; str deve ser uma bonita string de usuário do objeto.
Eric Towers
12

Uma versão mais bonita da resposta de @ 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)

Produz lista visualmente agradável de nomes e valores.

<class '__main__.Element'>
name = my_name
symbol = some_symbol
number = 3

Uma versão ainda mais sofisticada (graças ao Ruud) classifica os itens:

def __str__(self):
    return  str(self.__class__) + '\n' + '\n'.join((str(item) + ' = ' + str(self.__dict__[item]) for item in sorted(self.__dict__)))
MikeyB
fonte
8

Para Python 3:

Se o formato específico não for importante (por exemplo, para depuração), basta herdar da classe Printable abaixo. Não há necessidade de escrever código para cada objeto.

Inspirado por esta resposta

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

Já existem muitas respostas neste tópico, mas nenhuma delas me ajudou particularmente, eu tive que resolver isso sozinho, então espero que este seja um pouco mais informativo.

Você só precisa ter parênteses no final da sua aula, por exemplo:

print(class())

Aqui está um exemplo de código de um projeto no qual eu estava trabalhando:

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

Para imprimir minha classe de hidrogênio, usei o seguinte:

print(Hydrogen())

Observe que isso não funcionará sem os parênteses no final do hidrogênio. Eles são necessários.

Espero que isso ajude, deixe-me saber se você tiver mais perguntas.

Stumpy
fonte