Pergunta

O que é a diferença entre __str__ e __repr__ em Python?

Foi útil?

Solução

Alex resumiu bem, mas, surpreendentemente, foi muito sucinto.

Em primeiro lugar, deixe-me reiterar os pontos principais de Alex pós :

  • A implementação padrão é inútil (é difícil pensar em uma que não seria, mas sim)
  • objetivo __repr__ é ser inequívoca
  • objetivo __str__ é para ser lido
  • usos __str__ do contêiner continha __repr__ objetos

Implementação padrão é inútil

Isto é mais uma surpresa, porque os padrões do Python tendem a ser bastante útil. No entanto, neste caso, ter um padrão para __repr__ que agiria 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 referência uns aos outros). Então Python policiais fora. Note-se que há um padrão que é verdade:. Se __repr__ é definido, e __str__ não é, o objeto vai se comportar como se __str__=__repr__

Isto significa, em termos simples: quase todos os objetos que você implementar devem ter um __repr__ funcional que é útil para a compreensão do objeto. Implementação __str__ é opcional: fazer isso se você precisa de uma funcionalidade “Pretty print” (por exemplo, usado por um gerador de relatório)

.

O objetivo da __repr__ é ser inequívoca

Deixe-me sair bem e dizê-lo - Eu não acredito em depuradores. Eu realmente não sei como usar qualquer depurador, e nunca ter usado um gravemente. Além disso, acredito que a grande falha no depuradores é a sua natureza básica - a maioria das falhas de depuração que aconteceu há muito tempo atrás, em uma galáxia muito, muito distante. Isso significa que eu acredito que, com fervor religioso, no registro. Logging é a alma de qualquer e fogo-esquecer sistema decente servidor. Python torna fácil para iniciar sessão: com talvez alguns invólucros 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 o último passo - garantir que cada objeto que você implementar tem uma repr útil, assim como código que pode apenas trabalho. É por isso que a coisa “eval” trata-se: se você tem informações suficientes para eval(repr(c))==c, isso significa que você sabe tudo que há para saber sobre c. Se isso é fácil, pelo menos de uma forma difusa, fazê-lo. Se não, verifique se você tem informação suficiente sobre c de qualquer maneira. Eu costumo usar um eval-like formato: "MyClass(this=%r,that=%r)" % (self.this,self.that). Isso não significa que você pode realmente construir MyClass, ou que aqueles são os argumentos do construtor certas -. Mas é uma forma útil para expressar “isto é tudo o que você precisa saber sobre esta ocorrência”

Nota: Eu %r utilizado acima, não %s. Você sempre quer usar repr() [ou formatação de caracteres %r, equivalentemente] dentro implementação __repr__, ou você está derrotando o objetivo de repr. Você quer ser capaz de MyClass(3) diferenciar e MyClass("3").

O objetivo da __str__ é para ser lido

Especificamente, ele não se destina a ser inequívoca - aviso de que str(3)==str("3"). Da mesma forma, se você implementar uma abstração IP, tendo o str de que pareça que 192.168.1.1 é apenas multa. Ao implementar uma abstração data / hora, o str pode ser "2010/04/12 15:35:22", etc. O objetivo é representá-lo de uma forma que um usuário, não um programador, gostaria de lê-lo. Cortar dígitos inúteis, fingir ser uma outra classe -. Contanto que é compatível com a legibilidade, é uma melhoria

usos __str__ do contêiner continha objetos __repr__

Isto parece surpreendente, não é? É um pouco, mas como legível faria

