Python __str__ ve __unicode__


213

Uygulamak gerektiğine ilişkin bir piton kongre var mı __str__()versus __unicode__(). Sınıfların __unicode__()daha sık geçersiz kıldığını gördüm __str__()ama tutarlı görünmüyor. Birini diğerine uygulamak daha iyi olduğunda belirli kurallar var mı? Her ikisini de uygulamak gerekli / iyi bir uygulama mı?

Yanıtlar:


257

__str__()eski yöntemdir - bayt döndürür. __unicode__()yeni, tercih edilen yöntemdir - karakterleri döndürür. İsimler biraz kafa karıştırıcı, ancak 2.x'te uyumluluk nedeniyle onlara takılıp kalıyoruz. Genel olarak, tüm dize biçimlendirmenizi koymalı __unicode__()ve bir saplama __str__()yöntemi oluşturmalısınız :

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

3.0'da, strkarakterler içerir, bu nedenle aynı yöntemler __bytes__()ve olarak adlandırılır __str__(). Bunlar beklendiği gibi davranır.


2
sa hem oluştururken demek unicode ve str yöntemleri veya sadece ( "" u) _ dizeleri tutmak ve oluşturmak dize (unicode yöntemiyle olmadan)?
muntu

12
Bunlardan sadece birini uygulamada herhangi bir tuzak var mı? Yalnızca uygulamak ne olur __unicode__ve daha sonra yapılacak str(obj)?
RickyA

9
unicodeBir yükseltir NameErrorPython 3, 2 ve 3 her ikisi arasında çalışır basit bir kalıptır?
bradley.ayers

1
@ bradley.ayers futurepaketi de python_2_unicode_compatiblebağımlılık olarak Django olmadan sağlar .
Monkpit

1
Değişir. Çünkü python3 unicode kullanmıyor, bunun yerine str ;) python 2 unicode için kullanıyor
Eddwin Paz

23

Eğer belirli bir sınıf için mikro-optimizasyon dizgelemesini özellikle umursamış olsaydım, her zaman __unicode__sadece genel olarak uygulayacağım . Böyle bir dakika performans sorunları (bu kural değil istisna) umurumda __str__olduğunda , sadece sahip olmak (zaman asla ASCII olmayan karakter dizili çıktı olmayacak) veya her ikisi de (her ikisi de mümkün olduğunda), olabilir Yardım.

Bunlar bence sağlam ilkelerdir, ancak pratikte bunu kanıtlamak için çaba göstermeden ASCII karakterlerinden başka bir şey olmayacaktır (örneğin, dizilenmiş formda yalnızca rakamlar, noktalama işaretleri ve belki de kısa bir ASCII adı vardır ;-); doğrudan "adil __str__" yaklaşıma geçmek oldukça tipik bir durumdur (ancak birlikte çalıştığım bir programlama ekibi bundan kaçınmak için yerel bir kılavuz önerdiyse, bu konularda hata yapmak kolay olduğu için teklifte +1 olurdum VE msgstr "erken optimizasyon programlamadaki tüm kötülüklerin köküdür" ;-).


2
Python 2.6.2'de belirli bir yerleşik İstisna alt sınıfının örnekleri str (e) ve unicode (e) ile farklı sonuçlar verdiğinden yakın zamanda açıldım. str (e) kullanıcı dostu çıktı verdi; unicode (e) farklı, kullanıcı dostu olmayan çıktılar verdi. Bu, buggy davranışı olarak mı değerlendirilir? Sınıf UnicodeDecodeError; Karışıklığı önlemek için bunu önceden adlandırmadım - istisnanın unicode ile ilgili olması özellikle ilgili değildir.
Paul Du Bois

13

Dünya küçüldükçe, karşılaştığınız herhangi bir dizenin sonunda Unicode içermesi ihtimali vardır. Bu nedenle, yeni uygulamalar için en azından sağlamalısınız __unicode__(). Ayrıca geçersiz kılsanız __str__()da sadece bir tat meselesidir.


8

Django'da hem python2 hem de python3'te çalışıyorsanız, python_2_unicode_compatible dekoratörünü öneririm:

