क्लास ऑब्जेक्ट के लिए कस्टम स्ट्रिंग प्रतिनिधित्व कैसे बनाएं?


202

इस वर्ग पर विचार करें:

class foo(object):
    pass

डिफ़ॉल्ट स्ट्रिंग प्रतिनिधित्व कुछ इस तरह दिखता है:

>>> str(foo)
"<class '__main__.foo'>"

मैं इस प्रदर्शन को कस्टम स्ट्रिंग कैसे बना सकता हूं?

जवाबों:


272

लागू करें __str__()या __repr__()कक्षा के मेटाक्लस में।

class MC(type):
  def __repr__(self):
    return 'Wahaha!'

class C(object):
  __metaclass__ = MC

print C

का प्रयोग करें __str__आप एक पठनीय stringification, उपयोग मतलब अगर __repr__स्पष्ट अभ्यावेदन के लिए।


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

दुर्भाग्य से यह वर्ग सज्जाकारों के साथ नहीं किया जा सकता है; यह तब निर्धारित किया जाना चाहिए जब कक्षा परिभाषित हो।
इग्नासियो वाज़केज़-अब्राम्स

10
@ Space_C0wb0y: आप _representationक्लास बॉडी और मेटाक्लस return self._representationकी __repr__()विधि में एक स्ट्रिंग जोड़ सकते हैं ।
स्वेन मार्नाच

@ BjörnPollex आप डेकोरेटर के साथ इसे खींचने में सक्षम हो सकते हैं, लेकिन मुझे उम्मीद है कि आपको भाषा की बहुत सारी सूक्ष्मताओं के साथ संघर्ष करना होगा। और भले ही आप अभी भी एक तरह से या किसी अन्य तरीके से मेटाक्लास का उपयोग करने के लिए बाध्य हों क्योंकि आप डिफ़ॉल्ट __repr__का प्रतिनिधित्व नहीं करना चाहते हैं C। एक _representationसदस्य होने का एक विकल्प एक मेटाक्लास फैक्ट्री बनाना है जो उचित के साथ एक मेटाक्लास का उत्पादन करता है __repr__(यह अच्छा हो सकता है यदि आप इसे बहुत उपयोग कर रहे हैं)।
आसमान छू रहा है


22
class foo(object):
    def __str__(self):
        return "representation"
    def __unicode__(self):
        return u"representation"

10
यह instancesवर्ग के लिए स्ट्रिंग प्रतिनिधित्व को बदलता है, केवल कक्षा के लिए नहीं।
वृषभ

क्षमा करें, आपकी पोस्ट का दूसरा भाग नहीं दिखाई देगा। ऊपर विधि का प्रयोग करें।
एंड्री गुबारेव

6
@RobertSiemer क्यों? हालांकि उनका जवाब विशेष रूप से ओपी के सवाल को लक्षित नहीं कर रहा है, फिर भी यह मददगार है। इसने मेरी मदद की। और एक नज़र में, मैं उदाहरण कार्यान्वयन के लिए पूछ कोई सवाल नहीं दिख रहा है। इसलिए शायद लोग पहले इस पृष्ठ पर उतरते हैं।
एकिनुरी

14

यदि आपको पहले एक के बीच चयन करना है __repr__या __str__जाना है, जैसा कि डिफ़ॉल्ट कार्यान्वयन __str__कॉल द्वारा __repr__परिभाषित नहीं किया गया था।

कस्टम वेक्टर 3 उदाहरण:

class Vector3(object):
    def __init__(self, args):
        self.x = args[0]
        self.y = args[1]
        self.z = args[2]

    def __repr__(self):
        return "Vector3([{0},{1},{2}])".format(self.x, self.y, self.z)

    def __str__(self):
        return "x: {0}, y: {1}, z: {2}".format(self.x, self.y, self.z)

इस उदाहरण में, reprफिर से एक स्ट्रिंग देता है जिसे सीधे उपभोग / निष्पादित किया जा सकता है, जबकि strडिबग आउटपुट के रूप में अधिक उपयोगी है।

