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




magic-methods (17)

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


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

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

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

3) यदि, __repr__() गुम है, तो __repr__() str() का उपयोग करके प्रिंट और कोई फ़ंक्शन ऑब्जेक्ट के __repr__() को आमंत्रित करता है।

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

5) __str__() भीतर बुलाया गया str() आधार आधार के बिना संभावित रूप से __str__() कर सकता है, और अधिकतम रिकर्सन गहराई पर त्रुटि हो सकती है।

6) __repr__() repr() __repr__() को कॉल कर सकता है जो स्वचालित रूप से असीमित रिकर्सन से बचने का प्रयास करेगा, पहले से प्रदर्शित ऑब्जेक्ट को प्रतिस्थापित कर देगा ...


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

__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)

जब तक आप विशेष रूप से अन्यथा सुनिश्चित करने के लिए कार्य नहीं करते हैं, तब तक अधिकांश वर्गों के लिए सहायक परिणाम नहीं होते हैं:

>>> class Sic(object): pass
... 
>>> print str(Sic())
<__main__.Sic object at 0x8b7d0>
>>> print repr(Sic())
<__main__.Sic object at 0x8b7d0>
>>> 

जैसा कि आप देखते हैं - कोई फर्क नहीं पड़ता, और कक्षा और ऑब्जेक्ट की id से परे कोई जानकारी नहीं है। यदि आप केवल दो में से एक को ओवरराइड करते हैं ...:

>>> class Sic(object): 
...   def __repr__(object): return 'foo'
... 
>>> print str(Sic())
foo
>>> print repr(Sic())
foo
>>> class Sic(object):
...   def __str__(object): return 'foo'
... 
>>> print str(Sic())
foo
>>> print repr(Sic())
<__main__.Sic object at 0x2617f0>
>>> 

जैसा कि आप देखते हैं, यदि आप __repr__ ओवरराइड करते हैं, तो यह भी __str__ लिए उपयोग किया जाता है, लेकिन इसके विपरीत नहीं।

अन्य महत्वपूर्ण tidbits को जानने के लिए: एक निर्मित कंटेनर पर __repr__ का उपयोग करता है, __repr__ नहीं, इसमें मौजूद वस्तुओं के लिए। और, ठेठ दस्तावेज़ों में पाए गए विषय पर शब्दों के बावजूद, शायद ही कोई भी ऑब्जेक्ट्स के __repr__ को बनाने की परेशानी करता है, एक स्ट्रिंग है जो eval एक समान वस्तु बनाने के लिए उपयोग कर सकती है (यह बहुत कठिन है, और यह नहीं जानती कि प्रासंगिक मॉड्यूल वास्तव में कैसे आयात किया गया था यह वास्तव में असंभव बाहर फ्लैट)।

तो, मेरी सलाह: __str__ उचित रूप से मानव-पठनीय बनाने के लिए ध्यान केंद्रित करें, और __repr__ जितना संभव हो उतना स्पष्ट हो, भले ही वह __eval__ लौटे हुए मूल्य को __eval__ में इनपुट के रूप में स्वीकार्य बनाने के अस्पष्ट अटूट लक्ष्य के साथ हस्तक्षेप __eval__ !


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

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

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

Alex ने संक्षेप में संक्षेप में बताया, लेकिन आश्चर्यजनक रूप से, बहुत संक्षिप्त था।

सबसे पहले, मुझे एलेक्स के पोस्ट में मुख्य बिंदु दोहराएं :

  • डिफ़ॉल्ट कार्यान्वयन बेकार है (किसी के बारे में सोचना मुश्किल है जो नहीं होगा, लेकिन हाँ)
  • __repr__ लक्ष्य अस्पष्ट होना है
  • __str__ लक्ष्य पठनीय होना है
  • कंटेनर का __str__ निहित वस्तुओं का उपयोग करता है ' __repr__

डिफ़ॉल्ट कार्यान्वयन बेकार है

यह ज्यादातर आश्चर्यचकित है क्योंकि पायथन का डिफ़ॉल्ट काफी उपयोगी होता है। हालांकि, इस मामले में, __repr__ लिए डिफ़ॉल्ट होना जो इस प्रकार कार्य करेगा:

return "%s(%r)" % (self.__class__, self.__dict__)

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

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

__repr__ का लक्ष्य स्पष्ट होना है

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