[moshe is, 3, hello
world, this is a list, oh I don't know, containing just 4 elements]

ser? Não muito. Especificamente, a sTrings em um recipiente iria encontrá-lo muito fácil para perturbar sua representação de seqüência. Diante da ambiguidade, lembre-se, Python resiste à tentação de adivinhar. Se quiser que o comportamento acima quando você está imprimindo uma lista, apenas

print "[" + ", ".join(l) + "]"

(provavelmente você pode também descobrir o que fazer sobre dicionários.

Resumo

Implementar __repr__ para qualquer classe de implementar. Esta deve ser uma segunda natureza. Implementar __str__ se você acha que seria útil ter uma versão corda que erra no lado de leitura.

Outras dicas

A minha regra de ouro:. __repr__ é para desenvolvedores, __str__ é para clientes

A menos que você agir especificamente para garantir o contrário, a maioria das classes não temos resultados votos para qualquer um:

>>> 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ê só substituir 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__, que também é usado para __str__, mas não vice-versa.

Outros petiscos cruciais a saber: __str__ em um built-on usos contêiner __repr__, NÃO o __str__, para os itens que ele contém. E, apesar das palavras sobre o assunto encontrados nos docs típicas, quase não incomoda qualquer um fazendo a __repr__ de objetos ser uma cadeia que eval pode usar para construir um objeto igual (é muito difícil, e não saber como o módulo relevante foi realmente marcas importadas ele realmente flat out impossível).

Então, meu conselho: foco em tornar __str__ razoavelmente legível, e __repr__ como inequívoca quanto possível, mesmo que interfere com o objetivo inatingível difusa de fazer valor retornado do __repr__ aceitável como entrada para __eval__

__repr__ : representação do objeto python normalmente eval irá convertê-lo de volta para o objeto

__str__ : é o que você acha que é esse objeto em forma de texto

por exemplo.

>>> s="""w'o"w"""
>>> repr(s)
'\'w\\\'o"w\''
>>> str(s)
'w\'o"w'
>>> eval(str(s))==s
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1
    w'o"w
       ^
SyntaxError: EOL while scanning single-quoted string
>>> eval(repr(s))==s
True

Em suma, o objetivo do __repr__ é ser inequívoca e __str__ é 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 de impressão de um objeto. Este é o mesmo valor produzidos por conversões (reverso citações). Às vezes é útil para ser capaz de acessar esta operação como uma função comum. Para muitos tipos, esta função faz uma tentativa para devolver uma cadeia que iria produzir um objecto com o mesmo valor quando passado para eval(), caso contrário, a representação é uma cadeia entre colchetes que contém o nome do tipo de objecto juntamente 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 as suas instâncias, definindo um método __repr__().

Aqui está a documentação para str:

str(object='')

Retorna uma string contendo um bem para impressão representação de um objecto. Para strings, este retorna a string em si. A diferença com repr(object) é que str(object) não sempre tentar devolver uma cadeia que é aceitável para eval(); Está objetivo é retornar uma string de impressão. Se nenhum argumento for fornecido, retorna a cadeia vazia, ''.

O que é a diferença entre __str__ e __repr__ em Python?

__str__ (leia-se "Dunder (duplo sublinhado) string") e __repr__ (leia-se "Dunder-repper" (para "representação")) são os dois métodos especiais que as cordas de retorno com base no estado do objeto.

__repr__ fornece o comportamento de backup se __str__ está faltando.

Assim, um primeiro deve escrever uma __repr__ que lhe permite reinstantiate um objeto equivalente a partir da cadeia ele retorna por exemplo usando eval ou digitando-o em caractere por caractere em um shell Python.

A qualquer momento posterior, pode-se escrever uma __str__ para uma representação de cadeia legível pelo usuário do exemplo, quando se acredita que seja necessário.

__str__

Se você imprimir um objeto, ou passá-lo para format, str.format, ou str, em seguida, se um método __str__ é definido, esse método será chamado, caso contrário, será usado __repr__.

__repr__

O método __repr__ é chamado pela função repr embutido e é o que é ecoado em seu shell python quando se avalia uma expressão que retorna um objeto.

Uma vez que fornece um backup para __str__, se você só pode escrever um, começar com __repr__

Aqui está a ajuda embutida 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 pelo repr, você deve ser capaz de criar um objeto equivalente. Mas esta não é a implementação padrão.

Padrão Implementação de __repr__

O objeto padrão __repr__ é ( C Python fonte ) 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ê vai imprimir o módulo do objeto é de, o nome da classe, e a representação hexadecimal de sua localização na memória - por exemplo:

<__main__.Foo object at 0x7f80665abdd0>

Esta informação não é muito útil, mas não há nenhuma maneira de derivar como se pode criar com precisão uma representação canônica de qualquer instância, e é melhor do que nada, pelo menos nos dizer como podemos identificá-lo exclusivamente na memória.

Como pode __repr__ ser útil?

Vamos olhar como ele pode ser útil, usando o shell Python e objetos datetime. Primeiro, precisamos importar o módulo datetime:

import datetime

Se chamarmos datetime.now no shell, vamos ver tudo o que precisamos para recriar um objeto datetime equivalente. Este é criado pelo __repr__ data e hora:

>>> datetime.datetime.now()
datetime.datetime(2015, 1, 24, 20, 5, 36, 491180)

Se imprimir um objeto de data e hora, vemos um bom legível (na verdade, ISO) formato. Isso é implementado por __str__ de data e hora:

>>> print(datetime.datetime.now())
2015-01-24 20:05:44.977951

É uma simples questão de recriar o objeto perdemos porque não atribuí-la a uma variável, copiando e colando a partir da saída __repr__, e, em seguida, imprimi-lo, e nós obtê-lo na mesma saída legível como 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 posso implementá-las?

Como você está desenvolvendo, você vai querer ser capaz de reproduzir objetos no mesmo estado, se possível. Isto, por exemplo, é como a data e hora de objecto define __repr__ ( Python fonte ). É 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 = "%s.%s(%s)" % (self.__class__.__module__,
                       self.__class__.__qualname__,
                       ", ".join(map(str, L)))
    if self._tzinfo is not None:
        assert s[-1:] == ")"
        s = s[:-1] + ", tzinfo=%r" % self._tzinfo + ")"
    if self._fold:
        assert s[-1:] == ")"
        s = s[:-1] + ", fold=1)"
    return s

Se você quiser que o seu objeto para ter uma representação legível mais humano, você pode implementar __str__ seguinte. Veja como o objeto de data e hora ( Python fonte ) implementos __str__, que facilmente faz, porque ele já tem uma função para exibição -lo em formato ISO:

def __str__(self):
    "Convert to string, for str()."
    return self.isoformat(sep=' ')

Set __repr__ = __str__?

Esta é uma crítica da outra resposta aqui que sugere a criação __repr__ = __str__.

Configuração __repr__ = __str__ é bobagem -. __repr__ é um fallback para __str__ e uma __repr__, escrito para uso desenvolvedores na depuração, deve ser escrito antes de escrever uma __str__

Você precisa de um __str__ somente quando você precisa de uma representação textual do objeto.

Conclusão

Definir __repr__ para objetos que você escreve para que você e outros desenvolvedores têm um exemplo reproduzível quando usá-lo como você desenvolver. Definir __str__ quando você precisa de uma representação de cadeia legível dele.

Além de todas as respostas dadas, eu gostaria de acrescentar alguns pontos: -

1) __repr__() é invocado quando você nome simplesmente write do objeto no console python interativo e pressione enter.

2) __str__() é invocado quando você usa objeto com declaração de impressão.