Django, Python 2 ve 3'te çalışan str () ve unicode () yöntemlerini tanımlamak için basit bir yol sağlar : metin döndüren bir str () yöntemi tanımlamanız ve python_2_unicode_compatible () dekoratörünü uygulamanız gerekir.

Başka bir yanıta daha önceki yorumlarda belirtildiği gibi, future.utils'in bazı sürümleri de bu dekoratörü destekler. Sistemimde, python2 için daha yeni bir gelecek modülü ve python3 için geleceği yüklemem gerekiyordu. Bundan sonra, işte fonksiyonel bir örnek:

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

İşte örnek çıktı (burada venv2 / venv3 sanalenv örnekleridir):

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

3

Python 2: Yalnızca __str __ () işlevini uygulayın ve bir unicode döndürün.

Ne zaman __unicode__()atlanır ve biri unicode(o)veya çağırırsa u"%s"%o, Python arar o.__str__()ve sistem kodlamasını kullanarak unicode'a dönüştürür. ( Belgelerine__unicode__() bakınız .)

Bunun tersi doğru değildir. Uygular __unicode__()ancak uygulamazsanız __str__(), birisi aradığında str(o)veya "%s"%oPython geri döner repr(o).


gerekçe

Niçin bir dönüş için çalışacak unicodedan __str__()?
Eğer __str__()getiri unicode, Python otomatik olarak dönüştürür strsistem kodlama kullanarak.

Avantajı nedir?
① Sistem kodlamasının ne olduğu konusunda endişe duymanızı engeller (örn locale.getpreferredencoeding(…).). Bu sadece kişisel olarak dağınık değil, aynı zamanda sistemin yine de ilgilenmesi gereken bir şey olduğunu düşünüyorum. Care Dikkatli olursanız, kodunuz __str__()unicode döndüren Python 3 ile çapraz uyumlu olabilir .

Adlı bir işlevden bir unicode döndürmek aldatıcı değil __str__()mi?
Bir miktar. Ancak, zaten yapıyor olabilirsiniz. Eğer varsa from __future__ import unicode_literalsdosyanızın üst kısmında, sen bile bilmeden bir unicode dönüyoruz iyi bir şans var.

Python 3 ne olacak?
Python 3 kullanmaz __unicode__(). Ancak, __str__()Python 2 veya Python 3 altında unicode döndürecek şekilde uygularsanız , kodunuzun bu kısmı çapraz uyumlu olacaktır.

Ya unicode(o)büyük ölçüde farklı olmak istersem str()?
Hem __str__()(muhtemelen geri dönen str) hem de uygulayın __unicode__(). Ben bu nadir olacağını hayal, ama önemli ölçüde farklı çıktı isteyebilirsiniz (örneğin, gibi özel karakterlerin ASCII sürümleri ":)"için u"☺").

Bazılarının bunu tartışmalı bulabileceğini fark ettim.


1

__unicode__Özellikle yan yana tanımlandığında, Python 2.x'te onu çevreleyen bazı varsayılan davranışların işlevine aşina olmayanlara işaret etmeye değer __str__.

class A :
    def __init__(self) :
        self.x = 123
        self.y = 23.3

    #def __str__(self) :
    #    return "STR      {}      {}".format( self.x , self.y)
    def __unicode__(self) :
        return u"UNICODE  {}      {}".format( self.x , self.y)

a1 = A()
a2 = A()

print( "__repr__ checks")
print( a1 )
print( a2 )

print( "\n__str__ vs __unicode__ checks")
print( str( a1 ))
print( unicode(a1))
print( "{}".format( a1 ))
print( u"{}".format( a1 ))

aşağıdaki konsol çıktısını verir ...

__repr__ checks
<__main__.A instance at 0x103f063f8>
<__main__.A instance at 0x103f06440>

__str__ vs __unicode__ checks
<__main__.A instance at 0x103f063f8>
UNICODE 123      23.3
<__main__.A instance at 0x103f063f8>
UNICODE 123      23.3

Şimdi __str__yöntemi açtığımda

__repr__ checks
STR      123      23.3
STR      123      23.3

__str__ vs __unicode__ checks
STR      123      23.3
UNICODE  123      23.3
STR      123      23.3
UNICODE  123      23.3
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.