अजगर __str__ बनाम __unicode__


213

क्या आप के लिए एक अजगर सम्मेलन है जब आपको __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
sa का मतलब है कि आप यूनिकोड और स्ट्रॉग दोनों तरीकों का निर्माण कर रहे हैं या केवल _ (u "") में स्ट्रिंग्स रखते हैं और स्ट्रिंग (यूनिकोड विधि के बिना) बना सकते हैं?
12

12
क्या उनमें से केवल एक को लागू करने में कोई खराबी है? क्या होता है जब आप केवल लागू करते हैं __unicode__और फिर करते हैं str(obj)?
रिकी

9
unicodeNameErrorपायथन 3 पर उठता है , एक सरल पैटर्न है जो 2 और 3 दोनों में काम करता है?
bradley.ayers

1
@ bradley.ayers futureपैकेज भी python_2_unicode_compatibleनिर्भरता के रूप में Django के बिना प्रदान करता है ।
मोनकेपिट

1
निर्भर करता है। Python3 का उपयोग करता है नहीं करता है यूनिकोड लेकिन इसके बजाय str अजगर 2 के लिए); यूनिकोड
Eddwin पाज़

23

अगर मैं विशेष रूप से किसी दिए गए वर्ग के लिए माइक्रो-ऑप्टिमाइज़िंग स्ट्रिंग के बारे में परवाह नहीं करता था, तो मैं हमेशा __unicode__केवल इसे लागू करूंगा , क्योंकि यह अधिक सामान्य है। जब मैं ऐसे मिनट प्रदर्शन के मुद्दों (जो अपवाद नहीं है, नियम नहीं) के बारे में परवाह करता हूं, __str__केवल होने पर (जब मैं साबित कर सकता हूं कि कड़े उत्पादन में गैर-ASCII वर्ण नहीं होंगे) या दोनों (जब दोनों संभव हैं), हो सकता है मदद।

मुझे लगता है कि ये ठोस सिद्धांत हैं, लेकिन व्यवहार में यह बहुत सामान्य है कि इसे साबित करने के प्रयास के बिना ASCII वर्णों के अलावा कुछ भी नहीं होगा (उदाहरण के लिए कड़े रूप में केवल अंक, विराम चिह्न और शायद एक छोटा ASCII नाम है ;-) जिसमें; मामला "सीधे __str__" दृष्टिकोण पर स्थानांतरित करने के लिए काफी विशिष्ट है, लेकिन अगर एक प्रोग्रामिंग टीम मैंने उससे बचने के लिए एक स्थानीय दिशानिर्देश का प्रस्ताव रखा, तो मैं प्रस्ताव पर +1 करूंगा, क्योंकि इन मामलों में गलती करना आसान है और "समयपूर्व अनुकूलन प्रोग्रामिंग में सभी बुराई की जड़ है" ;-)।


2
अजगर 2.6.2 में, मैं हाल ही में फंस गया क्योंकि एक विशेष रूप से निर्मित अपवाद उपवर्ग के उदाहरणों ने str (e) और यूनिकोड (e) के साथ अलग-अलग परिणाम दिए। str (e) ने उपयोगकर्ता के अनुकूल आउटपुट दिया; यूनिकोड (e) ने अलग-अलग, उपयोगकर्ता-अमित्र उत्पादन दिया। क्या यह बुग्याल व्यवहार माना जाता है? वर्ग यूनिकोडडॉफॉरट्रॉन है; मैंने इसे भ्रम से बचने के लिए सामने नहीं रखा - तथ्य यह है कि अपवाद यूनिकोड-संबंधित विशेष रूप से प्रासंगिक नहीं है।
पॉल डु बोइस

13

दुनिया छोटी होने के साथ, संभावना है कि आपके द्वारा सामना किए जाने वाले किसी भी तार में अंततः यूनिकोड होगा। इसलिए किसी भी नए ऐप के लिए, आपको कम से कम प्रदान करना चाहिए __unicode__()। चाहे आप ओवरराइड करें भी __str__()तो सिर्फ स्वाद की बात है।


