2012-06-04 19 views
14

मैंने कक्षा परिभाषाओं में __repr__ विधि सेट करने के लिए केवल उदाहरण देखे हैं। क्या __repr__ को उनके परिभाषाओं में या उन्हें परिभाषित करने के बाद कार्यों के लिए बदलना संभव है?पायथन में फ़ंक्शन के रिप्रर को बदलना संभव है?

मैं सफलता के बिना प्रयास किया है ...

>>> def f(): 
    pass 
>>> f 
<function f at 0x1026730c8> 
>>> f.__repr__ = lambda: '<New repr>' 
>>> f 
<function __main__.f> 

उत्तर

14

हां, यदि आप वास्तव में फ़ंक्शन से गुजरने के इच्छुक हैं।

सबसे पहले, हमारे नए प्रकार के लिए एक वर्ग को परिभाषित:

import functools 
class reprwrapper(object): 
    def __init__(self, repr, func): 
     self._repr = repr 
     self._func = func 
     functools.update_wrapper(self, func) 
    def __call__(self, *args, **kw): 
     return self._func(*args, **kw) 
    def __repr__(self): 
     return self._repr(self._func) 

एक डेकोरेटर समारोह में जोड़ें:

def withrepr(reprfun): 
    def _wrap(func): 
     return reprwrapper(reprfun, func) 
    return _wrap 

और अब हम समारोह के साथ रेपर परिभाषित कर सकते हैं:

@withrepr(lambda x: "<Func: %s>" % x.__name__) 
def mul42(y): 
    return y*42 

अब repr(mul42)'<Func: mul42>'

012 उत्पन्न करता है
+3

सज्जाकार नाम और सजाया कार्यों का docstring अद्यतन करने के लिए के लिए functools.wraps' का उपयोग करें '। – schlamar

+1

समस्या यह है कि 'प्रिंट mul42 .__ name__' एक एट्रिब्यूट एरर उठाएगा जो किसी फ़ंक्शन के लिए अपेक्षित नहीं है। तो यह होगा: 'ठीक करने के लिए वापसी wraps (func) (reprwrapper (reprfun, func))' इसे ठीक करने के लिए। – schlamar

+1

@ ms4py इस मामले में मुझे लगता है कि 'update_wrapper' थोड़ा अधिक उचित/प्रत्यक्ष है। मैंने रैपर वर्ग को संशोधित किया है ताकि यह अपने कन्स्ट्रक्टर में ऐसा कर सके। इस तरह अद्यतन तब भी होता है जब आप 'withrepr' सजावट का उपयोग करने के बजाय सीधे कक्षा का उपयोग करते हैं। – kwatford

5

नहीं, क्योंकि repr(f) बजाय type(f).__repr__(f) के रूप में किया जाता है।

3

ऐसा करने के लिए, आपको दिए गए वर्ग के लिए __repr__ फ़ंक्शन को बदलने की आवश्यकता होगी, जो इस मामले में अंतर्निहित फ़ंक्शन क्लास (types.FunctionType) है। चूंकि पाइथन में आप अंतर्निर्मित कक्षाओं को संपादित नहीं कर सकते हैं, केवल उन्हें उपclass, आप नहीं कर सकते हैं।

हालांकि, वहाँ दो दृष्टिकोण आप का पालन कर सकते हैं: सुझाव

  1. लपेटें कुछ kwatford के रूप में कार्य
  2. अपनी खुद की रेपर समारोह के साथ अपने स्वयं प्रतिनिधित्व प्रोटोकॉल बनाएँ। उदाहरण के लिए, आप myrepr फ़ंक्शन को परिभाषित कर सकते हैं जो पहले __myrepr__ विधियों को देखता है, जिसे आप फ़ंक्शन क्लास में नहीं जोड़ सकते हैं, लेकिन आप इसे अलग-अलग फ़ंक्शन ऑब्जेक्ट्स में जोड़ सकते हैं जैसा कि आप सुझाव देते हैं (साथ ही साथ आपके कस्टम क्लासेस और ऑब्जेक्ट्स), फिर डिफ़ॉल्ट repr अगर __myrepr__ नहीं मिला है। इस के लिए एक संभावित कार्यान्वयन होगा:

    def myrepr(x): 
        try: 
        x.__myrepr__ 
        except AttributeError: 
        return repr(x) 
        else: 
        return x.__myrepr__() 
    

    तो फिर तुम __myrepr__ तरीकों को परिभाषित करने और myrepr समारोह इस्तेमाल कर सकते हैं। वैकल्पिक रूप से, आप अपने कार्य को डिफ़ॉल्ट repr बनाने के लिए __builtins__.repr = myrepr भी कर सकते हैं और repr का उपयोग जारी रख सकते हैं। यह दृष्टिकोण ठीक वही कर रहा है जो आप चाहते हैं, हालांकि __builtins__ संपादित करना हमेशा वांछनीय नहीं हो सकता है।

संबंधित मुद्दे