Czy istnieje konwencja Pythona, w której należy wdrożyć __str__()
versus __unicode__()
. Widziałem klasy zastępujące __unicode__()
częściej niż, __str__()
ale nie wydaje się to spójne. Czy istnieją konkretne zasady, kiedy lepiej wdrożyć jedną z drugą? Czy wdrożenie obu jest konieczne / dobre praktyki?
python
string
unicode
conventions
Cory
źródło
źródło
__unicode__
a następnie zrobiszstr(obj)
?unicode
podnosi aNameError
na Pythonie 3, czy prosty wzorzec działa zarówno na 2, jak i na 3?future
pakiet zapewnia równieżpython_2_unicode_compatible
bez zależności Django.Gdybym specjalnie nie dbał o mikrooptymalizację rygoryzacji dla danej klasy, zawsze wdrażałbym
__unicode__
tylko, ponieważ jest bardziej ogólna. Kiedy zależy mi na tak drobnych problemach z wydajnością (co jest wyjątkiem, a nie regułą), posiadanie__str__
tylko (kiedy mogę udowodnić, że nigdy nie będzie znaków spoza ASCII w łańcuchowym wyjściu) lub obu (gdy oba są możliwe), może Wsparcie.Sądzę, że są to solidne zasady, ale w praktyce bardzo często WIEDZIEĆ, że nie będzie nic poza znakami ASCII bez wysiłku, aby to udowodnić (np. Forma strunowa ma tylko cyfry, znaki interpunkcyjne i być może krótką nazwę ASCII ;-), w której w przypadku przejścia do
__str__
podejścia „po prostu ” jest dość typowe (ale jeśli zespół programistów, z którym współpracowałem, zaproponowałby lokalne wytyczne, aby tego uniknąć, dałbym +1 w tej propozycji, ponieważ łatwo jest się mylić w tych sprawach ORAZ „przedwczesna optymalizacja jest źródłem wszelkiego zła w programowaniu” ;-).źródło
Świat staje się coraz mniejszy, więc istnieje prawdopodobieństwo, że każdy napotkany ciąg będzie zawierał Unicode. Dlatego w przypadku każdej nowej aplikacji powinieneś przynajmniej ją podać
__unicode__()
. To, czy ty też przeskoczysz,__str__()
to tylko kwestia gustu.źródło
Jeśli pracujesz zarówno w Python2, jak i Python3 w Django, polecam dekorator kompatybilny z python_2_unicode_compliance:
Jak zauważono we wcześniejszych komentarzach do innej odpowiedzi, niektóre wersje future.utils również obsługują ten dekorator. W moim systemie musiałem zainstalować nowszy moduł przyszłości dla python2 i zainstalować przyszłość dla python3. Następnie jest funkcjonalny przykład:
Oto przykładowe dane wyjściowe (gdzie venv2 / venv3 są instancjami virtualenv):
źródło
Python 2: Zaimplementuj tylko __str __ () i zwróć Unicode.
Kiedy
__unicode__()
jest pominięty, a ktoś dzwoniunicode(o)
lubu"%s"%o
, Python wywołujeo.__str__()
i konwertuje na Unicode przy użyciu kodowania systemowego. (Zobacz dokumentację__unicode__()
.)Przeciwnie nie jest prawdą. Jeśli zaimplementujesz,
__unicode__()
ale nie__str__()
, to kiedy ktoś zadzwonistr(o)
lub"%s"%o
, Python powrócirepr(o)
.Racjonalne uzasadnienie
Dlaczego to działa na zwracają
unicode
od__str__()
?Jeśli
__str__()
zwraca kod Unicode, Python automatycznie konwertuje go nastr
kodowanie systemowe.Jaka jest korzyść?
① Uwalnia od martwienia się o to, czym jest kodowanie systemowe (tj
locale.getpreferredencoeding(…)
.). Osobiście jest to nie tylko niechlujne, ale myślę, że i tak powinien się tym zająć. ② Jeśli jesteś ostrożny, twój kod może wyjść kompatybilny z Pythonem 3, w którym__str__()
zwraca Unicode.Czy zwodnicze jest zwrócenie kodu Unicode z funkcji o nazwie
__str__()
?Trochę. Być może już to robisz. Jeśli masz
from __future__ import unicode_literals
na górze pliku, istnieje duża szansa, że zwrócisz Unicode, nawet o tym nie wiedząc.Co z Python 3?
Python 3 nie używa
__unicode__()
. Jeśli jednak zaimplementujesz,__str__()
aby zwracał Unicode w Pythonie 2 lub Pythonie 3, to ta część kodu będzie kompatybilna krzyżowo.Co jeśli chcę
unicode(o)
się zasadniczo różnić odstr()
?Zaimplementuj zarówno
__str__()
(możliwe zwrotstr
) i__unicode__()
. Wyobrażam sobie, że byłoby to rzadkie, ale możesz chcieć mieć zasadniczo różne dane wyjściowe (np. Wersje znaków specjalnych ASCII, jak":)"
dlau"☺"
).Zdaję sobie sprawę, że niektórzy mogą uznać to za kontrowersyjne.
źródło
Warto zwrócić uwagę na osoby nieznające tej
__unicode__
funkcji niektóre z domyślnych zachowań, które ją otaczają w Pythonie 2.x, zwłaszcza gdy są zdefiniowane obok siebie__str__
.daje następujące dane wyjściowe konsoli ...
Teraz, kiedy odkomentuję tę
__str__
metodęźródło