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?
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.
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"; -).
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.
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__