Python str contre unicode

Existe - t-il une convention python pour savoir quand vous devez implémenter __str__() par rapport à __unicode__(). J'ai vu des classes remplacer __unicode__() plus fréquemment que __str__() mais cela ne semble pas être cohérent. Des règles particulières quand il est préférable de mettre en œuvre un contre l'autre? Est-il nécessaire/bonne pratique de mettre en œuvre les deux?

193
demandé sur Cory 2009-08-20 19:34:07

4 réponses

__str__() est l'ancienne méthode - elle renvoie des octets. __unicode__() est la nouvelle méthode préférée - elle renvoie des caractères. Les noms sont un peu confus, mais en 2.x nous sommes coincés avec eux pour des raisons de compatibilité. Généralement, vous devriez mettre toute votre mise en forme de chaîne dans __unicode__(), et créer une méthode stub __str__():

def __str__(self):
    return unicode(self).encode('utf-8')

Dans 3.0, str contient des caractères, donc les mêmes méthodes sont nommées __bytes__() et __str__(). Celles-ci se passent comme prévu.

236
répondu John Millikin 2009-08-20 16:04:34

Si Je ne me souciais pas particulièrement de la micro-optimisation de la stringification pour une classe donnée, j'implémenterais toujours __unicode__ seulement, car c'est plus général. Quand je me soucie de tels problèmes de performance minute (qui est l'exception, pas la règle), avoir __str__ seulement (quand je peux prouver qu'il n'y aura jamais de caractères non-ASCII dans la sortie stringifiée) ou les deux (quand les deux sont possibles), peut aider.

Je pense que ce sont des principes solides, mais en pratique, il est très courant de savoir qu'il n'y aura rien mais les caractères ASCII sans faire d'effort pour le prouver (par exemple, la forme stringifiée n'a que des chiffres, de la ponctuation, et peut-être un nom ASCII court; -) auquel cas il est assez typique de passer directement à l'approche" just __str__ "(mais si une équipe de programmation avec laquelle j'ai travaillé proposait une directive locale pour éviter cela, je serais +1 sur la proposition, car il est facile de se tromper dans ces questions et"l'optimisation prématurée est la racine de tout mal dans la programmation"; -).

21
répondu Alex Martelli 2009-08-20 16:04:22

Avec le monde devenant plus petit, les chances sont que toute chaîne que vous rencontrez contiendra éventuellement Unicode. Donc, pour toute nouvelle application, vous devez au moins fournir __unicode__(). Si vous remplacez également __str__() est alors juste une question de goût.

11
répondu Aaron Digulla 2009-08-20 16:00:08

Si vous travaillez à la fois en python2 et en python3 dans Django, je recommande le décorateur python_2_unicode_compatible:

Django fournit un moyen simple de définir les méthodesstr () etunicode () qui fonctionnent sur Python 2 et 3: vous devez définir une méthodestr () renvoyant du texte et appliquer le décorateur python_2_unicode_compatible ().

Comme indiqué dans les commentaires précédents à une autre réponse, certaines versions de future.utils supporte également ce décorateur. Sur mon système, j'avais besoin d'installer un module futur plus récent pour python2 et d'installer future pour python3. Après cela, Voici un exemple fonctionnel:

#! /usr/bin/env python

from future.utils import python_2_unicode_compatible
from sys import version_info

@python_2_unicode_compatible
class SomeClass():
    def __str__(self):
        return "Called __str__"


if __name__ == "__main__":
    some_inst = SomeClass()
    print(some_inst)
    if (version_info > (3,0)):
        print("Python 3 does not support unicode()")
    else:
        print(unicode(some_inst))

Voici un exemple de sortie (où venv2 / venv3 sont des instances virtualenv):

~/tmp$ ./venv3/bin/python3 demo_python_2_unicode_compatible.py 
Called __str__
Python 3 does not support unicode()

~/tmp$ ./venv2/bin/python2 demo_python_2_unicode_compatible.py 
Called __str__
Called __str__
1
répondu sage 2017-06-18 21:19:25