[python] __str__ और __repr__ के बीच अंतर?


Answers

अंगूठे का मेरा नियम: __repr__ डेवलपर्स के लिए है, __str__ ग्राहकों के लिए है।

Question

Python में __str__ और __repr__ बीच क्या अंतर है?




ध्यान में रखना एक महत्वपूर्ण बात यह है कि कंटेनर का __str__ निहित वस्तुओं का उपयोग करता है ' __repr__

>>> from datetime import datetime
>>> from decimal import Decimal
>>> print (Decimal('52'), datetime.now())
(Decimal('52'), datetime.datetime(2015, 11, 16, 10, 51, 26, 185000))
>>> str((Decimal('52'), datetime.now()))
"(Decimal('52'), datetime.datetime(2015, 11, 16, 10, 52, 22, 176000))"

पायथन पठनीयता पर असंबद्धता का समर्थन करता है , एक tuple कॉल निहित वस्तुओं ' __repr__ , किसी ऑब्जेक्ट का "औपचारिक" प्रतिनिधित्व कहता है। हालांकि औपचारिक प्रतिनिधित्व एक अनौपचारिक से पढ़ने के लिए कठिन है, यह बग के खिलाफ स्पष्ट और अधिक मजबूत है।




उत्कृष्ट उत्तरों में पहले से ही __str__ और __repr__ बीच का अंतर शामिल है, जो मेरे लिए अंतिम उपयोगकर्ता द्वारा भी पढ़ने योग्य पूर्व तक उबलता है, और बाद वाले डेवलपर्स के लिए जितना संभव हो उतना उपयोगी होता है। यह देखते हुए, मुझे लगता है कि __repr__ का डिफ़ॉल्ट कार्यान्वयन अक्सर इस लक्ष्य को प्राप्त करने में विफल रहता है क्योंकि यह डेवलपर्स के लिए उपयोगी जानकारी को छोड़ देता है।

इस कारण से, यदि मेरे पास पर्याप्त सरल __str__ , तो मैं आम तौर पर दोनों दुनिया के सर्वश्रेष्ठ कुछ प्राप्त करने का प्रयास करता हूं जैसे:

def __repr__(self):
    return '{0} ({1})'.format(object.__repr__(self), str(self))



पायथन में __str__ और __repr__ बीच क्या अंतर है?

__str__ ("डंडर (डबल-अंडरस्कोर) स्ट्रिंग" के रूप में पढ़ें) और __repr__ ("डंडर-रिपपर" ("प्रतिनिधित्व" के लिए) के रूप में पढ़ें) दोनों विशेष विधियां हैं जो ऑब्जेक्ट की स्थिति के आधार पर स्ट्रिंग लौटाती हैं।

यदि __str__ गुम है तो __str__ बैकअप व्यवहार प्रदान करता है।

तो सबसे पहले एक __repr__ लिखना चाहिए जो आपको स्ट्रिंग से प्राप्त समकक्ष ऑब्जेक्ट को पुन: स्थापित करने की अनुमति देता है जैसे कि eval का उपयोग करके या इसे पायथन शेल में वर्ण-के-चरित्र में टाइप करके।

किसी भी समय बाद में, कोई उदाहरण के उपयोगकर्ता-पठनीय स्ट्रिंग प्रस्तुति के लिए __str__ लिख सकता है, जब कोई मानता है कि यह आवश्यक है।

__str__

यदि आप किसी ऑब्जेक्ट को प्रिंट करते हैं, या format , str.format , या str , तो यदि एक str.format विधि परिभाषित की जाती है, तो उस विधि को बुलाया जाएगा, अन्यथा, __repr__ का उपयोग किया जाएगा।

__repr__

__repr__ विधि को बिल्टिन फ़ंक्शन repr द्वारा बुलाया जाता है और यह आपके पाइथन शेल पर प्रतिबिंबित होता है जब यह किसी ऑब्जेक्ट को लौटने वाली अभिव्यक्ति का मूल्यांकन करता है।

