11
votes

Utilisation de la représentation __STR__ pour imprimer des objets dans des conteneurs en python

J'ai remarqué que lorsqu'une instance avec une méthode surchargée __ str __ est transmise à la fonction imprimer comme argument, elle imprime comme prévu. Cependant, lors du passage d'un conteneur contenant l'une de ces instances à Imprimer , il utilise la méthode __ RECR __ . C'est-à-dire que impression (x) affiche la représentation de chaîne correcte de x et impression (x, y) fonctionne correctement, mais < Code> Imprimer ([x]) ou Imprimer ((x, y)) imprime le __ RECR __ représentation.

Tout d'abord, pourquoi cela se produit-il? Deuxièmement, est-il un moyen de corriger ce comportement de imprimer dans cette circonstance?


0 commentaires

3 Réponses :


1
votes

Parce que lorsque vous imprimez la liste, vous recherchez généralement du point de vue du programmeur ou du débogage. Si vous vouliez afficher la liste, vous traiteriez ses éléments de manière significative, la RECI est donc utilisée.

Si vous souhaitez que vos objets soient imprimés dans des conteneurs, définissez REC P>

class MyObject:
    def __str__(self): return ""

    __repr__ = __str__


0 commentaires

13
votes

Le problème avec le conteneur à l'aide des objets ' __ str __ serait l'ambiguïté totale - que signifierait cela, disons, si impression L a montré [1 , 2] ? l pourrait être ['1, 2'] (une liste d'éléments unique dont l'élément de chaîne contient une virgule) ou l'une des quatre listes de 2 points (car chaque élément peut être une chaîne ou int). L'ambiguïté du type est courante pour d'impression bien sûr, mais l'ambiguïté totale du nombre d'éléments (car chaque virgule pourrait délimiter des éléments ou partie d'un élément de chaîne) était la considération décisive.


0 commentaires

5
votes

Je ne suis pas sûr pourquoi exactement le __ str __ La méthode d'une liste renvoie le __ rep __ des objets contenus dans - donc je l'ai regardé up: [python-3000] pep: str (conteneur) devrait appeler str (item), non REC (article)

arguments pour cela:

- Les conteneurs refusent de deviner ce que l'utilisateur souhaite voir sur Str (conteneur) - Environnement, délimiteurs, etc.

- REC (article) affiche généralement les informations de type - Apostrophes autour des chaînes, des noms de classe, etc.

Il est donc plus clair sur ce qui est exactement dans la liste (puisque la représentation des chaînes de l'objet pourrait avoir des virgules, etc.). Le comportement ne s'en va pas, par Guido "BDFL" Van Rossum:

Permettez-moi de sauver tout le monde beaucoup de temps et dire que je suis opposé à cela changer, et que je crois que ça causerait beaucoup trop de perturbations être accepté cela près de la bêta.


MAINTENANT, il existe deux façons de résoudre ce problème pour votre code.

La première consiste à la sous-classe Liste et à mettre en œuvre votre propre __ str __ méthode. xxx

et maintenant pour le tester: xxx

Je pense personnellement que c'est un Une idée terrible. Certaines fonctions - telles que aléatoire.sample , comme démontré - retournez réellement list objets - même si vous avez des listes sous-classées. Donc, si vous prenez cette route, il peut y avoir beaucoup de résultats = strlist (fonction (myList)) appels, ce qui pourrait être inefficace. C'est aussi une mauvaise idée car alors vous aurez probablement la moitié de votre code en utilisant des objets réguliers car vous ne les imprimez pas et l'autre moitié en utilisant strlist Objets, qui Peut conduire à votre code devenir messier et plus déroutant. Néanmoins, l'option est là et c'est le seul moyen d'obtenir la fonction imprimer (ou la déclaration, pour 2.x) pour se comporter de la façon dont vous le souhaitez.

L'autre solution est simplement d'écrire votre propre fonction strlist () qui renvoie la chaîne comme vous le souhaitez: xxx

Les deux solutions exigent que vous Refacteur Code existant, malheureusement - mais le comportement de str (conteneur) est là pour rester.


1 commentaires

Très bonne réponse. Je veux juste noter qu'il existe un moyen plus idiomatique d'exprimer le code que vous avez écrit pour __ str __ : def __str __ (auto): éléments = "," .join ([STR (article) pour l'article en soi]); retour "[{0}]". Format (éléments) (évidemment, divisé sur plusieurs lignes). Le point principal est que rejoindre est le moyen préféré d'insérer , (ou une autre chaîne) entre chaque élément d'une liste.