log(INFO, "I am in the weird function and a is", a, "and b is", b, "but I got a null C — using default", default_c)

लेकिन आपको अंतिम चरण करना है - सुनिश्चित करें कि आपके द्वारा लागू हर ऑब्जेक्ट में एक उपयोगी प्रतिनिधि है, इसलिए ऐसा कोड बस काम कर सकता है। यही कारण है कि "eval" चीज आती है: यदि आपके पास पर्याप्त जानकारी है तो eval(repr(c))==c , इसका मतलब है कि आप c बारे में जानने के लिए सबकुछ जानते हैं। यदि यह कम से कम एक अस्पष्ट तरीके से पर्याप्त है, तो इसे करें। यदि नहीं, तो सुनिश्चित करें कि आपके पास c बारे में पर्याप्त जानकारी है। मैं आमतौर पर एक eval- जैसे प्रारूप का उपयोग करता हूं: "MyClass(this=%r,that=%r)" % (self.this,self.that) । इसका मतलब यह नहीं है कि आप वास्तव में MyClass का निर्माण कर सकते हैं, या वे सही कन्स्ट्रक्टर तर्क हैं - लेकिन यह अभिव्यक्ति करने के लिए एक उपयोगी रूप है "यह सब कुछ है जिसे आपको इस उदाहरण के बारे में जानने की आवश्यकता है"।

नोट: मैंने %s उपयोग किया, %s नहीं। आप हमेशा __repr__ कार्यान्वयन के अंदर repr() [या %r स्वरूपण वर्ण, समकक्ष] का उपयोग करना चाहते हैं, या आप repr के लक्ष्य को हरा रहे हैं। आप MyClass(3) और MyClass("3") को अलग करने में सक्षम होना चाहते हैं।

__str__ का लक्ष्य पठनीय होना है

विशेष रूप से, यह स्पष्ट नहीं है - ध्यान दें कि str(3)==str("3") । इसी प्रकार, यदि आप एक आईपी अबास्ट्रक्शन लागू करते हैं, तो इसका स्ट्रिंग 1 9 2.168.1.1 जैसा दिखता है ठीक है। दिनांक / समय अबास्ट्रक्शन को कार्यान्वित करते समय, str "2010/4/12 15:35:22" हो सकता है, लक्ष्य इसका प्रतिनिधित्व इस तरह से करना है कि एक उपयोगकर्ता, प्रोग्रामर नहीं, इसे पढ़ना चाहेगा। बेकार अंकों को बंद करो, कुछ अन्य वर्ग होने का नाटक करें - जब तक यह पठनीयता का समर्थन करता है, यह एक सुधार है।

कंटेनर का __str__ निहित वस्तुओं का उपयोग करता है ' __repr__

यह आश्चर्यजनक लगता है, है ना? यह थोड़ा सा है, लेकिन कितना पठनीय होगा