8

यदि आप Django में python2 और python3 दोनों में काम कर रहे हैं, तो मैं python_2_unicode_compatible डेकोरेटर की सलाह देता हूं:

Django स्ट्रिंग () और यूनिकोड () विधियों को निर्धारित करता है जो पायथन 2 और 3 पर काम करते हैं: आपको एक str () विधि रिटर्निंग टेक्स्ट और python_2_unicode_compatible () डेकोरेटर को लागू करने के लिए परिभाषित करना होगा ।

जैसा कि पहले एक अन्य जवाब में टिप्पणी में कहा गया था, भविष्य के कुछ संस्करण। मेरे सिस्टम पर, मुझे python2 के लिए एक नया भविष्य मॉड्यूल स्थापित करने और python3 के लिए भविष्य स्थापित करने की आवश्यकता है। उसके बाद, यहाँ एक कार्यात्मक उदाहरण है:

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

पायथन 2: केवल __str __ () को लागू करें, और एक यूनिकोड लौटाएं।

जब __unicode__()छोड़ा जाता है और कोई व्यक्ति कॉल करता है unicode(o)या u"%s"%o, पायथन कॉल करता है o.__str__()और सिस्टम एन्कोडिंग का उपयोग करके यूनिकोड में परिवर्तित होता है। (का प्रलेखन__unicode__() देखें ।)

विपरीत सत्य नहीं है। यदि आप कार्यान्वित करते __unicode__()हैं __str__(), लेकिन तब नहीं , जब कोई फोन करता है str(o)या "%s"%o, पायथन वापस लौटता है repr(o)


दलील

यह एक unicodeसे लौटने के लिए क्यों काम करेगा __str__()?
यदि __str__()एक यूनिकोड लौटाता है, तो पायथन स्वचालित रूप strसे सिस्टम एन्कोडिंग का उपयोग करके इसे परिवर्तित करता है ।

फायदा क्या है?
① यह सिस्टम एन्कोडिंग (यानी, locale.getpreferredencoeding(…)) के बारे में चिंता करने से आपको मुक्त करता है । न केवल वह गन्दा है, व्यक्तिगत रूप से, लेकिन मुझे लगता है कि यह कुछ ऐसा है जिसे सिस्टम को वैसे भी ध्यान रखना चाहिए। ② यदि आप सावधान हैं, तो आपका कोड पायथन 3 के साथ क्रॉस-संगत हो सकता है, जिसमें __str__()यूनिकोड रिटर्न होता है।

क्या यह एक फ़ंक्शन नामक यूनिकोड को वापस करने के लिए धोखा नहीं है __str__()?
थोड़ा सा। हालाँकि, आप पहले से ही ऐसा कर रहे होंगे। यदि आपके पास from __future__ import unicode_literalsआपकी फ़ाइल के शीर्ष पर है, तो एक अच्छा मौका है कि आप यूनिकोड को बिना जाने भी वापस कर सकते हैं।

पायथन 3 के बारे में क्या?
पायथन 3 का उपयोग नहीं करता है __unicode__()। हालाँकि, यदि आप __str__()इसे लागू करते हैं , तो यह पायथन 2 या पायथन 3 के तहत यूनिकोड देता है, तो आपके कोड का वह हिस्सा क्रॉस-संगत होगा।

क्या होगा यदि मैं इससे unicode(o)अलग होना चाहता हूं str()?
दोनों को लागू करें __str__()(संभवतः वापस लौटते हुए str) और __unicode__()। मुझे लगता है इस दुर्लभ होगा, लेकिन आप काफ़ी भिन्न आउटपुट चाहते हो सकता है (उदाहरण के लिए, विशेष वर्ण का ASCII संस्करणों की तरह ":)"के लिए u"☺")।

मुझे लगता है कि कुछ को यह विवादास्पद लग सकता है।


1

यह उन अपरिचित लोगों को इंगित करने के लायक है जो __unicode__फ़ंक्शन के साथ कुछ डिफ़ॉल्ट व्यवहार करते हैं, जो कि पाइथन 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
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.