चूंकि यह __str__ लिए बैकअप प्रदान करता है, अगर आप केवल एक लिख सकते हैं, तो __repr__ शुरू करें

Repr पर अंतर्निहित सहायता यहां दी गई है:

repr(...)
    repr(object) -> string

    Return the canonical string representation of the object.
    For most object types, eval(repr(object)) == object.

यही है, ज्यादातर ऑब्जेक्ट्स के लिए, यदि आप repr द्वारा मुद्रित किए गए टाइप में टाइप करते हैं, तो आप समकक्ष ऑब्जेक्ट बनाने में सक्षम होना चाहिए। लेकिन यह डिफ़ॉल्ट कार्यान्वयन नहीं है।

__repr__ का डिफ़ॉल्ट कार्यान्वयन

डिफ़ॉल्ट ऑब्जेक्ट __repr__ है ( सी पायथन स्रोत ) कुछ ऐसा है:

def __repr__(self):
    return '<{0}.{1} object at {2}>'.format(
      self.__module__, type(self).__name__, hex(id(self)))

इसका मतलब है कि डिफ़ॉल्ट रूप से आप उस मॉड्यूल को प्रिंट करेंगे, ऑब्जेक्ट क्लास नाम, और मेमोरी में इसके स्थान के हेक्साडेसिमल प्रतिनिधित्व - उदाहरण के लिए:

<__main__.Foo object at 0x7f80665abdd0>

यह जानकारी बहुत उपयोगी नहीं है, लेकिन कोई भी तरीका प्राप्त करने का कोई तरीका नहीं है कि कोई भी किसी दिए गए उदाहरण के कैननिकल प्रतिनिधित्व को सही तरीके से कैसे बना सकता है, और यह कम से कम कुछ भी नहीं है, कम से कम हमें बता रहा है कि हम इसे स्मृति में विशिष्ट रूप से कैसे पहचान सकते हैं।

__repr__ कैसे उपयोगी हो सकता है?

चलो देखते हैं कि पाइथन शेल और datetime ऑब्जेक्ट्स का उपयोग करके यह कितना उपयोगी हो सकता है। सबसे पहले हमें datetime मॉड्यूल आयात करने की आवश्यकता है:

import datetime

यदि हम शैल में datetime.now कहते हैं। अब, हम समतुल्य डेटाटाइम ऑब्जेक्ट को फिर से बनाने के लिए आवश्यक सब कुछ देखेंगे। यह डेटाटाइम __repr__ द्वारा बनाया गया है:

>>> datetime.datetime.now()
datetime.datetime(2015, 1, 24, 20, 5, 36, 491180)

यदि हम डेटाटाइम ऑब्जेक्ट प्रिंट करते हैं, तो हम एक अच्छा मानव पठनीय (वास्तव में, आईएसओ) प्रारूप देखते हैं। यह __str__ द्वारा कार्यान्वित किया जाता है:

>>> print(datetime.datetime.now())
2015-01-24 20:05:44.977951

हमारे द्वारा खोए गए ऑब्जेक्ट को फिर से बनाना एक साधारण बात है क्योंकि हमने इसे __repr__ आउटपुट से प्रतिलिपि बनाने और चिपकाने के द्वारा एक चर को असाइन नहीं किया है, और उसके बाद इसे प्रिंट किया है, और हम इसे अन्य ऑब्जेक्ट के समान मानव पठनीय आउटपुट में प्राप्त करते हैं:

>>> the_past = datetime.datetime(2015, 1, 24, 20, 5, 36, 491180)
>>> print(the_past)
2015-01-24 20:05:36.491180

मैं उन्हें कैसे लागू करूं?

जैसे-जैसे आप विकास कर रहे हैं, यदि आप संभव हो तो उसी स्थिति में ऑब्जेक्ट्स को पुन: उत्पन्न करने में सक्षम होना चाहेंगे। उदाहरण के लिए, डेटाटाइम ऑब्जेक्ट __repr__ ( पायथन स्रोत ) को परिभाषित करता है। यह काफी जटिल है, इस तरह की वस्तु को पुन: उत्पन्न करने के लिए आवश्यक सभी विशेषताओं के कारण:

