Réponses:
Alex a bien résumé, mais, étonnamment, était trop succinct.
Tout d'abord, permettez-moi de réitérer les principaux points du message d'Alex :
__repr__
l'objectif est d'être sans ambiguïté__str__
le but est d'être lisible__str__
utilise des objets contenus '__repr__
L'implémentation par défaut est inutile
C'est surtout une surprise car les valeurs par défaut de Python ont tendance à être assez utiles. Cependant, dans ce cas, avoir un défaut pour __repr__
lequel agirait comme:
return "%s(%r)" % (self.__class__, self.__dict__)
aurait été trop dangereux (par exemple, trop facile d'entrer dans une récursion infinie si les objets se référencent). Alors Python s'en sort. Notez qu'il y a une valeur par défaut qui est vraie: si __repr__
est défini, et __str__
ne l'est pas, l'objet se comportera comme si __str__=__repr__
.
Cela signifie, en termes simples: presque chaque objet que vous implémentez devrait avoir une fonctionnalité __repr__
utilisable pour comprendre l'objet. L'implémentation __str__
est facultative: faites-le si vous avez besoin d'une fonctionnalité «jolie impression» (par exemple, utilisée par un générateur de rapports).
L'objectif __repr__
est d'être sans ambiguïté
Permettez-moi de le dire tout de suite - je ne crois pas aux débogueurs. Je ne sais pas vraiment comment utiliser un débogueur et je n'en ai jamais utilisé sérieusement. De plus, je crois que le gros défaut des débogueurs est leur nature fondamentale - la plupart des échecs que je débogue se sont produits il y a très longtemps, dans une galaxie très éloignée. Cela signifie que je crois, avec ferveur religieuse, à l'exploitation forestière. La journalisation est la pierre angulaire de tout système serveur décent de type feu et oubli. Python facilite la journalisation: avec peut-être des wrappers spécifiques à un projet, tout ce dont vous avez besoin est un
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)
Mais vous devez faire la dernière étape - assurez-vous que chaque objet que vous implémentez a une représentation utile, donc un code comme celui-ci peut simplement fonctionner. C'est pourquoi la chose «eval» apparaît: si vous avez suffisamment d'informations eval(repr(c))==c
, cela signifie que vous savez tout ce qu'il y a à savoir c
. Si c'est assez facile, au moins d'une manière floue, faites-le. Si ce n'est pas le cas, assurez-vous d'avoir suffisamment d'informations sur de c
toute façon. Je l'habitude d' utiliser un eval comme le format: "MyClass(this=%r,that=%r)" % (self.this,self.that)
. Cela ne signifie pas que vous pouvez réellement construire MyClass, ou que ce sont les bons arguments du constructeur - mais c'est une forme utile pour exprimer «c'est tout ce que vous devez savoir sur cette instance».
Remarque: je l'ai utilisé %r
ci-dessus, non %s
. Vous voulez toujours utiliser repr()
[ou un %r
caractère de mise en forme, de manière équivalente] à l'intérieur de l' __repr__
implémentation, ou vous battez l'objectif de repr. Vous voulez pouvoir différencier MyClass(3)
et MyClass("3")
.
L'objectif __str__
est d'être lisible
Plus précisément, il n'est pas destiné à être sans ambiguïté - notez cela str(3)==str("3")
. De même, si vous implémentez une abstraction IP, le fait de faire ressembler la chaîne à 192.168.1.1 est très bien. Lors de l'implémentation d'une abstraction de date / heure, la chaîne peut être "2010/4/12 15:35:22", etc. Le but est de la représenter d'une manière qu'un utilisateur, et non un programmeur, voudrait la lire. Coupez les chiffres inutiles, faites semblant d'être une autre classe - tant qu'il prend en charge la lisibilité, c'est une amélioration.
Le conteneur __str__
utilise des objets contenus '__repr__
Cela semble surprenant, non? C'est un peu, mais comment serait-il lisible s'il utilisait leur __str__
?
[moshe is, 3, hello
world, this is a list, oh I don't know, containing just 4 elements]
Pas très. Plus précisément, les chaînes d'un conteneur trouveraient trop facile de perturber sa représentation. Face à l'ambiguïté, rappelez-vous, Python résiste à la tentation de deviner. Si vous voulez le comportement ci-dessus lorsque vous imprimez une liste,
print "[" + ", ".join(l) + "]"
(vous pouvez probablement aussi savoir quoi faire à propos des dictionnaires.
Sommaire
Implémentez __repr__
pour n'importe quelle classe que vous implémentez. Cela devrait être une seconde nature. Implémentez-le __str__
si vous pensez qu'il serait utile d'avoir une version chaîne qui pèche du côté de la lisibilité.
__repr__
que j'avais besoin de débogage. Merci de votre aide.
Ma règle d'or: __repr__
c'est pour les développeurs, __str__
c'est pour les clients.
__str__
donc les développeurs normaux ont un objet lisible. En revanche, __repr__
c'est pour les développeurs du SDK eux-mêmes.
Sauf si vous agissez spécifiquement pour garantir le contraire, la plupart des classes n'ont pas de résultats utiles pour:
>>> class Sic(object): pass
...
>>> print str(Sic())
<__main__.Sic object at 0x8b7d0>
>>> print repr(Sic())
<__main__.Sic object at 0x8b7d0>
>>>
Comme vous le voyez - aucune différence, et aucune information au-delà de la classe et de l'objet id
. Si vous ne remplacez que l'un des deux ...:
>>> 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>
>>>
comme vous le voyez, si vous remplacez __repr__
, c'est également utilisé pour __str__
, mais pas vice versa.
Autres informations essentielles à savoir: __str__
sur un conteneur intégré, utilise le __repr__
, PAS le __str__
, pour les éléments qu'il contient. Et, malgré les mots sur le sujet trouvés dans les documents typiques, presque personne ne prend la peine de faire __repr__
des objets une chaîne qui eval
peut être utilisée pour construire un objet égal (c'est tout simplement trop difficile, ET ne pas savoir comment le module pertinent a été réellement importé le rend réellement à plat impossible).
Donc, mon conseil: concentrez-vous sur le fait de rendre __str__
raisonnablement lisible par l'homme, et __repr__
aussi sans ambiguïté que possible, même si cela interfère avec l'objectif flou et inaccessible de rendre __repr__
la valeur retournée de 'acceptable comme entrée pour __eval__
!
eval(repr(foo))
égal à un objet égal à foo
. Vous avez raison, cela ne fonctionnera pas en dehors de mes cas de test car je ne sais pas comment le module est importé, mais cela garantit au moins qu'il fonctionne dans un contexte prévisible. Je pense que c'est une bonne façon d'évaluer si le résultat __repr__
est suffisamment explicite. Faire cela dans un test unitaire permet également de s'assurer que les __repr__
modifications apportées à la classe suivent.
eval(repr(spam)) == spam
(au moins dans le bon contexte), ou eval(repr(spam))
soulève un SyntaxError
. De cette façon, vous évitez la confusion. (Et c'est presque vrai pour les builtins et la plupart des stdlib, sauf, par exemple, des listes récursives, où a=[]; a.append(a); print(eval(repr(a)))
vous donne [[Ellipses]]
...) Bien sûr , je ne fais pas ça pour réellement utiliser eval(repr(spam))
, sauf un contrôle de santé mentale dans les tests unitaires ... mais je ne parfois copier et coller repr(spam)
dans une session interactive.
__str__
pour chaque élément au lieu de __repr__
? Cela me semble tout à fait faux, car j'ai implémenté un __str__
objet lisible dans mon objet et lorsqu'il fait partie d'une liste, je vois le plus laid à la __repr__
place.
eval(repr(x))
échoue même pour les types intégrés: class A(str, Enum): X = 'x'
déclenche SyntaxError eval(repr(A.X))
. C'est triste, mais compréhensible. BTW, en eval(str(A.X))
fait fonctionne, mais bien sûr seulement s'il class A
est dans la portée - donc ce n'est probablement pas très utile.
str
élément d'utilisation du conteneur repr
car [1, 2, 3]
! = ["1", "2, 3"]
.
__repr__
: la représentation de l'objet python habituellement eval le reconvertira en cet objet
__str__
: est ce que vous pensez est cet objet sous forme de texte
par exemple
>>> 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
En bref, l'objectif de
__repr__
est d'être sans ambiguïté et__str__
d'être lisible.
Voici un bon exemple:
>>> 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)'
Lisez cette documentation pour repr:
repr(object)
Renvoie une chaîne contenant une représentation imprimable d'un objet. Il s'agit de la même valeur fournie par les conversions (guillemets inversés). Il est parfois utile de pouvoir accéder à cette opération comme une fonction ordinaire. Pour de nombreux types, cette fonction tente de renvoyer une chaîne qui donnerait un objet avec la même valeur lorsqu'elle est transmise à
eval()
, sinon la représentation est une chaîne entre crochets qui contient le nom du type de l'objet avec des informations supplémentaires comprenant souvent le nom et l'adresse de l'objet. Une classe peut contrôler ce que cette fonction renvoie pour ses instances en définissant une__repr__()
méthode.
Voici la documentation de str:
str(object='')
Renvoie une chaîne contenant une représentation bien imprimable d'un objet. Pour les chaînes, cela renvoie la chaîne elle-même. La différence avec
repr(object)
est qu'ilstr(object)
n'essaie pas toujours de renvoyer une chaîne acceptable poureval()
; son objectif est de renvoyer une chaîne imprimable. Si aucun argument est donné, renvoie la chaîne vide,''
.
Quelle est la différence entre
__str__
et__repr__
en Python?
__str__
(lu comme "dunder (double soulignement) chaîne") et __repr__
(lu comme "dunder-repper" (pour "représentation")) sont deux méthodes spéciales qui renvoient des chaînes en fonction de l'état de l'objet.
__repr__
fournit un comportement de sauvegarde s'il __str__
est manquant.
Donc, il faut d'abord écrire un __repr__
qui vous permet de réinstancier un objet équivalent à partir de la chaîne qu'il retourne, par exemple en utilisant eval
ou en le tapant caractère par caractère dans un shell Python.
À tout moment plus tard, on peut écrire un __str__
pour une représentation en chaîne lisible par l'utilisateur de l'instance, quand on le juge nécessaire.
__str__
Si vous imprimez un objet, ou le transmettez à format
,, str.format
ou str
, si une __str__
méthode est définie, cette méthode sera appelée, sinon, __repr__
elle sera utilisée.
__repr__
La __repr__
méthode est appelée par la fonction intégrée repr
et correspond à ce qui est répercuté sur votre shell python lors de l'évaluation d'une expression qui renvoie un objet.
Puisqu'il fournit une sauvegarde pour __str__
, si vous ne pouvez en écrire qu'une, commencez par__repr__
Voici l'aide intégrée sur repr
:
repr(...)
repr(object) -> string
Return the canonical string representation of the object.
For most object types, eval(repr(object)) == object.
Autrement dit, pour la plupart des objets, si vous tapez ce qui est imprimé par repr
, vous devriez pouvoir créer un objet équivalent. Mais ce n'est pas l'implémentation par défaut.
__repr__
L'objet par défaut __repr__
est ( source C Python ) quelque chose comme:
def __repr__(self):
return '<{0}.{1} object at {2}>'.format(
self.__module__, type(self).__name__, hex(id(self)))
Cela signifie que par défaut, vous imprimerez le module d'où provient l'objet, le nom de la classe et la représentation hexadécimale de son emplacement en mémoire - par exemple:
<__main__.Foo object at 0x7f80665abdd0>
Ces informations ne sont pas très utiles, mais il n'y a aucun moyen de déterminer comment créer avec précision une représentation canonique d'une instance donnée, et c'est mieux que rien, du moins en nous disant comment nous pourrions l'identifier de manière unique en mémoire.
__repr__
être utile?Voyons à quel point cela peut être utile, en utilisant le shell et les datetime
objets Python . Nous devons d'abord importer le datetime
module:
import datetime
Si nous appelons datetime.now
dans le shell, nous verrons tout ce dont nous avons besoin pour recréer un objet datetime équivalent. Ceci est créé par le datetime __repr__
:
>>> datetime.datetime.now()
datetime.datetime(2015, 1, 24, 20, 5, 36, 491180)
Si nous imprimons un objet datetime, nous voyons un joli format lisible par l'homme (en fait, ISO). Ceci est implémenté par datetime __str__
:
>>> print(datetime.datetime.now())
2015-01-24 20:05:44.977951
Il est simple de recréer l'objet que nous avons perdu parce que nous ne l'avons pas affecté à une variable en copiant et en collant à partir de la __repr__
sortie, puis en l'imprimant, et nous l'obtenons dans la même sortie lisible par l'homme que l'autre objet:
>>> the_past = datetime.datetime(2015, 1, 24, 20, 5, 36, 491180)
>>> print(the_past)
2015-01-24 20:05:36.491180
Au fur et à mesure que vous développez, vous voudrez pouvoir reproduire des objets dans le même état, si possible. C'est par exemple ainsi que définit l'objet datetime __repr__
( source Python ). C'est assez complexe, à cause de tous les attributs nécessaires pour reproduire un tel objet:
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
Si vous souhaitez que votre objet ait une représentation plus lisible par l'homme, vous pouvez l'implémenter __str__
ensuite. Voici comment l'objet datetime ( source Python ) implémente __str__
, ce qu'il fait facilement car il a déjà une fonction pour l'afficher au format ISO:
def __str__(self):
"Convert to string, for str()."
return self.isoformat(sep=' ')
__repr__ = __str__
?Ceci est une critique d'une autre réponse ici qui suggère un réglage __repr__ = __str__
.
Le réglage __repr__ = __str__
est stupide - __repr__
est un substitut pour __str__
et un __repr__
, écrit pour les développeurs à des fins de débogage, doit être écrit avant d'écrire un __str__
.
Vous __str__
n'en avez besoin que lorsque vous avez besoin d'une représentation textuelle de l'objet.
Définissez __repr__
pour les objets que vous écrivez afin que vous et les autres développeurs ayez un exemple reproductible lorsque vous l'utilisez pendant votre développement. Définissez __str__
quand vous avez besoin d'une représentation en chaîne lisible par l'homme.
type(obj).__qualname__
?
À la page 358 du livre Python scripting for computational science de Hans Petter Langtangen, il indique clairement que
__repr__
vise à une représentation complète de la chaîne de l'objet;__str__
s'agit de renvoyer une jolie chaîne pour l'impression.Donc, je préfère les comprendre comme
du point de vue de l'utilisateur bien que ce soit un malentendu que j'ai fait lors de l'apprentissage du python.
Un petit mais bon exemple est également donné sur la même page comme suit:
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'
repr
reproduire. Il vaut mieux y penser comme représentant.
Outre toutes les réponses données, je voudrais ajouter quelques points: -
1) __repr__()
est invoqué lorsque vous écrivez simplement le nom de l'objet sur la console python interactive et appuyez sur Entrée.
2) __str__()
est invoqué lorsque vous utilisez un objet avec l'instruction print.
3) Au cas où, s'il __str__
manque, imprimer et toute fonction utilisant des str()
invocations __repr__()
d'objet.
4) __str__()
des conteneurs, lorsqu'ils sont invoqués, exécutera la __repr__()
méthode de ses éléments contenus.
5) str()
appelé à l'intérieur __str__()
pourrait potentiellement récurrence sans cas de base, et erreur sur la profondeur de récursivité maximale.
6) __repr__()
peut appeler repr()
ce qui tentera d'éviter automatiquement la récursion infinie, en remplaçant un objet déjà représenté par ...
.
Pour le dire simplement:
__str__
est utilisé pour afficher une représentation sous forme de chaîne de votre objet pour être lu facilement par les autres.
__repr__
est utilisé pour afficher une représentation sous forme de chaîne de l' objet.
Disons que je veux créer une Fraction
classe où la représentation sous forme de chaîne d'une fraction est '(1/2)' et l'objet (classe Fraction) doit être représenté comme 'Fraction (1,2)'
Nous pouvons donc créer une classe Fraction simple:
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)
En toute honnêteté, eval(repr(obj))
n'est jamais utilisé. Si vous vous retrouvez à l'utiliser, vous devez vous arrêter, car eval
c'est dangereux, et les chaînes sont un moyen très inefficace de sérialiser vos objets (utilisez pickle
plutôt).
Par conséquent, je recommanderais le réglage __repr__ = __str__
. La raison en est que cela fait str(list)
appel repr
aux éléments (je considère que c'est l'un des plus gros défauts de conception de Python qui n'a pas été corrigé par Python 3). Un réel repr
ne sera probablement pas très utile comme sortie de print [your, objects]
.
Pour qualifier cela, d'après mon expérience, le cas d'utilisation le plus utile de la repr
fonction est de mettre une chaîne à l'intérieur d'une autre chaîne (en utilisant le formatage de chaîne). De cette façon, vous n'avez pas à vous soucier d'échapper aux citations ou à quoi que ce soit. Mais notez qu'il ne se eval
passe rien ici.
eval(repr(obj))
est un test d'intégrité et une règle de base - si cela recrée correctement l'objet d'origine, alors vous avez une __repr__
implémentation décente . Il n'est pas prévu que vous sérialisiez des objets de cette façon.
eval
n'est pas intrinsèquement dangereux. Est -ce pas plus dangereux que unlink
, open
ou l' écriture de fichiers. Devrions-nous arrêter d'écrire dans des fichiers parce qu'une attaque malveillante pourrait peut-être utiliser un chemin de fichier arbitraire pour mettre du contenu à l'intérieur? Tout est dangereux s'il est bêtement utilisé par des gens stupides. L'idiotie est dangereuse. Les effets de Dunning-Kruger sont dangereux. eval
est juste une fonction.
À partir d' un Wiki de référence Python (non officiel) (copie d'archive) par effbot:
__str__
" calcule la représentation sous forme de chaîne" informelle "d'un objet. Cela diffère du __repr__
fait qu'il ne doit pas nécessairement être une expression Python valide: une représentation plus pratique ou concise peut être utilisée à la place. "
__repr__
n'est en aucun cas requis pour renvoyer une expression Python vaild.
str
- Crée un nouvel objet chaîne à partir de l'objet donné.
repr
- Renvoie la représentation sous forme de chaîne canonique de l'objet.
Les différences:
str ():
repr ():
Un aspect qui manque dans d'autres réponses. Il est vrai qu'en général le schéma est:
__str__
: lisible par l'homme__repr__
: sans ambiguïté, peut-être lisible par machine viaeval
Malheureusement, cette différenciation est imparfaite, car Python REPL et IPython utilisent également __repr__
pour imprimer des objets dans une console REPL (voir les questions connexes pour Python et IPython ). Ainsi, les projets ciblés pour le travail sur console interactive (par exemple, Numpy ou Pandas) ont commencé à ignorer les règles ci-dessus et à fournir une __repr__
implémentation lisible par l'homme .
Extrait du livre Fluent Python :
Une exigence de base pour un objet Python est de fournir des représentations de chaîne utilisables de lui-même, une utilisée pour le débogage et la journalisation, une autre pour la présentation aux utilisateurs finaux. C'est pourquoi les
méthodes spéciales__repr__
et__str__
existent dans le modèle de données.
D'excellentes réponses couvrent déjà la différence entre __str__
et __repr__
, ce qui pour moi se résume à ce que le premier soit lisible même par un utilisateur final, et que le second soit aussi utile que possible aux développeurs. Compte tenu de cela, je trouve que l'implémentation par défaut de __repr__
souvent échoue à atteindre cet objectif car elle omet les informations utiles aux développeurs.
Pour cette raison, si j'en ai un assez simple __str__
, j'essaye généralement de tirer le meilleur parti des deux mondes avec quelque chose comme:
def __repr__(self):
return '{0} ({1})'.format(object.__repr__(self), str(self))
Une chose importante à garder à l'esprit est que le conteneur
__str__
utilise des objets contenus__repr__
.
>>> 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 privilégie la non-ambiguïté sur la lisibilité , l' __str__
appel d'un tuple
appelle les objets contenus __repr__
, la représentation "formelle" d'un objet. Bien que la représentation formelle soit plus difficile à lire qu'une représentation informelle, elle est sans ambiguïté et plus robuste contre les bogues.
__repr__
quand il ( __str__
) n'est pas défini! Vous vous trompez donc.
En un mot:
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')
Quand print()
est appelé, le résultat du decimal.Decimal(23) / decimal.Decimal("1.05")
nombre brut est imprimé; cette sortie est sous forme de chaîne qui peut être réalisée avec __str__()
. Si nous entrons simplement l'expression, nous obtenons une decimal.Decimal
sortie - cette sortie est sous une forme représentative qui peut être obtenue avec __repr__()
. Tous les objets Python ont deux formes de sortie. La forme de chaîne est conçue pour être lisible par l'homme. La forme représentationnelle est conçue pour produire une sortie qui, si elle était envoyée à un interpréteur Python, reproduirait (si possible) l'objet représenté.
__str__
peut être invoqué sur un objet en appelant str(obj)
et doit renvoyer une chaîne lisible par l'homme.
__repr__
peut être invoqué sur un objet en appelant repr(obj)
et doit renvoyer un objet interne (champs / attributs d'objet)
Cet exemple peut aider:
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
Les comprendre __str__
et __repr__
les distinguer de manière intuitive et permanente.
__str__
renvoyer la chaîne déguisée corps d'un objet donné pour une lecture des yeux
__repr__
retourner le corps de chair réel d'un objet donné (retour lui-même) pour une ambiguïté à identifier.
Voir dans un exemple
In [30]: str(datetime.datetime.now())
Out[30]: '2017-12-07 15:41:14.002752'
Disguised in string form
Quant à __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.
Nous pouvons __repr__
facilement effectuer des opérations arithmétiques sur les résultats.
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)
si appliquer l'opération sur __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'
Ne renvoie rien d'autre qu'une erreur.
Un autre exemple.
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
J'espère que cela vous aidera à construire des terrains concrets pour explorer plus de réponses.
__str__
doit renvoyer un objet chaîne alors qu'il __repr__
peut renvoyer n'importe quelle expression python.__str__
implémentation est manquante, la __repr__
fonction est utilisée comme solution de repli. Il n'y a pas de solution de repli si __repr__
l'implémentation de fonction est manquante.__repr__
fonction renvoie une représentation String de l'objet, nous pouvons ignorer l'implémentation de la __str__
fonction.Source: https://www.journaldev.com/22460/python-str-repr-functions