python __Str__ और __repr__ के बीच अंतर?





10 Answers

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

python magic-methods repr

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




__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



पायथन में __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__ परिभाषित करें जब आपको इसके मानव पठनीय स्ट्रिंग प्रस्तुति की आवश्यकता होती है।




हंस पेटटर लैंगटैंगन द्वारा कम्प्यूटेशनल साइंस के लिए पायथन स्क्रीटिंग पुस्तक के पृष्ठ 358 पर, यह स्पष्ट रूप से बताता है कि

  • __repr__ उद्देश्य वस्तु के पूर्ण स्ट्रिंग प्रतिनिधित्व पर है;
  • __str__ मुद्रण के लिए एक अच्छी तरह से स्ट्रिंग वापस करने के लिए है।

इसलिए, मैं उन्हें समझना पसंद करता हूं

  • repr = पुनरुत्पादन
  • str = स्ट्रिंग (प्रतिनिधित्व)

उपयोगकर्ता के दृष्टिकोण से हालांकि यह एक गलतफहमी है जिसे मैंने पाइथन सीखते समय बनाया था।

एक ही पृष्ठ पर एक छोटा लेकिन अच्छा उदाहरण भी दिया गया है:

उदाहरण

In [38]: str('s')
Out[38]: 's'

In [39]: repr('s')
Out[39]: "'s'"

In [40]: eval(str('s'))
Traceback (most recent call last):

  File "<ipython-input-40-abd46c0c43e7>", line 1, in <module>
    eval(str('s'))

  File "<string>", line 1, in <module>

NameError: name 's' is not defined


In [41]: eval(repr('s'))
Out[41]: 's'



अगर सरल शब्द में कहा जाए तो:

__str__ का उपयोग दूसरों द्वारा आसानी से पढ़ने के लिए आपके ऑब्जेक्ट का स्ट्रिंग प्रस्तुति दिखाने के लिए किया जाता है।

__repr__ ऑब्जेक्ट का स्ट्रिंग प्रस्तुति दिखाने के लिए प्रयोग किया जाता है।

मान लें कि मैं एक Fraction वर्ग बनाना चाहता हूं जहां एक अंश का स्ट्रिंग प्रस्तुति '(1/2)' है और ऑब्जेक्ट (फ्रैक्शन क्लास) को 'फ्रैक्शन (1,2)' के रूप में दर्शाया जाना है।

तो हम एक साधारण फ्रैक्शन वर्ग बना सकते हैं:

class Fraction:
    def __init__(self, num, den):
        self.__num = num
        self.__den = den

    def __str__(self):
        return '(' + str(self.__num) + '/' + str(self.__den) + ')'

    def __repr__(self):
        return 'Fraction (' + str(self.__num) + ',' + str(self.__den) + ')'



f = Fraction(1,2)
print('I want to represent the Fraction STRING as ' + str(f)) # (1/2)
print('I want to represent the Fraction OBJECT as ', repr(f)) # Fraction (1,2)



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

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

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




"A basic requirement for a Python object is to provide usable 
 string   representations of itself, one used for debugging and
 logging, another for presentation to end users. That is why the  
 special methods __repr__ and __str__ exist in the data model."

पुस्तक से: फ्लुएंट पायथन




>>> print(decimal.Decimal(23) / decimal.Decimal("1.05"))
21.90476190476190476190476190
>>> decimal.Decimal(23) / decimal.Decimal("1.05")
Decimal('21.90476190476190476190476190')

जब प्रिंट () को दशमलव के परिणाम पर कॉल किया जाता है। डेसिमल (23) / डेसी-माल। डेसीमल ("1.05") कच्चे नंबर को मुद्रित किया जाता है; यह आउटपुट स्ट्रिंग फॉर्म में है जिसे __str __ () के साथ हासिल किया जा सकता है। अगर हम अभिव्यक्ति दर्ज करते हैं तो हमें दशमलव मिलता है। दशमलव आउटपुट - यह आउटपुट प्रतिनिधित्वकारी रूप में है जिसे __repr __ () के साथ प्राप्त किया जा सकता है। सभी पायथन वस्तुओं में दो आउटपुट फॉर्म होते हैं। स्ट्रिंग फॉर्म मानव-पठनीय होने के लिए डिज़ाइन किया गया है। प्रतिनिधि प्रपत्र आउटपुट का उत्पादन करने के लिए डिज़ाइन किया गया है कि यदि एक पाइथन दुभाषिया को खिलाया जाता है (जब संभव हो) प्रतिनिधित्व वस्तु का पुन: उत्पादन करेगा




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__ को समझदारी से समझें और स्थायी रूप से उन्हें अलग करें।

__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

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




Related