def __repr__(self):
    """Convert to formal string, for repr()."""
    L = [self._year, self._month, self._day, # These are never zero
         self._hour, self._minute, self._second, self._microsecond]
    if L[-1] == 0:
        del L[-1]
    if L[-1] == 0:
        del L[-1]
    s = ", ".join(map(str, L))
    s = "%s(%s)" % ('datetime.' + self.__class__.__name__, s)
    if self._tzinfo is not None:
        assert s[-1:] == ")"
        s = s[:-1] + ", tzinfo=%r" % self._tzinfo + ")"
    return s

यदि आप चाहते हैं कि आपकी ऑब्जेक्ट में अधिक मानव पठनीय प्रतिनिधित्व हो, तो आप अगले __str__ को कार्यान्वित कर सकते हैं। यहां बताया गया है कि डेटाटाइम ऑब्जेक्ट ( पायथन स्रोत ) __str__ लागू करता है, जो यह आसानी से करता है क्योंकि इसमें पहले से ही इसे आईएसओ प्रारूप में प्रदर्शित करने के लिए एक फ़ंक्शन है:

def __str__(self):
    "Convert to string, for str()."
    return self.isoformat(sep=' ')

__repr__ = __str__ सेट करें?

यह यहां एक और उत्तर की आलोचना है जो __repr__ = __str__ स्थापित करने का सुझाव देती है।

__repr__ = __str__ को सेट करना मूर्खतापूर्ण है - __repr__ लिए फॉलबैक है और __repr__ , जो डिबगिंग में डेवलपर्स के उपयोग के लिए लिखा गया है, आपको __str__ लिखने से पहले लिखा जाना चाहिए।

आपको केवल __str__ की आवश्यकता होती है जब आपको ऑब्जेक्ट का टेक्स्ट प्रस्तुतिकरण की आवश्यकता होती है।

निष्कर्ष

आपके द्वारा लिखे गए ऑब्जेक्ट्स के लिए __repr__ को परिभाषित करें ताकि आप और अन्य डेवलपर्स के पास इसका उपयोग करते समय पुन: उत्पन्न उदाहरण हो। __str__ परिभाषित करें जब आपको इसके मानव पठनीय स्ट्रिंग प्रस्तुति की आवश्यकता होती है।




__repr__ : पाइथन ऑब्जेक्ट का प्रतिनिधित्व आमतौर पर eval उस वस्तु को वापस परिवर्तित कर देगा

__str__ : जो कुछ भी आपको लगता है वह वस्तु है जो पाठ रूप में है

जैसे

>>> s="""w'o"w"""
>>> repr(s)
'\'w\\\'o"w\''
>>> str(s)
'w\'o"w'
>>> eval(str(s))==s
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1
    w'o"w
       ^
SyntaxError: EOL while scanning single-quoted string
>>> eval(repr(s))==s
True



blog से बहुत स्पष्ट है

str स्ट्रिंग की तरह है। बनाया गया है ताकि आप डेटा repr मुद्रित कर सकते हैं serialize, या अचार की तरह है। अगर मैं eval () का उपयोग कर ऐसा करने की ज़रूरत है तो मैं इस ऑब्जेक्ट को फिर से कैसे बना सकता हूं

>>> import datetime
>>> now = datetime.datetime.now() 
>>> str(now)
'2015-04-04 20:51:31.766862'
>>> repr(now)
'datetime.datetime(2015, 4, 4, 20, 51, 31, 766862)'
>>mydate = eval(repr(now))



एक पहलू जो अन्य उत्तरों में गायब है। यह सच है कि सामान्य रूप से पैटर्न है:

  • __str__ का लक्ष्य: मानव-पठनीय
  • __repr__ का लक्ष्य: स्पष्ट, संभावित रूप से मशीन-पठनीय eval माध्यम से