3) No caso, se __str__ está faltando, então imprimir e qualquer função usando invoca str() __repr__() de objeto.

4) __str__() de recipientes, quando invocado irá executar método __repr__() dos seus elementos contidos.

5) str() chamado dentro __str__() poderia potencialmente recurse sem um caso base, e erro na profundidade máxima de recursão.

6) __repr__() pode chamar repr() que tentará evitar recursão infinita automaticamente, substituindo um objeto já representado com ....

Na página 358 do livro Python scripting para a ciência computacional por Hans Petter Langtangen, ele afirma claramente que

  • Os objectivos __repr__ em uma representação de cadeia completa do objeto;
  • O __str__ é retornar uma string agradável para a impressão.

Então, eu prefiro entendê-los como

  • repr = reproduzir
  • str = string (representação)

Do ponto de vista do usuário embora este é um mal-entendido que eu fiz quando aprender python.

Um pequeno, mas bom exemplo também é dada na mesma página da seguinte forma:

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'

Em toda a honestidade, eval(repr(obj)) nunca é usada. Se você encontrar-se usá-lo, você deve parar, porque eval é perigoso, e as cordas são uma maneira muito ineficiente para serializar seus objetos (uso pickle vez).

Por isso, eu recomendaria configuração __repr__ = __str__. A razão é que as chamadas str(list) repr sobre os elementos (eu considero que este seja um dos maiores falhas de projeto de Python que não foi abordado por Python 3). Um repr real provavelmente não será muito útil como a saída de print [your, objects].

