Python __str__対__unicode__


213

そこにあなたが実装する必要があるときのためのPythonの慣習である__str__()__unicode__()。クラスが__unicode__()より頻繁にオーバーライドするのを見てきまし__str__()たが、一貫性がないようです。どちらか一方を実装する方が良い場合、特定のルールはありますか?両方を実装する必要がある/良い習慣はありますか?

回答:


257

__str__()古いメソッドです-バイトを返します。__unicode__()新しい優先メソッドです-文字を返します。名前はやや混乱しますが、2.xでは互換性の理由でそのまま使用されています。一般に、すべての文字列フォーマットをに入れ__unicode__()、スタブ__str__()メソッドを作成する必要があります。

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

3.0では、str文字が含まれているため、同じメソッドの名前は__bytes__()および__str__()です。これらは期待どおりに動作します。


2
unicodestrメソッドの両方を作成することを意味しますか、それとも_(u "")に文字列を保持し、(unicodeメソッドなしで)文字列を作成しますか?
muntu

12
そのうちの1つだけを実装することに落とし穴はありますか?実装して__unicode__から実行するとどうなりstr(obj)ますか?
RickyA 2013

9
unicodeNameErrorPython 3でa を発生させます。2と3の両方で機能する単純なパターンですか?
bradley.ayers 2013年

1
@ bradley.ayersまた、futureパッケージはpython_2_unicode_compatibleDjangoを依存関係なしで提供します。
モンクピット2016年

1
場合によります。python3はユニコードを使用せず、代わりにstr ;)をPython 2 ユニコードに
Eddwin Paz

23

特定のクラスのマイクロ最適化文字列化について特に気にしない場合は__unicode__、より一般的なため、常に実装するだけにします。そのような細かいパフォーマンスの問題(これは例外であり、規則では__str__ありません)に関心がある場合、(文字列化された出力に非ASCII文字がないことを証明できる場合のみ)または両方(両方が可能である場合)を持っている可能性があります。助けて。

これらは確かな原則だと思いますが、実際にはそれを証明する努力をせずにASCII文字しか存在しないことは非常に一般的です(たとえば、文字列化された形式には数字、句読点、そしておそらく短いASCII名しかありません;-)。直接「ただ__str__」のアプローチに直接進むことが非常に一般的である場合(ただし、私が一緒に作業したプログラミングチームがそれを回避するためにローカルガイドラインを提案した場合、これらの問題で誤りが発生しやすいため、提案に+1します。 「時期尚早な最適化はプログラミングにおけるすべての悪の根源です」;-)。


2
python 2.6.2では、特定の組み込みExceptionサブクラスのインスタンスがstr(e)とunicode(e)で異なる結果を返すため、最近トリップしました。str(e)はユーザーフレンドリーな出力を提供しました。unicode(e)は、ユーザーにわかりにくいさまざまな出力を提供しました。これはバグのある動作と見なされますか?クラスはUnicodeDecodeErrorです。混乱を避けるために、前もって名前を付けていませんでした-例外がユニコードに関連しているという事実は、特に関係ありません。
Paul Du Bois

13

世界が小さくなるにつれて、遭遇する文字列には最終的にUnicodeが含まれる可能性があります。新しいアプリの場合は、少なくともを提供する必要があります__unicode__()。オーバーライドもするかどうか__str__()は、好みの問題です。


8

Djangoのpython2とpython3の両方で作業している場合は、python_2_unicode_compatibleデコレーターをお勧めします。

Djangoは、Python 2および3で機能するstr()および unicode()メソッドを定義する簡単な方法を提供します。テキストを返すstr()メソッドを定義し、python_2_unicode_compatible()デコレータを適用する必要があります。

別の回答に対する以前のコメントで述べたように、future.utilsの一部のバージョンもこのデコレーターをサポートしています。私のシステムでは、python2の新しいfutureモジュールをインストールし、python3のfutureをインストールする必要がありました。その後、機能的な例を次に示します。

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

次に出力例を示します(ここでvenv2 / venv3は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__

3

Python 2: __str __()のみを実装し、ユニコードを返します。

場合__unicode__()省略している人の呼び出しunicode(o)またはu"%s"%o、Pythonのコールo.__str__()と変換システムエンコーディングを使用してUnicodeに。(のドキュメントを__unicode__()参照してください。)

反対は真実ではありません。実装しても実装し__unicode__()ない__str__()場合、誰かがstr(o)orを呼び出すと"%s"%o、Pythonが返されますrepr(o)


根拠

unicodefrom を返すのはなぜでしょう__str__()か?がユニコードを返す
場合__str__()、Pythonは自動的strにシステムエンコーディングを使用するように変換します。

メリットは何ですか?
①システムエンコーディングが何であるかを気にする必要がありません(つまり、locale.getpreferredencoeding(…))。個人的には面倒なだけでなく、システムが対処すべきことだと思います。②注意すると、コードがPython 3と相互互換になる可能性があり__str__()ます。

呼び出された関数からユニコードを返すのは不正ではありません__str__()か?
少し。ただし、すでに実行している可能性があります。あなたが持っている場合はfrom __future__ import unicode_literals、ファイルの先頭に、あなたもそれを知らずにユニコードを返している可能性が高いと言えます。

Python 3はどうですか?
Python 3はを使用しません__unicode__()。ただし、__str__()Python 2またはPython 3のいずれかでユニコードを返すように実装すると、コードのその部分は相互互換性があります。

unicode(o)実質的に違うものにしたい場合はどうなりstr()ますか?
の両方を実装します__str__()(おそらく戻るstr)と__unicode__()。これはまれだと思いますが、実質的に異なる出力が必要な場合があります(たとえば、":)"forのような特殊文字のASCIIバージョンu"☺")。

一部の人がこの論争を呼ぶかもしれないことに気づきます。


1

__unicode__特に2.と並べて定義されている場合、Python 2.xで関数を取り巻くデフォルトの動作のいくつかに慣れていない人に指摘する価値があります__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 ))

次のコンソール出力が生成されます...

__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

__str__メソッドをコメントアウトすると、

__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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.