2013-08-06 5 views
7
कभी कभी

मैं कक्षा, हालांकि संभावना के साथ यह प्रारंभ और राज्य (वस्तु)अजगर: नियमित रूप से विधि के बीच संकर और classmethod

sth की तरह रखने के लिए स्थिर तरीकों के साथ लिखने के लिए की जरूरत है:

class A: 
    @classmethod 
    def method(cls_or_self): 
    # get reference to object when A().method() or to class when A.method() 
    code 

क्या अब मेरे पास है:

class A: 
    def method(self = None, *params): code 
    # or 
    def method2(self = None, **params): code 
    # but what I need is rather normal parameters, not optional and named args: 
    def method3(self_or_cls, a, b=1, c=2, *p, **kw): code 

कृपया staticmethod और classmethod के बीच मतभेदों के बारे में न लिखें। मुझे दिलचस्पी है यदि इस तरह के सजावटी मौजूद हैं (अधिक या कम मानक libs में) और इसके अलावा यदि ऊपर पीईपी के लिए उपयुक्त है।

+2

आप एक classmethod और एक * नियमित रूप से * विधि के बीच एक संकर मतलब है। –

उत्तर

17

कार्य और classmethod ऑब्जेक्ट descriptors के रूप में कार्य करते हैं; दोनों एक रैपर लौटाते हैं जिसे बदले में अंतर्निहित फ़ंक्शन को अतिरिक्त पैरामीटर के साथ कॉल किया जाएगा। कार्यों और classmethod ऑब्जेक्ट्स व्यवहार के बीच एकमात्र अंतर यह है कि उस अतिरिक्त पैरामीटर है।

दो दृष्टिकोण का एक संकर बनाने के लिए, अपने खुद के वर्णनकर्ता डेकोरेटर का निर्माण:

from functools import wraps 

class hybridmethod(object): 
    def __init__(self, func): 
     self.func = func 

    def __get__(self, obj, cls): 
     context = obj if obj is not None else cls 

     @wraps(self.func) 
     def hybrid(*args, **kw): 
      return self.func(context, *args, **kw) 

     # optional, mimic methods some more 
     hybrid.__func__ = hybrid.im_func = self.func 
     hybrid.__self__ = hybrid.im_self = context 

     return hybrid 

यहाँ, हम एक आवरण है कि पहले पैरामीटर के रूप में या तो वर्ग या उदाहरण के इस्तेमाल करेंगे वापसी, पर निर्भर करता है क्या उपलब्ध है जब वर्णनकर्ता __get__ विधि कहा जाता है।

डेमो:

>>> class Foo(object): 
...  @hybridmethod 
...  def bar(cls_or_self): 
...   print 'Called with cls_or_self={!r}'.format(cls_or_self) 
... 
>>> Foo.bar() 
Called with cls_or_self=<class '__main__.Foo'> 
>>> Foo().bar() 
Called with cls_or_self=<__main__.Foo object at 0x1043a4390> 
+0

... इस तरह के तेज़ और आश्चर्यजनक कि मुझे जवाब स्वीकार करने के लिए इंतजार करना होगा (stackoverflow reqs), लेकिन classmethod के बारे में क्या? - मेरे ऊपर सजावटी के लिए अधिक कार्यात्मक दिखता है, यहां तक ​​कि क्लैज्म विधि को ओवरराइट करने या विधियों के लिए तीसरे मानक सजावट को जोड़ने का सुझाव देने के लिए भी। मुझे पता है कि इसे मजबूत आलोचना की आवश्यकता है। –

+0

'क्लासमेड' सजावट एक अलग लक्ष्य परोसता है; वे विधियां जो उनके व्यवहार के बारे में संदिग्ध हैं (संदर्भ के आधार पर एक या दूसरे कार्य करें) बहुत पाइथनिक नहीं हैं। –

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