v = Vector3([1,2,3])
print repr(v)    #Vector3([1,2,3])
print str(v)     #x:1, y:2, z:3

1
जबकि __repr__बनाम के बारे में आपकी बात __str__सही है, यह वास्तविक प्रश्न का उत्तर नहीं देता है, जो वर्ग-वस्तुओं के बारे में है, उदाहरणों के बारे में नहीं।
ब्योर्न पोलेक्स

प्रतिक्रिया के लिए धन्यवाद, पूरी तरह से देखरेख। मुझे मेरे उत्तर की समीक्षा करने दीजिए।
user1767754

मुझे लगता है कि आप repr और str के लिए कार्यान्वयन की अदला-बदली कर रहे हैं।
jspencer

4

इग्नासियो वाज़क्वेज़-अब्राम्स का स्वीकृत उत्तर काफी सही है। हालांकि, यह पायथन 2 पीढ़ी से है। अब के मौजूदा पायथन 3 के लिए एक अपडेट होगा:

class MC(type):
  def __repr__(self):
    return 'Wahaha!'

class C(object, metaclass=MC):
    pass

print(C)

यदि आप ऐसा कोड चाहते हैं जो Python 2 और Python 3 दोनों पर चलता है, तो आपके द्वारा कवर किया गया छह मॉड्यूल:

from __future__ import print_function
from six import with_metaclass

class MC(type):
  def __repr__(self):
    return 'Wahaha!'

class C(with_metaclass(MC)):
    pass

print(C)

अंत में, यदि आपके पास एक वर्ग है जिसे आप एक कस्टम स्टेटिक रीप चाहते हैं, तो ऊपर स्थित क्लास-आधारित दृष्टिकोण शानदार काम करता है। लेकिन अगर आपके पास कई हैं, तो आपको MCप्रत्येक के लिए इसी तरह का एक मेटाक्लस जेनरेट करना होगा , और वह थकाऊ हो सकता है। उस स्थिति में, अपने मेटाप्रोग्रामिंग को एक कदम आगे ले जाना और मेटाक्लास फैक्टरी बनाने से चीजें थोड़ी साफ हो जाती हैं:

from __future__ import print_function
from six import with_metaclass

def custom_class_repr(name):
    """
    Factory that returns custom metaclass with a class ``__repr__`` that
    returns ``name``.
    """
    return type('whatever', (type,), {'__repr__': lambda self: name})

class C(with_metaclass(custom_class_repr('Wahaha!'))): pass

class D(with_metaclass(custom_class_repr('Booyah!'))): pass

class E(with_metaclass(custom_class_repr('Gotcha!'))): pass

print(C, D, E)

प्रिंट:

Wahaha! Booyah! Gotcha!

Metaprogramming ऐसी चीज़ नहीं है जिसकी आपको आम तौर पर हर रोज़ ज़रूरत पड़ती है- लेकिन जब आपको इसकी ज़रूरत होती है, तो यह वास्तव में मौके पर पहुँच जाती है!


0

बस सभी ठीक उत्तरों को जोड़ते हुए, सजावट के साथ मेरा संस्करण:

from __future__ import print_function
import six

def classrep(rep):
    def decorate(cls):
        class RepMetaclass(type):
            def __repr__(self):
                return rep

        class Decorated(six.with_metaclass(RepMetaclass, cls)):
            pass

        return Decorated
    return decorate


@classrep("Wahaha!")
class C(object):
    pass

print(C)

stdout:

Wahaha!

नीचे की ओर:

  1. आप Cसुपर क्लास के बिना घोषित नहीं कर सकते (नहीं class C:)
  2. Cउदाहरण कुछ अजीब व्युत्पत्ति के उदाहरण होंगे, इसलिए यह __repr__उदाहरणों के लिए भी जोड़ना एक अच्छा विचार है ।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.