[moshe is, 3, hello
world, this is a list, oh I don't know, containing just 4 elements]

हो सकता है? बहुत नहीं। विशेष रूप से, एक कंटेनर में तारों को इसकी स्ट्रिंग प्रस्तुति को परेशान करने के लिए बहुत आसान तरीका मिल जाएगा। अस्पष्टता के सामने, याद रखें, पायथन अनुमान लगाने के लिए प्रलोभन का विरोध करता है। यदि आप एक सूची मुद्रित करते समय उपर्युक्त व्यवहार चाहते हैं, तो बस

print "[" + ", ".join(l) + "]"

(आप शायद यह भी पता लगा सकते हैं कि शब्दकोशों के बारे में क्या करना है।

सारांश

आपके द्वारा कार्यान्वित किसी भी वर्ग के लिए __repr__ लागू करें। यह दूसरी प्रकृति होनी चाहिए। __str__ लागू करें यदि आपको लगता है कि यह एक स्ट्रिंग संस्करण होना उपयोगी होगा जो अधिक अस्पष्टता के पक्ष में अधिक पठनीयता के पक्ष में गलती करता है।


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

__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__ पहचानने के लिए असंबद्धता के लिए किसी दिए गए ऑब्जेक्ट (खुद को लौटाएं) के वास्तविक मांस निकाय को वापस कर दें।

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

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

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


"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."

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


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

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

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


संक्षेप में, __repr__ का लक्ष्य अस्पष्ट होना चाहिए और __str__ को पठनीय होना है।

यहां एक अच्छा उदाहरण है:

>>> import datetime
>>> today = datetime.datetime.now()
>>> str(today)
'2012-03-14 09:21:58.130922'
>>> repr(today)
'datetime.datetime(2012, 3, 14, 9, 21, 58, 130922)'

Repr के लिए इस दस्तावेज़ को पढ़ें:

repr(object)

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

Str के लिए प्रलेखन यहां दिया गया है:

str(object='')

एक ऑब्जेक्ट का एक अच्छी तरह से मुद्रित प्रतिनिधित्व युक्त एक स्ट्रिंग लौटें। तारों के लिए, यह स्ट्रिंग स्वयं ही देता है। repr(object) साथ अंतर यह है कि str(object) हमेशा एक स्ट्रिंग को वापस करने का प्रयास नहीं करता है जो eval() को स्वीकार्य है; इसका लक्ष्य एक प्रिंट करने योग्य स्ट्रिंग को वापस करना है। यदि कोई तर्क नहीं दिया जाता है, तो खाली स्ट्रिंग देता है, ''


संक्षेप में:

class Demo:
  def __repr__(self):
    return 'repr'
  def __str__(self):
    return 'str'

demo = Demo()
print(demo) # use __str__, output 'str' to stdout

s = str(demo) # __str__ is used, return 'str'
r = repr(demo) # __repr__ is used, return 'repr'

import logging
logger = logging.getLogger(logging.INFO)
logger.info(demo) # use __str__, output 'str' to stdout

from pprint import pprint, pformat
pprint(demo) # use __repr__, output 'repr' to stdout
result = pformat(demo) # use __repr__, result is string which value is 'str'

सभी ईमानदारी में, eval(repr(obj)) का कभी भी उपयोग नहीं किया जाता है। यदि आप इसे स्वयं का उपयोग करते हैं, तो आपको रोकना चाहिए, क्योंकि eval खतरनाक है, और तार आपके ऑब्जेक्ट्स को क्रमबद्ध करने के लिए एक बहुत ही अक्षम तरीका है (इसके बजाय pickle उपयोग करें)।

इसलिए, मैं __repr__ = __str__ सेटिंग की अनुशंसा करता हूं। कारण यह है कि str(list) तत्वों पर repr कहते हैं (मैं इसे पायथन की सबसे बड़ी डिजाइन त्रुटियों में से एक माना जाता है जिसे पायथन 3 द्वारा संबोधित नहीं किया गया था)। print [your, objects] आउटपुट print [your, objects] के आउटपुट के रूप में एक वास्तविक repr शायद बहुत उपयोगी नहीं होगा।

इसे अर्हता प्राप्त करने के लिए, मेरे अनुभव में, repr फ़ंक्शन का सबसे उपयोगी उपयोग केस स्ट्रिंग स्वरूपण का उपयोग करके स्ट्रिंग को अन्य स्ट्रिंग के अंदर रखना है। इस तरह, आपको उद्धरण या कुछ भी बचने की चिंता करने की ज़रूरत नहीं है। लेकिन ध्यान दें कि यहां कोई eval नहीं हुआ है।


__repr__ को हर जगह प्रयोग किया जाता है, print और str को छोड़कर जब __str__ परिभाषित किया जाता है


>>> 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 __ () के साथ प्राप्त किया जा सकता है। सभी पायथन वस्तुओं में दो आउटपुट फॉर्म होते हैं। स्ट्रिंग फॉर्म मानव-पठनीय होने के लिए डिज़ाइन किया गया है। प्रतिनिधि प्रपत्र आउटपुट का उत्पादन करने के लिए डिज़ाइन किया गया है कि यदि एक पाइथन दुभाषिया को खिलाया जाता है (जब संभव हो) प्रतिनिधित्व वस्तु का पुन: उत्पादन करेगा


ध्यान में रखना एक महत्वपूर्ण बात यह है कि कंटेनर का __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 - वस्तु के canonical स्ट्रिंग प्रतिनिधित्व देता है।

भिन्नताएं:

str ():

  • ऑब्जेक्ट पठनीय बनाता है
  • एंड-यूजर के लिए आउटपुट उत्पन्न करता है

रेपर ():

  • ऑब्जेक्ट को पुन: उत्पन्न करने वाले कोड की आवश्यकता होती है
  • डेवलपर के लिए आउटपुट उत्पन्न करता है




repr