2012-01-19 9 views
5

कक्षा परिभाषित करने के बाद आप क्लास विधि स्थैतिक कैसे बना सकते हैं? दूसरे शब्दों में, तीसरा मामला क्यों विफल रहता है?कक्षा के बाहर किसी मौजूदा विधि से staticmethod बनाएँ? ("अनबाउंड विधि" त्रुटि)

 

>>> class b: 
... @staticmethod 
... def foo(): 
... pass 
... 
>>> b.foo() 
>>> class c: 
... def foo(): 
... pass 
... foo = staticmethod(foo) 
... 
>>> c.foo() 
>>> class d: 
... def foo(): 
... pass 
... 
>>> d.foo = staticmethod(d.foo) 
>>> d.foo() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: unbound method foo() must be called with d instance as first argument (got nothing instead) 

उत्तर

6

के बाद वर्ग परिभाषित किया गया है, foo एक अबाध विधि वस्तु (एक आवरण वर्ग के लिए समारोह बाँधती है कि), नहीं एक समारोह है। रैपर वर्ग के उदाहरण (self) को पहले तर्क के रूप में कार्य करने के लिए प्रयास करने जा रहा है और इसलिए यह शिकायत करता है कि आपने इसे एक नहीं दिया है।

staticmethod() वास्तव में केवल कार्यों के साथ उपयोग किया जाना चाहिए। जबकि कक्षा अभी भी परिभाषित की जा रही है (जैसा कि आपके b और c में) foo() अभी भी एक फ़ंक्शन है, क्योंकि क्लास परिभाषा पूर्ण होने पर विधि रैपर लागू होती है।

अनबाउंड विधि ऑब्जेक्ट से फ़ंक्शन निकालना संभव है, staticmethod() लागू करें, और उसे कक्षा में वापस असाइन करें।

class d(object): 
    def foo(): 
     pass 

d.foo = staticmethod(d.foo.im_func) 

पायथन 3 में, कोई अनबाउंड उदाहरण विधियां नहीं हैं (कक्षाओं पर संग्रहीत विधियां सादा कार्य हैं)। तो अपने मूल कोड वास्तव में पायथन 3.

पर ठीक काम करेगा एक तरह से है कि दोनों अजगर 2 और अजगर 3 पर काम करता है:

d.foo = staticmethod(d.__dict__['foo']) 

(यह भी बनाने और विधि आवरण को त्यागकर बचा जाता है।)

+0

क्या यह 'd.foo.im_func' नहीं होना चाहिए? –

+0

हां, धन्यवाद। फिक्स्ड! – kindall

+0

ठीक है, आपको उन्हें केवल 'वर्ग' के साथ चिह्नित करने के लिए उन्हें 'staticmethod'' के साथ चिह्नित करने की आवश्यकता है। 'd.foo()' 'staticmethod' wrapping के साथ या उसके बिना काम करता है, लेकिन' d()। foo() 'विस्फोट करेगा (यह 'स्वयं' को पार करने का प्रयास करेगा जो 'foo' स्वीकार नहीं करता है)। निश्चित रूप से, कोई उदाहरण-संबंधित सुविधा नहीं है जिसे उन्हें किसी उदाहरण पर कॉल करने की आवश्यकता होगी, लेकिन DRY के लिए, स्थिर विधि का संदर्भ देने वाली विधियां इसे कक्षा के नामकरण के बजाय 'self.foo()' के रूप में कॉल कर सकती हैं। – ShadowRanger

5

आपको फ़ंक्शन को पास करना होगा, न कि अनबाउंड विधि।

>>> class d: 
... def foo(): 
...  pass 
... 
>>> d.foo = staticmethod(d.foo.im_func) 
>>> d.foo() 
संबंधित मुद्दे