50

एक Django ऐप को एकीकृत करते समय मैंने पहले उपयोग नहीं किया है, मुझे कक्षाओं में कार्यों को परिभाषित करने के लिए दो अलग-अलग तरीकों का उपयोग किया गया है। लेखक दोनों को जानबूझकर दोनों का उपयोग करना प्रतीत होता है। पहले एक के बाद एक मैं अपने आप को एक बहुत का उपयोग करें:मुझे @classmethod का उपयोग कब करना चाहिए और जब डीफ विधि (स्वयं)?

class Dummy(object): 

    def some_function(self,*args,**kwargs): 
     do something here 
     self is the class instance 

अन्य एक, एक मैं का उपयोग नहीं करते है ज्यादातर क्योंकि मैं क्या समझ में नहीं आता है, जब यह उपयोग करने के लिए, और:

class Dummy(object): 

    @classmethod 
    def some_function(cls,*args,**kwargs): 
     do something here 
     cls refers to what? 

अजगर डॉक्स में classmethod डेकोरेटर इस वाक्य के साथ समझाया गया है:

एक वर्ग विधि, अंतर्निहित पहले तर्क के रूप में वर्ग को मिलने वाले एक उदाहरण विधि सिर्फ की तरह उदाहरण प्राप्त करता है।

तो मैं clsDummy करने के लिए स्वयं (class, नहीं उदाहरण) संदर्भित करता है लगता है। मैं ठीक से समझ नहीं ऐसा क्यों मौजूद है, क्योंकि मैं हमेशा ऐसा कर सकता है:

type(self).do_something_with_the_class 

सिर्फ स्पष्टता के लिए इस है, या मैं सबसे महत्वपूर्ण हिस्सा याद किया: डरावना और आकर्षक चीजें हैं जो नहीं किया जा सका इसके बिना किया?

उत्तर

47

आपका अनुमान सही है - आप कैसेclassmethod के काम को समझते हैं।

क्यों कि है इन तरीकों दोनों एक उदाहरण पर या वर्ग (दोनों ही मामलों में, वर्ग वस्तु पहले तर्क के रूप में पारित हो जाएगा) पर कहा जा सकता है:

class Dummy(object): 

    @classmethod 
    def some_function(cls,*args,**kwargs): 
     print cls 

#both of these will have exactly the same effect 
Dummy.some_function() 
Dummy().some_function() 

के उपयोग पर उदाहरणों पर इन:

  1. self.some_function()self के वास्तविक प्रकार पर some_function के संस्करण फोन करेगा, बजाय clas: एक उदाहरण पर एक classmethod फोन करने के लिए कम से कम दो मुख्य उपयोग कर रहे हैं जिसमें वह कॉल प्रकट होता है (और कक्षा का नाम बदलकर ध्यान देने की आवश्यकता नहीं होगी); और
  2. ऐसे मामलों में जहां some_function कुछ प्रोटोकॉल को लागू करने के लिए आवश्यक है, लेकिन केवल क्लास ऑब्जेक्ट पर कॉल करने के लिए उपयोगी है।

staticmethod के साथ अंतर: तरीकों कि उदाहरण के डेटा का उपयोग नहीं है परिभाषित करने का एक और तरीका है, staticmethod कहा जाता है। यह एक ऐसी विधि बनाता है जो बिल्कुल अंतर्निहित पहला तर्क प्राप्त नहीं करता है; तदनुसार यह उस उदाहरण या कक्षा के बारे में कोई जानकारी पारित नहीं की जाएगी जिस पर इसे कहा जाता था।

In [6]: class Foo(object): some_static = staticmethod(lambda x: x+1) 

In [7]: Foo.some_static(1) 
Out[7]: 2 

In [8]: Foo().some_static(1) 
Out[8]: 2 

In [9]: class Bar(Foo): some_static = staticmethod(lambda x: x*2) 

In [10]: Bar.some_static(1) 
Out[10]: 2 

In [11]: Bar().some_static(1) 
Out[11]: 2 

मुख्य उपयोग मैं इसके लिए मिल गया है एक वर्ग (या वस्तु) पर एक विधि के लिए (जो एक self प्राप्त करने की अपेक्षा नहीं करता है) एक मौजूदा समारोह अनुकूल करने के लिए है।

+1

अच्छा एक: मुझे जवाब पसंद है कि क्यों - क्यों। जहां तक ​​मुझे अब मिल गया है @classmethod किसी उदाहरण की आवश्यकता के बिना फ़ंक्शन तक पहुंचने की अनुमति देता है। यह वही है जो मैं खोज रहा था, धन्यवाद। – marue

+0

@marue आपका स्वागत है! – Marcin

+0

मैं कहूंगा कि उदाहरणों पर कॉलिंग क्लास विधियां खराब कोडिंग शैली है - ऐसा करने का कोई कारण नहीं है और केवल भ्रम पैदा कर सकता है। लेकिन हाँ यह काम करता है (जावा एक ही चीज़ की अनुमति देता है, लेकिन उदाहरणों के माध्यम से स्थैतिक तरीकों को कॉल करते समय एक संकलन चेतावनी जारी करता है) – Voo

0

यदि आप सजावटी @classmethod जोड़ते हैं, तो इसका मतलब है कि आप जावा या सी ++ की स्थिर विधि के रूप में उस विधि को बनाने जा रहे हैं।(स्थैतिक विधि सामान्य शब्द मुझे लगता है ;)) पायथन में @staticmethod भी है। और classmethod और staticmethod के बीच अंतर यह है कि क्या आप तर्क या कक्षा नाम का उपयोग कर कक्षा या स्थैतिक चर तक पहुंच सकते हैं।

class TestMethod(object): 
    cls_var = 1 
    @classmethod 
    def class_method(cls): 
     cls.cls_var += 1 
     print cls.cls_var 

    @staticmethod 
    def static_method(): 
     TestMethod.cls_var += 1 
     print TestMethod.cls_var 
#call each method from class itself. 
TestMethod.class_method() 
TestMethod.static_method() 

#construct instances 
testMethodInst1 = TestMethod()  
testMethodInst2 = TestMethod() 

#call each method from instances 
testMethodInst1.class_method() 
testMethodInst2.static_method() 

उन सभी वर्गों में cls.cls_var 1 तक बढ़ जाती है और इसे प्रिंट करती है।

और इन वर्गों के साथ बनाए गए समान दायरे या उदाहरणों पर समान नाम का उपयोग करने वाले प्रत्येक वर्ग उन तरीकों को साझा करने जा रहे हैं। केवल एक TestMethod.cls_var नहीं है और यह भी केवल एक ही TestMethod.class_method(), TestMethod.static_method()

और महत्वपूर्ण सवाल है। इन तरीकों की आवश्यकता क्यों होगी।

क्लासमेड या staticmethod उपयोगी है जब आप उस श्रेणी को फैक्टरी के रूप में करते हैं या जब आपको केवल एक बार अपनी कक्षा शुरू करना होता है। एक बार खुली फ़ाइल की तरह, और फ़ाइल लाइन को लाइन लाइन पढ़ने के लिए फ़ीड विधि का उपयोग करना।

+1

(ए) स्टेटिक विधियां कुछ और हैं; (बी) कक्षाओं को हर वर्ग द्वारा साझा नहीं किया जाता है। – Marcin

+0

@ मार्सिन मुझे मेरी अस्पष्ट परिभाषाओं और सभी को जानने के लिए धन्यवाद। –

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