Para se qualificar isso, na minha experiência, o caso de uso útil maior parte da função repr é colocar uma string dentro de outra string (usando a corda formatação). Desta forma, você não precisa se preocupar com citações fuga ou qualquer coisa. Mas nota que não há eval acontecendo aqui.

Para colocá-lo simplesmente:

__str__ é usado para mostrar a representação de seu objeto de para ser lido facilmente por outros.

__repr__ é usado para mostrar a representação de o objeto.

Vamos dizer que eu quero criar uma classe Fraction onde a representação de cadeia de uma fração é '(1/2)' eo objeto (classe Fraction) deve ser representada como 'Fraction (1,2)'

Assim, podemos criar uma classe Fraction 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)

A partir um (An Unofficial) Python Wiki Referência (cópia de arquivo) por effbot:

__str__ " calcula a 'representação de cadeia informal' de um objeto Isso difere do __repr__ na medida em que não tem de ser uma expressão Python válido:.. Uma representação mais conveniente ou concisa pode ser usado em vez "

Um aspecto que está faltando em outras respostas. É verdade que, em geral, o padrão é:

  • Meta de __str__: legível
  • Meta de __repr__: não ambígua, possivelmente legível por máquina via eval

Infelizmente, essa diferenciação é falho, pois o Python REPL e também IPython uso __repr__ para impressão de objetos em um console REPL (ver perguntas relacionadas para Python e IPython ). Assim, os projectos que são direcionados para o trabalho console interativo (por exemplo, Numpy ou Pandas) começaram a ignorar acima regras e fornecer uma implementação __repr__ legível vez.

str -. Cria um novo objeto string do objeto dado

repr -. Retorna a representação de cadeia canônica do objeto

As diferenças:

str ():

  • marcas objeto legível
  • gera saída para o usuário final

repr ():

  • necessita de código que reproduz objeto
  • gera saída para desenvolvedor

Excelentes respostas já cobrir a diferença entre __str__ e __repr__, que para mim resume-se ao ex-readable ser até mesmo por um usuário final, e sendo este último 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 este objetivo porque omite informações úteis para os desenvolvedores.

Por esta razão, se eu tiver uma __str__ bastante simples, eu geralmente apenas tentar obter o melhor dos dois mundos com algo como:

def __repr__(self):
    return '{0} ({1})'.format(object.__repr__(self), str(self))

Do livro Fluente Python :

Um requisito básico para um objeto Python é fornecer utilizável representações de seqüência de si mesmo, aquele usado para depuração e logging, outro para apresentação aos usuários finais. É por isso que o
métodos especiais __repr__ e exist __str__ no modelo de dados.

Uma coisa importante a ter em mente é usos __str__ desse recipiente continha __repr__ objetos.

>>> from datetime import datetime
>>> from decimal import Decimal
>>> print (Decimal('52'), datetime.now())
(Decimal('52'), datetime.datetime(2015, 11, 16, 10, 51, 26, 185000))
>>> str((Decimal('52'), datetime.now()))
"(Decimal('52'), datetime.datetime(2015, 11, 16, 10, 52, 22, 176000))"

Python favorece unambiguity sobre a legibilidade , a chamada __str__ de um tuple chama __repr__ dos objetos contidos, o "formal" representação de um objeto. Embora a representação formal é mais difícil de ler do que um informal, é inequívoca e mais firme contra bugs.

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'
>>> print(decimal.Decimal(23) / decimal.Decimal("1.05"))
21.90476190476190476190476190
>>> decimal.Decimal(23) / decimal.Decimal("1.05")
Decimal('21.90476190476190476190476190')

