str - python__repr__ example




Diferença entre__str__ e__repr__? (14)

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.

Qual é a diferença entre __str__ e __repr__ em Python ?


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) é que str(object) nem sempre tenta retornar uma string que seja aceitável para eval() ; 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





repr