दुर्भाग्यवश, यह भेदभाव त्रुटिपूर्ण है, क्योंकि पाइथन आरईपीएल और आईपीथॉन एक आरईपीएल कंसोल में प्रिंटिंग ऑब्जेक्ट्स के लिए __repr__ का उपयोग करते हैं ( Python और IPython के लिए संबंधित प्रश्न देखें)। इस प्रकार, परियोजनाएं जो इंटरैक्टिव कंसोल काम (उदाहरण के लिए, नम्पी या पांडस) के लिए लक्षित हैं, ने नियमों को अनदेखा करना शुरू कर दिया है और इसके बजाय मानव-पठनीय __repr__ कार्यान्वयन प्रदान किया है।




__str__ और __repr__ को समझदारी से समझें और स्थायी रूप से उन्हें अलग करें।

__str__ आंखों के पठनीय के लिए किसी दिए गए ऑब्जेक्ट के स्ट्रिंग छिपे हुए शरीर को वापस कर दें
__repr__ पहचानने के लिए असंबद्धता के लिए किसी दिए गए ऑब्जेक्ट (खुद को लौटाएं) के वास्तविक मांस निकाय को वापस कर दें।

इसे एक उदाहरण में देखें

In [30]: str(datetime.datetime.now())
Out[30]: '2017-12-07 15:41:14.002752'
Disguised in string form

__repr__ रूप में

In [32]: datetime.datetime.now()
Out[32]: datetime.datetime(2017, 12, 7, 15, 43, 27, 297769)
Presence in real body which allows to be manipulated directly.

हम आसानी से __repr__ परिणामों पर अंकगणितीय ऑपरेशन कर सकते हैं।

In [33]: datetime.datetime.now()
Out[33]: datetime.datetime(2017, 12, 7, 15, 47, 9, 741521)
In [34]: datetime.datetime(2017, 12, 7, 15, 47, 9, 741521) - datetime.datetime(2
    ...: 017, 12, 7, 15, 43, 27, 297769)
Out[34]: datetime.timedelta(0, 222, 443752)

यदि __str__ पर ऑपरेशन लागू करें

In [35]: '2017-12-07 15:43:14.002752' - '2017-12-07 15:41:14.002752'
TypeError: unsupported operand type(s) for -: 'str' and 'str'

त्रुटि के अलावा कुछ भी नहीं देता है।

एक और उदाहरण।

In [36]: str('string_body')
Out[36]: 'string_body' # in string form

In [37]: repr('real_body')
Out[37]: "'real_body'" #its real body hide inside

आशा है कि इससे आपको अधिक उत्तरों का पता लगाने के लिए ठोस आधार तैयार करने में मदद मिलेगी।




दिए गए सभी उत्तरों के अलावा, मैं कुछ अंक जोड़ना चाहता हूं: -

1) __str__() जब आप प्रिंट स्टेटमेंट के साथ ऑब्जेक्ट का उपयोग करते हैं तो लागू किया जाता है। यदि, __repr__() गुम है, तो ऑब्जेक्ट के __repr__() को मुद्रित करें।

2) __repr__() तब लागू होता है जब आप इंटरैक्टिव पायथन कंसोल पर ऑब्जेक्ट का नाम लिखते हैं और एंटर दबाते हैं।

3) कंटेनर के __str__() , जब लागू किया जाता है तो इसके निहित तत्वों के __repr__() विधि को निष्पादित किया जाएगा।




Effbot द्वारा http://pyref.infogami.com/__str__ से:

__str__ "किसी ऑब्जेक्ट की" अनौपचारिक "स्ट्रिंग प्रस्तुति की गणना करता है। यह __repr__ से अलग है जिसमें यह एक वैध पायथन अभिव्यक्ति नहीं है: इसके बजाय एक अधिक सुविधाजनक या संक्षिप्त प्रतिनिधित्व का उपयोग किया जा सकता है।"






Links