Quando print() é chamado no resultado de decimal.Decimal(23) / decimal.Decimal("1.05") o número bruto é impresso; esta saída está em forma de string , que pode ser alcançado com __str__(). Se nós simplesmente digite a expressão tenhamos uma saída decimal.Decimal - esta saída está em forma representacional , que pode ser alcançado com __repr__(). Todos os objetos Python tem duas formas de saída. forma de string é projetado para ser legível. A forma de representação é projetado para saída de produtos que, se alimentado a um interpretador Python seria (quando possível) reproduzir o objeto representado.

Entenda __str__ e __repr__ intuitivamente e permanentemente distingui-los em tudo.

__str__ retornar o corpo corda disfarçada de um determinado objeto para leitura de olhos
__repr__ devolver o corpo real carne de um determinado objeto (ele próprio retorno) para unambiguity de identificar.

Veja-o em um exemplo

In [30]: str(datetime.datetime.now())
Out[30]: '2017-12-07 15:41:14.002752'
Disguised in string form

Como a __repr__

In [32]: datetime.datetime.now()
Out[32]: datetime.datetime(2017, 12, 7, 15, 43, 27, 297769)
Presence in real body which allows to be manipulated directly.

Podemos fazer operação aritmética dos resultados __repr__ convenientemente.

In [33]: datetime.datetime.now()
Out[33]: datetime.datetime(2017, 12, 7, 15, 47, 9, 741521)
In [34]: datetime.datetime(2017, 12, 7, 15, 47, 9, 741521) - datetime.datetime(2
    ...: 017, 12, 7, 15, 43, 27, 297769)
Out[34]: datetime.timedelta(0, 222, 443752)

se aplica a operação em __str__

In [35]: '2017-12-07 15:43:14.002752' - '2017-12-07 15:41:14.002752'
TypeError: unsupported operand type(s) for -: 'str' and 'str'

Retorna nada, mas erro.

Um outro exemplo.

In [36]: str('string_body')
Out[36]: 'string_body' # in string form

In [37]: repr('real_body')
Out[37]: "'real_body'" #its real body hide inside

Espero que isso ajuda a construir motivos concretos para explorar mais respostas.

__repr__ é usado em todos os lugares, exceto por métodos print e str (quando um __str__is definido!)

  1. __str__ deve retornar objeto string enquanto __repr__ pode retornar qualquer expressão python.
  2. Se a implementação __str__ está faltando, então função __repr__ é usada como fallback. Não há alternativa se implementação da função __repr__ está faltando.
  3. Se a função __repr__ está retornando representação String do objeto, podemos pular implementação da função __str__.

Fonte: https://www.journaldev.com/22460/python -str-repr-funções

__str__ pode ser invocado em um objeto chamando str(obj) e deve retornar uma string legível.

__repr__ pode ser invocado em um objeto chamando repr(obj) e deve retornar objeto interno (campos de objetos / atributos)

Este exemplo pode ajudar:

class C1:pass

class C2:        
    def __str__(self):
        return str(f"{self.__class__.__name__} class str ")

class C3:        
    def __repr__(self):        
         return str(f"{self.__class__.__name__} class repr")

class C4:        
    def __str__(self):
        return str(f"{self.__class__.__name__} class str ")
    def __repr__(self):        
         return str(f"{self.__class__.__name__} class repr")


ci1 = C1()    
ci2 = C2()  
ci3 = C3()  
ci4 = C4()

print(ci1)       #<__main__.C1 object at 0x0000024C44A80C18>
print(str(ci1))  #<__main__.C1 object at 0x0000024C44A80C18>
print(repr(ci1)) #<__main__.C1 object at 0x0000024C44A80C18>
print(ci2)       #C2 class str
print(str(ci2))  #C2 class str
print(repr(ci2)) #<__main__.C2 object at 0x0000024C44AE12E8>
print(ci3)       #C3 class repr
print(str(ci3))  #C3 class repr
print(repr(ci3)) #C3 class repr
print(ci4)       #C4 class str 
print(str(ci4))  #C4 class str 
print(repr(ci4)) #C4 class repr
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top