str - python__repr__ example
Diferença entre__str__ e__repr__? (14)
Qual é a diferença entre __str__
e __repr__
em Python
?
Qual é a diferença entre
__str__
e__repr__
em Python?
__str__
(leia-se como "dunder (sublinhado duplo) string") e __repr__
(leia como "dunder-repper" (para "representação")) são ambos métodos especiais que retornam strings baseadas no estado do objeto.
__repr__
fornece o comportamento de backup se __str__
estiver faltando.
Portanto, deve-se primeiro escrever um __repr__
que permita a você reinstanciar um objeto equivalente da string que retorna, por exemplo, usando eval
ou digitando-o em character-for-character em um shell Python.
A qualquer momento, pode-se escrever um __str__
para uma representação de string legível pelo usuário da instância, quando se acredita ser necessário.
__str__
Se você imprimir um objeto ou passá-lo para format
str.format
ou str
, se um método __str__
for definido, esse método será chamado, caso contrário, __repr__
será usado.
__repr__
O método __repr__
é chamado pela função repr
e é o que é ecoado em seu shell python quando avalia uma expressão que retorna um objeto.
Como ele fornece um backup para __str__
, se você puder escrever apenas um, comece com __repr__
Aqui está a ajuda repr
em repr
:
repr(...)
repr(object) -> string
Return the canonical string representation of the object.
For most object types, eval(repr(object)) == object.
Isto é, para a maioria dos objetos, se você digitar o que é impresso por repr
, você deve ser capaz de criar um objeto equivalente. Mas esta não é a implementação padrão.
Implementação Padrão de __repr__
O objeto padrão __repr__
é ( fonte de C Python ) algo como:
def __repr__(self):
return '<{0}.{1} object at {2}>'.format(
self.__module__, type(self).__name__, hex(id(self)))
Isso significa que, por padrão, você imprimirá o módulo do qual o objeto é, o nome da classe e a representação hexadecimal de sua localização na memória - por exemplo:
<__main__.Foo object at 0x7f80665abdd0>
Essa informação não é muito útil, mas não há como derivar como alguém pode criar com precisão uma representação canônica de qualquer instância, e é melhor do que nada, pelo menos nos dizendo como podemos identificá-la na memória.
Como __repr__
pode ser útil?
Vamos ver como isso pode ser útil, usando os objetos shell e datetime
do Python. Primeiro precisamos importar o módulo datetime
:
import datetime
Se chamarmos datetime.now
no shell, veremos tudo de que precisamos para recriar um objeto de data e hora equivalente. Isto é criado pelo datetime __repr__
:
>>> datetime.datetime.now()
datetime.datetime(2015, 1, 24, 20, 5, 36, 491180)
Se imprimirmos um objeto datetime, veremos um bom formato legível por humanos (na verdade, ISO). Isso é implementado pelo __str__
de data e hora:
>>> print(datetime.datetime.now())
2015-01-24 20:05:44.977951
É simples recriar o objeto que perdemos porque não o atribuímos a uma variável copiando e colando da saída __repr__
e depois imprimindo-a, e a obtemos na mesma saída legível humana que o outro objeto:
>>> the_past = datetime.datetime(2015, 1, 24, 20, 5, 36, 491180)
>>> print(the_past)
2015-01-24 20:05:36.491180
Como faço para implementá-los?
Durante o desenvolvimento, você poderá reproduzir objetos no mesmo estado, se possível. Este, por exemplo, é como o objeto datetime define __repr__
( fonte Python ). É bastante complexo, por causa de todos os atributos necessários para reproduzir tal objeto:
def __repr__(self):
"""Convert to formal string, for repr()."""
L = [self._year, self._month, self._day, # These are never zero
self._hour, self._minute, self._second, self._microsecond]
if L[-1] == 0:
del L[-1]
if L[-1] == 0:
del L[-1]
s = ", ".join(map(str, L))
s = "%s(%s)" % ('datetime.' + self.__class__.__name__, s)
if self._tzinfo is not None:
assert s[-1:] == ")"
s = s[:-1] + ", tzinfo=%r" % self._tzinfo + ")"
return s
Se você quiser que seu objeto tenha uma representação legível mais humana, você poderá implementar __str__
seguida. Veja como o objeto datetime ( fonte Python ) implementa __str__
, o que ele faz facilmente porque já tem uma função para exibi-lo no formato ISO:
def __str__(self):
"Convert to string, for str()."
return self.isoformat(sep=' ')
Definir __repr__ = __str__
?
Esta é uma crítica de outra resposta aqui que sugere configurar __repr__ = __str__
.
Definir __repr__ = __str__
é bobo - __repr__
é um fallback para __str__
e um __repr__
, escrito para uso dos desenvolvedores na depuração, deve ser escrito antes de você escrever um __str__
.
Você precisa de um __str__
somente quando precisar de uma representação textual do objeto.
Conclusão
Defina __repr__
para os objetos que você escreve para que você e outros desenvolvedores tenham um exemplo reproduzível ao usá-lo enquanto você desenvolve. Defina __str__
quando precisar de uma representação de string legível por humanos.
Em resumo, o objetivo de
__repr__
é ser inequívoco e__str__
deve ser legível.
Aqui está um bom exemplo:
>>> import datetime
>>> today = datetime.datetime.now()
>>> str(today)
'2012-03-14 09:21:58.130922'
>>> repr(today)
'datetime.datetime(2012, 3, 14, 9, 21, 58, 130922)'
Leia esta documentação para repr:
repr(object)
Retorna uma string contendo uma representação imprimível de um objeto. Esse é o mesmo valor gerado pelas conversões (aspas reversas). Às vezes, é útil poder acessar essa operação como uma função comum. Para muitos tipos, essa função faz uma tentativa de retornar uma string que produziria um objeto com o mesmo valor quando passada para
eval()
, caso contrário, a representação é uma string entre colchetes que contém o nome do tipo do objeto juntos com informações adicionais, muitas vezes incluindo o nome e endereço do objeto. Uma classe pode controlar o que esta função retorna para suas instâncias definindo um__repr__()
.
Aqui está a documentação para str:
str(object='')
Retorna uma string contendo uma representação bem impressa de um objeto. Para strings, isso retorna a string em si. A diferença com
repr(object)
é questr(object)
nem sempre tenta retornar uma string que seja aceitável paraeval()
; seu objetivo é retornar uma string imprimível. Se nenhum argumento for dado, retorna a string vazia,''
.
A menos que você atue especificamente para garantir o contrário, a maioria das turmas não tem resultados úteis para:
>>> class Sic(object): pass
...
>>> print str(Sic())
<__main__.Sic object at 0x8b7d0>
>>> print repr(Sic())
<__main__.Sic object at 0x8b7d0>
>>>
Como você vê - nenhuma diferença, e nenhuma informação além da classe e id
do objeto. Se você substituir apenas um dos dois ...:
>>> class Sic(object):
... def __repr__(object): return 'foo'
...
>>> print str(Sic())
foo
>>> print repr(Sic())
foo
>>> class Sic(object):
... def __str__(object): return 'foo'
...
>>> print str(Sic())
foo
>>> print repr(Sic())
<__main__.Sic object at 0x2617f0>
>>>
como você vê, se você substituir __repr__
, isso também é usado para __str__
, mas não vice-versa.
Outros detalhes cruciais a saber: __str__
em um contêiner embutido usa o __repr__
, NÃO o __str__
, para os itens que ele contém. E, apesar das palavras sobre o assunto encontradas em documentos típicos, dificilmente alguém se incomoda em fazer o __repr__
de objetos ser uma string que eval
possa usar para construir um objeto igual (é muito difícil, e não saber como o módulo relevante foi realmente importado realmente impossível impossível).
Então, meu conselho: concentre-se em tornar __str__
razoavelmente legível, e __repr__
tão inequivocamente quanto possível, mesmo que isso interfira com a meta inatingível de tornar o valor retornado de __repr__
aceitável como entrada para __eval__
!
Além de todas as respostas dadas, gostaria de acrescentar alguns pontos:
1) __repr__()
é invocado quando você simplesmente escreve o nome do objeto no console python interativo e pressiona enter.
2) __str__()
é invocado quando você usa o objeto com a instrução print.
3) No caso, se __str__
estiver faltando, então print e qualquer função usando str()
chama __repr__()
do objeto.
4) __str__()
dos contêineres, quando invocado executará o __repr__()
de seus elementos contidos.
5) str()
chamado dentro de __str__()
poderia recorrer sem um caso base, e erro na profundidade máxima de recursão.
6) __repr__()
pode chamar repr()
que tentará evitar a recursão infinita automaticamente, substituindo um objeto já representado por ...
De http://pyref.infogami.com/__str__ por effbot:
__str__
"calcula a representação de string" informal "de um objeto. Isso difere de __repr__
por não precisar ser uma expressão válida do Python: uma representação mais conveniente ou concisa pode ser usada no lugar."
Em poucas palavras:
class Demo:
def __repr__(self):
return 'repr'
def __str__(self):
return 'str'
demo = Demo()
print(demo) # use __str__, output 'str' to stdout
s = str(demo) # __str__ is used, return 'str'
r = repr(demo) # __repr__ is used, return 'repr'
import logging
logger = logging.getLogger(logging.INFO)
logger.info(demo) # use __str__, output 'str' to stdout
from pprint import pprint, pformat
pprint(demo) # use __repr__, output 'repr' to stdout
result = pformat(demo) # use __repr__, result is string which value is 'str'
Excelentes respostas já cobrem a diferença entre __str__
e __repr__
, que para mim resume-se à primeira sendo legível até mesmo por um usuário final, e a última sendo o mais útil possível para os desenvolvedores. Dado que, eu acho que a implementação padrão de __repr__
muitas vezes não consegue atingir esse objetivo, porque omite informações úteis para os desenvolvedores.
Por essa razão, se eu tiver um __str__
simples o suficiente, eu geralmente tento obter o melhor dos dois mundos com algo como:
def __repr__(self):
return '{0} ({1})'.format(object.__repr__(self), str(self))
Minha regra __repr__
é: __repr__
é para desenvolvedores, __str__
é para clientes.
Na página 358 do livro Python scripting for computational science, de Hans Petter Langtangen, afirma claramente que
- O
__repr__
visa uma representação de string completa do objeto; - O
__str__
é para retornar um bom cordão para impressão.
Então, eu prefiro entendê-los como
- repr = reproduz
- str = string (representação)
do ponto de vista do usuário, embora este seja um mal-entendido que eu fiz ao aprender python.
Um exemplo pequeno, mas bom, também é dado na mesma página, como segue:
Exemplo
In [38]: str('s')
Out[38]: 's'
In [39]: repr('s')
Out[39]: "'s'"
In [40]: eval(str('s'))
Traceback (most recent call last):
File "<ipython-input-40-abd46c0c43e7>", line 1, in <module>
eval(str('s'))
File "<string>", line 1, in <module>
NameError: name 's' is not defined
In [41]: eval(repr('s'))
Out[41]: 's'
Para simplificar:
__str__
é usado para mostrar uma representação de string do seu objeto para ser lido facilmente por outros.
__repr__
é usado para mostrar uma representação de string do objeto.
Digamos que eu queira criar uma classe de Fraction
onde a representação de string de uma fração seja '(1/2)' e o objeto (classe de fração) seja representado como 'Fraction (1,2)'
Então podemos criar uma classe de fração simples:
class Fraction:
def __init__(self, num, den):
self.__num = num
self.__den = den
def __str__(self):
return '(' + str(self.__num) + '/' + str(self.__den) + ')'
def __repr__(self):
return 'Fraction (' + str(self.__num) + ',' + str(self.__den) + ')'
f = Fraction(1,2)
print('I want to represent the Fraction STRING as ' + str(f)) # (1/2)
print('I want to represent the Fraction OBJECT as ', repr(f)) # Fraction (1,2)
__repr__
é usado em todos os lugares, exceto por print
e str
quando um __str__
é definido
str
- Cria um novo objeto de string a partir do objeto dado.
repr
- Retorna a representação da string canônica do objeto.
As diferenças:
str ():
- torna o objeto legível
- gera saída para o usuário final
repr ():
- precisa de código que reproduza o objeto
- gera saída para o desenvolvedor
Alex resumiu bem, mas, surpreendentemente, foi muito sucinto.
Primeiro, deixe-me reiterar os principais pontos do post de Alex :
- A implementação padrão é inútil (é difícil pensar em uma que não seria, mas sim)
-
__repr__
objetivo__repr__
é ser inequívoco -
__str__
objetivo é ser legível - O
__str__
do__str__
usa objetos contidos '__repr__
Implementação padrão é inútil
Isso é principalmente uma surpresa porque os padrões do Python tendem a ser bastante úteis. No entanto, neste caso, ter um padrão para __repr__
que funcionaria como:
return "%s(%r)" % (self.__class__, self.__dict__)
teria sido muito perigoso (por exemplo, muito fácil entrar em recursão infinita se os objetos referirem-se uns aos outros). Então, o Python aparece fora. Observe que há um padrão que é verdadeiro: se __repr__
estiver definido, e __str__
não, o objeto se comportará como se __str__=__repr__
.
Isto significa, em termos simples: quase todos os objetos que você implementa devem ter um __repr__
funcional que seja utilizável para entender o objeto. A implementação de __str__
é opcional: faça isso se precisar de uma funcionalidade de “impressão bonita” (por exemplo, usada por um gerador de relatórios).
O objetivo do __repr__
é ser inequívoco
Deixe-me sair e dizer isso - eu não acredito em depuradores. Eu realmente não sei como usar qualquer depurador, e nunca usei um sério. Além disso, acredito que a grande falha nos depuradores é sua natureza básica - a maioria das falhas que depurei aconteceu há muito tempo, em uma galáxia muito distante. Isso significa que eu acredito, com fervor religioso, na extração de madeira. O registro é a força vital de qualquer sistema de servidores decente de ignorar e esquecer. O Python facilita o registro: com talvez alguns wrappers específicos do projeto, tudo que você precisa é de um
log(INFO, "I am in the weird function and a is", a, "and b is", b, "but I got a null C — using default", default_c)
Mas você tem que fazer a última etapa - certifique-se de que cada objeto que você implementa tenha uma repr, então um código como esse pode funcionar. É por isso que surge a coisa “eval”: se você tem informação suficiente para que eval(repr(c))==c
, isso significa que você sabe tudo o que há para saber sobre c
. Se isso for fácil, pelo menos de uma maneira imprecisa, faça-o. Se não, verifique se você tem informações suficientes sobre c
qualquer maneira. Eu costumo usar um formato de eval-like: "MyClass(this=%r,that=%r)" % (self.this,self.that)
. Isso não significa que você pode realmente construir MyClass, ou que esses são os argumentos construtores corretos - mas é uma forma útil para expressar "isso é tudo que você precisa saber sobre esta instância".
Nota: eu usei %r
acima, não %s
. Você sempre quer usar repr()
[ou %r
caractere de formatação, equivalentemente] dentro da implementação __repr__
, ou você está derrotando a meta de repr. Você quer ser capaz de diferenciar MyClass(3)
e MyClass("3")
.
O objetivo de __str__
é ser legível
Especificamente, não se destina a ser inequívoca - observe que str(3)==str("3")
. Da mesma forma, se você implementar uma abstração IP, ter a aparência de 192.168.1.1 está bem. Ao implementar uma abstração de data / hora, o str pode ser "2010/4/12 15:35:22", etc. O objetivo é representá-lo de uma maneira que um usuário, não um programador, gostaria de lê-lo. Cortar dígitos inúteis, fingir ser alguma outra classe - contanto que seja compatível com a legibilidade, é uma melhoria.
O __str__
do __str__
usa objetos contidos ' __repr__
Isso parece surpreendente, não é? É um pouco, mas quão legível seria
[moshe is, 3, hello
world, this is a list, oh I don't know, containing just 4 elements]
estar? Não muito. Especificamente, as cadeias de caracteres em um contêiner acham muito fácil perturbar sua representação de cadeia de caracteres. Em face da ambigüidade, lembre-se, o Python resiste à tentação de adivinhar. Se você quiser o comportamento acima quando estiver imprimindo uma lista, apenas
print "[" + ", ".join(l) + "]"
(provavelmente você também pode descobrir o que fazer com os dicionários.
Resumo
Implemente __repr__
para qualquer classe que você implementar. Isso deve ser uma segunda natureza. Implemente __str__
se você acha que seria útil ter uma versão de string que erra ao lado de maior legibilidade em favor de mais ambigüidade.
"A basic requirement for a Python object is to provide usable
string representations of itself, one used for debugging and
logging, another for presentation to end users. That is why the
special methods __repr__ and __str__ exist in the data model."
Do livro: Fluent Python