2009-08-20 11 views
182

Czy istnieje konwencja python, w przypadku gdy należy wdrożyć __str__() versus __unicode__(). Zauważyłem, że klasy zastępują __unicode__() częściej niż __str__(), ale nie wydają się być spójne. Czy istnieją konkretne zasady, gdy lepiej jest wdrożyć jeden w stosunku do drugiego? Czy jest to niezbędne/dobrej praktyki do wdrożenia obu?Python __str__ versus __unicode__

Odpowiedz

227

__str__() to stara metoda - zwraca bajty. __unicode__() to nowa, preferowana metoda - zwraca znaki. Nazwy są nieco mylące, ale w wersji 2.x utknęliśmy z nimi ze względu na kompatybilność. Generalnie, należy umieścić wszystkie kryteria formatowania w __unicode__() i stworzyć zalążek __str__() metody:

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

w 3,0, str zawiera znaki, więc te same metody są nazywane __bytes__() i __str__(). Te zachowują się zgodnie z oczekiwaniami.

+1

oznacza tworzenie metod __unicode__ i __str__ lub po prostu ciągi znaków w _ (u "") i tworzenie __string__ (bez metody unicode)? – muntu

+9

Czy jest jakaś pułapka w realizacji tylko jednego z nich? Co stanie się, gdy zaimplementujesz tylko '__unicode__', a następnie zrobisz' str (obj) '? – RickyA

+9

'unicode' podnosi' NameError' na Pythonie 3, jest prosty wzór, który działa zarówno w 2 i 3? –

9

Wraz ze zmniejszaniem się świata istnieje szansa, że ​​dowolny ciąg znaków, który napotkasz, będzie w końcu zawierał Unicode. Dlatego w przypadku nowych aplikacji należy przynajmniej podać __unicode__(). Niezależnie od tego, czy zastąpisz także __str__(), to tylko kwestia gustu.

19

Gdybym nie dbał szczególnie o mikro-optymalizację uszeregowania dla danej klasy, zawsze implementowałbym tylko __unicode__, ponieważ jest bardziej ogólny. Kiedy zależy mi na tak drobnych problemach z wydajnością (co jest wyjątkiem, a nie regułą), mając tylko __str__ (kiedy mogę udowodnić, że nigdy nie będą to znaki spoza ASCII w wyfiszerowanym wyjściu) lub oba (jeśli oba są możliwe), może pomóc.

Sądzę, że są to solidne zasady, ale w praktyce bardzo często jest WIEDZIEĆ, że nie będzie nic poza znakami ASCII bez wysiłku, aby to udowodnić (np. Ujęta forma ma tylko cyfry, znaki interpunkcyjne i być może krótkie nazwy ASCII; -) w takim przypadku dość typowe jest przejście bezpośrednio do podejścia "just __str__" (ale jeśli zespół programistów, z którym pracowałem zaproponował lokalną wytyczną, aby tego uniknąć, byłbym +1 w sprawie wniosku, ponieważ łatwo jest błądzić w tych sprawach ORAZ "przedwczesna optymalizacja jest źródłem wszelkiego zła w programowaniu" ;-).

+2

W python 2.6.2, niedawno został wyzwolony, bo przypadkach konkretnej wbudowanej podklasy Exception dały inne wyniki z str (e) i unicode (e). str (e) dał przyjazne dla użytkownika wyjście; unicode (e) dawał różne, nieprzyjazne dla użytkownika wydruki. Czy jest to uważane za błędne zachowanie? Klasa to UnicodeDecodeError; Nie wymieniłem tego z góry, aby uniknąć nieporozumień - fakt, że wyjątek jest związany z Unicode, nie jest szczególnie istotny. –

0

Jeśli pracujesz w obu python2 i python3 w Django, polecam python_2_unicode_compatible dekorator:

Django umożliwia łatwe do zdefiniowania str() i unicode() metody, które działają na Python 2 i 3: musisz zdefiniować metodę zwracania tekstu i zastosować metodę dekoratora python_2_unicode_compatible().

Jak wspomniano we wcześniejszych komentarzach do innej odpowiedzi, niektóre wersje future.utils również obsługują tego dekoratora. W moim systemie potrzebowałem zainstalować nowszy moduł przyszłości dla Pythona2 i zainstalować przyszłe dla Pythona3. Po tym, to tutaj jest funkcjonalny przykład:

#! /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)) 

Oto przykład wyjście (gdzie venv2/venv3 są virtualenv przypadki):

~/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__