स्टेटमिथोड और क्लासमेथोड के बीच अंतर


3579

एक समारोह के साथ सजाया @staticmethodऔर एक के साथ सजाया के बीच क्या अंतर है @classmethod?


11
स्थैतिक तरीके कभी-कभी बेहतर होते हैं क्योंकि स्वच्छता के लिए अजगर में मॉड्यूल स्तर के कार्य होते हैं। मॉड्यूल फ़ंक्शन के साथ यह केवल आपके द्वारा आवश्यक फ़ंक्शन को आयात करने और अनावश्यक को रोकने के लिए आसान है "।" वाक्यविन्यास (मैं आपको उद्देश्य-सी देख रहा हूं)। क्लास के तरीकों का अधिक उपयोग होता है क्योंकि उनका उपयोग "फैक्टरी पैटर्न" फ़ंक्शन बनाने के लिए बहुरूपता के साथ संयोजन में किया जा सकता है। इसका कारण यह है कि वर्ग विधियाँ कक्षा को एक निहित पैरामीटर के रूप में प्राप्त करती हैं।
FistOfFury

27
tl; dr >> सामान्य तरीकों की तुलना में, स्थैतिक विधियों और वर्ग विधियों को भी वर्ग का उपयोग करके एक्सेस किया जा सकता है लेकिन वर्ग विधियों के विपरीत, स्थैतिक विधियाँ वंशानुक्रम के माध्यम से अपरिवर्तनीय हैं।
15 सितंबर को imsrgadich

4
संबंधित विषय पर रेमंड
हेटिंगर

अधिक सटीक youtube.com/watch?v=HTLu2DFOdTg&feature=youtu.be&t=2689 आपको वैकल्पिक निर्माणकर्ताओं के लिए केवल क्लासमेट की आवश्यकता है। नहीं तो आप (के माध्यम से / डॉट।) Staticmethod और उपयोग किसी भी वर्ग विशेषता का उपयोग कर सकते किसी भी तरह अधिक सूचनात्मक वास्तविक "classname" द्वारा cls के बजाय classmethod में तरह
रॉबर्ट नोवाक

जवाबों:


3136

शायद उदाहरण के एक बिट कोड में मदद मिलेगी: कॉल हस्ताक्षर में अंतर नोटिस foo, class_fooऔर static_foo:

class A(object):
    def foo(self, x):
        print "executing foo(%s, %s)" % (self, x)

    @classmethod
    def class_foo(cls, x):
        print "executing class_foo(%s, %s)" % (cls, x)

    @staticmethod
    def static_foo(x):
        print "executing static_foo(%s)" % x    

a = A()

नीचे एक सामान्य तरीके से एक वस्तु उदाहरण एक विधि को कॉल करता है। वस्तु उदाहरण, aको पहले तर्क के रूप में स्पष्ट रूप से पारित किया जाता है।

a.foo(1)
# executing foo(<__main__.A object at 0xb7dbef0c>,1)

क्लासमेथोड्स के साथ , वस्तु उदाहरण के वर्ग को इसके बजाय पहले तर्क के रूप में पारित किया जाता है self

a.class_foo(1)
# executing class_foo(<class '__main__.A'>,1)

आप class_fooकक्षा का उपयोग करके भी कॉल कर सकते हैं । वास्तव में, यदि आप किसी क्लासमेथोड होने के लिए कुछ परिभाषित करते हैं, तो यह संभवतः इसलिए है क्योंकि आप इसे क्लास उदाहरण से नहीं बल्कि कक्षा से बुलाना चाहते हैं। A.foo(1)एक TypeError उठाया होगा, लेकिन A.class_foo(1)ठीक काम करता है:

A.class_foo(1)
# executing class_foo(<class '__main__.A'>,1)

क्लास के तरीकों के लिए लोगों ने जो एक उपयोग पाया है वह अंतर्निहित वैकल्पिक निर्माणकर्ता बनाना है ।


स्टेटमिथोड्स के साथ , न तो self(ऑब्जेक्ट उदाहरण) और न ही cls(वर्ग) को पहले तर्क के रूप में पारित किया जाता है। वे सादे कार्यों की तरह व्यवहार करते हैं सिवाय इसके कि आप उन्हें एक उदाहरण या वर्ग से बुला सकते हैं:

a.static_foo(1)
# executing static_foo(1)

A.static_foo('hi')
# executing static_foo(hi)

स्टैटिकमेथोड्स का उपयोग समूह कार्यों के लिए किया जाता है जिनका कक्षा के साथ कक्षा के साथ कुछ तार्किक संबंध होता है।


fooकेवल एक फ़ंक्शन है, लेकिन जब आप कॉल a.fooकरते हैं तो आपको केवल फ़ंक्शन नहीं मिलता है, आपको फ़ंक्शन aका पहला आंशिक रूप से "संस्करण" प्राप्त होता है, जो फ़ंक्शन के पहले तर्क के रूप में बाध्य ऑब्जेक्ट उदाहरण के साथ होता है। foo2 तर्क की अपेक्षा करता है, जबकि a.fooकेवल 1 तर्क की अपेक्षा करता है।

aके लिए बाध्य है foo। नीचे दिए गए शब्द "बाउंड" का मतलब है:

print(a.foo)
# <bound method A.foo of <__main__.A object at 0xb7d52f0c>>

के साथ a.class_foo, के aलिए बाध्य नहीं है class_foo, बल्कि वर्ग के Aलिए बाध्य है class_foo

print(a.class_foo)
# <bound method type.class_foo of <class '__main__.A'>>

यहाँ, एक स्टैटिकमेथोड के साथ, भले ही यह एक विधि है, a.static_fooबस एक अच्छा 'ओले फ़ंक्शन देता है जिसमें कोई तर्क नहीं है। static_foo1 तर्क की अपेक्षा करता है, और a.static_foo1 तर्क की भी अपेक्षा करता है।

print(a.static_foo)
# <function static_foo at 0xb7d479cc>

और निश्चित रूप से एक ही बात तब होती है जब आप static_fooक्लास के Aबजाय बुलाते हैं ।

print(A.static_foo)
# <function static_foo at 0xb7d479cc>

182
मुझे समझ में नहीं आ रहा है कि स्टेटमिथोड का उपयोग करने के लिए क्या पकड़ है। हम केवल एक साधारण बाहरी श्रेणी के कार्य का उपयोग कर सकते हैं।
Alcott

372
@ अलॉट: आप एक फ़ंक्शन को एक कक्षा में ले जाना चाहते हैं क्योंकि यह तार्किक रूप से कक्षा के साथ संबंधित है। पायथन सोर्स कोड (जैसे मल्टीप्रोसेसिंग, टर्टल, डिस्ट-पैकेज) में, इसका इस्तेमाल मॉड्यूल नेमस्पेस से "सिंगल-अंडरस्कोर" प्राइवेट "फंक्शन को छिपाने के लिए किया जाता है। इसका उपयोग, हालांकि, केवल कुछ मॉड्यूल में अत्यधिक केंद्रित है - शायद एक संकेत है कि यह मुख्य रूप से एक शैलीगत चीज है। हालांकि मुझे इसका कोई उदाहरण नहीं मिला, लेकिन @staticmethodउपवर्गों द्वारा अतिदेय होने से आपके कोड को व्यवस्थित करने में मदद मिल सकती है। इसके बिना आपके पास मॉड्यूल नेमस्पेस में चल समारोह के वेरिएंट होंगे।
अनटुब

14
... कहाँ और क्यों , उदाहरण, वर्ग या स्थिर तरीकों का उपयोग करने पर कुछ स्पष्टीकरण के साथ । आपने इसके बारे में एक भी शब्द नहीं दिया, लेकिन न तो ओपी ने इसके बारे में पूछा।
MestreLion

106
@ अलकोट: जैसा कि अनटु ने कहा, स्थैतिक विधियाँ एक संगठन / शैलीगत विशेषता हैं। कभी-कभी एक मॉड्यूल में कई वर्ग होते हैं, और कुछ सहायक कार्य तार्किक रूप से एक दिए गए वर्ग से बंधे होते हैं और दूसरों से नहीं होते हैं, इसलिए यह समझ में आता है कि मॉड्यूल कई "मुक्त कार्यों" के साथ "प्रदूषण" नहीं करता है, और यह एक स्थैतिक का उपयोग करना बेहतर है मिक्सिंग क्लासेस और फंक्शन के घटिया अंदाज पर भरोसा करने का तरीका कोड में एक साथ सिर्फ "संबंधित" दिखाने के लिए है
MestreLion

4
के लिए एक और उपयोग @staticmethod- आप इसे हटाने के लिए उपयोग कर सकते हैं। मैं पायथन में एक प्रोग्रामिंग भाषा लागू कर रहा हूं - पुस्तकालय-परिभाषित फ़ंक्शन एक स्थिर executeपद्धति का उपयोग करते हैं , जहां उपयोगकर्ता-परिभाषित फ़ंक्शन को उदाहरण तर्क (अर्थात फ़ंक्शन बॉडी) की आवश्यकता होती है। यह डेकोरेटर PyCharm इंस्पेक्टर में "अप्रयुक्त पैरामीटर स्वयं" चेतावनी को समाप्त करता है।
तेहलवस

798

एक स्टैटिकमेथोड एक ऐसी विधि है जो उस वर्ग या उदाहरण के बारे में कुछ नहीं जानती है जिस पर उसे बुलाया गया था। यह सिर्फ उन तर्कों को प्राप्त करता है जो पारित किए गए थे, कोई निहित पहला तर्क नहीं है। यह मूल रूप से पायथन में बेकार है - आप केवल स्टैमीमेथोड के बजाय एक मॉड्यूल फ़ंक्शन का उपयोग कर सकते हैं।

दूसरी ओर एक क्लासमेथोड , एक विधि है जो उस कक्षा में उत्तीर्ण होती है जिसे उस पर बुलाया गया था, या जिस वर्ग को यह कहा गया था, वह पहला तर्क था। यह तब उपयोगी होता है जब आप चाहते हैं कि विधि वर्ग के लिए एक कारखाना हो: चूंकि इसे वास्तविक वर्ग मिलता है, इसलिए इसे प्रथम तर्क के रूप में कहा जाता था, आप हमेशा सही वर्ग को तत्काल कर सकते हैं, भले ही उपवर्ग शामिल हों। उदाहरण के लिए देखें कि dict.fromkeys()एक वर्गमिथोड कैसे उप-वर्ग का उदाहरण देता है, जब उप-वर्ग पर बुलाया जाता है:

>>> class DictSubclass(dict):
...     def __repr__(self):
...         return "DictSubclass"
... 
>>> dict.fromkeys("abc")
{'a': None, 'c': None, 'b': None}
>>> DictSubclass.fromkeys("abc")
DictSubclass
>>> 

712
एक स्टेथमैथोड बेकार नहीं है - यह एक वर्ग में एक फ़ंक्शन डालने का एक तरीका है (क्योंकि यह तार्किक रूप से वहां है), जबकि यह इंगित करता है कि इसे कक्षा तक पहुंच की आवश्यकता नहीं है।
टोनी मेयर

135
इसलिए केवल 'मूल रूप से' बेकार है। इस तरह के संगठन, साथ ही निर्भरता इंजेक्शन, स्टेथेमिथोड्स के मान्य उपयोग हैं, लेकिन चूंकि मॉड्यूल, जावा में कक्षाएं नहीं जैसे पायथन में कोड संगठन के मूल तत्व हैं, इसलिए उनका उपयोग और उपयोगिता दुर्लभ है।
थॉमस वाउचर

40
एक वर्ग के अंदर एक विधि को परिभाषित करने के बारे में क्या तर्कसंगत है, जब इसका वर्ग या उसके उदाहरणों से कोई लेना-देना नहीं है?
बेन जेम्स

106
शायद विरासत के लिए? स्थैतिक विधियों को विरासत के तरीकों और वर्ग के तरीकों की तरह ही विरासत में मिला और अधिभूत किया जा सकता है और लुकअप अपेक्षा के अनुरूप काम करता है (जावा के विपरीत)। स्टैटिक विधियों को वास्तव में वैधानिक रूप से हल नहीं किया जाता है चाहे वह वर्ग या उदाहरण पर कहा जाता है, इसलिए वर्ग और स्थिर तरीकों के बीच एकमात्र अंतर निहित पहला तर्क है।
haridsv

80
वे एक क्लीनर नेमस्पेस भी बनाते हैं, और यह समझना आसान बनाते हैं कि फ़ंक्शन का कक्षा के साथ कुछ करना है।
इम्ब्रोनडिर

149

मूल रूप @classmethodसे एक विधि है जिसका पहला तर्क वह वर्ग है जिसे (वर्ग उदाहरण के बजाय) कहा जाता है, @staticmethodमें कोई निहित तर्क नहीं है।


103

आधिकारिक अजगर डॉक्स:

@classmethod

एक क्लास मेथड को इंप्लिमेंट फस्र्ट लॉजिक के रूप में प्राप्त होता है, ठीक उसी तरह जैसे इंस्टेंस मेथड को इंस्टेंस प्राप्त होता है। एक वर्ग विधि घोषित करने के लिए, इस मुहावरे का उपयोग करें:

class C:
    @classmethod
    def f(cls, arg1, arg2, ...): ... 

@classmethodप्रपत्र एक समारोह है डेकोरेटर - में समारोह परिभाषाओं का विवरण देखने के समारोह परिभाषाएँ जानकारी के लिए।

इसे या तो कक्षा (जैसे C.f()) या उदाहरण पर (जैसे C().f()) कहा जा सकता है । इसके वर्ग को छोड़कर उदाहरण को नजरअंदाज किया जाता है। यदि किसी वर्ग पद्धति को एक व्युत्पन्न वर्ग के लिए कहा जाता है, तो व्युत्पन्न वर्ग वस्तु को पहले तर्क के रूप में पारित किया जाता है।

वर्ग विधियाँ C ++ या Java स्थैतिक विधियों से भिन्न हैं। यदि आप चाहते हैं, तो staticmethod()इस अनुभाग में देखें ।

@staticmethod

एक स्थैतिक विधि एक अंतर्निहित पहला तर्क प्राप्त नहीं करता है। एक स्थिर विधि घोषित करने के लिए, इस मुहावरे का उपयोग करें:

class C:
    @staticmethod
    def f(arg1, arg2, ...): ... 

@staticmethodप्रपत्र एक समारोह है डेकोरेटर - में समारोह परिभाषाओं का विवरण देखने के समारोह परिभाषाएँ जानकारी के लिए।

इसे या तो कक्षा (जैसे C.f()) या उदाहरण पर (जैसे C().f()) कहा जा सकता है । इसके वर्ग को छोड़कर उदाहरण को नजरअंदाज किया जाता है।

पायथन में स्थैतिक विधियाँ जावा या C ++ में पाए जाने वाले समान हैं। अधिक उन्नत अवधारणा के लिए, classmethod()इस अनुभाग में देखें ।


क्या डॉक्स में कोई त्रुटि नहीं है? स्टेटिकमेथोड में नहीं होना चाहिए: "उदाहरण और इसकी कक्षा दोनों को अनदेखा किया जाता है।" इसके बजाय "उदाहरण को इसके वर्ग को छोड़कर अनदेखा किया गया है।"
मर्क

यह एक कट-एंड-पेस्ट त्रुटि हो सकती है, लेकिन यदि आप कक्षा को अनदेखा करते हैं, तो कड़ाई से बोलकर आप क्लास पर एक विधि नहीं कह सकते हैं।
आरोन बेंटले

76

इस प्रश्न पर एक संक्षिप्त लेख यहाँ दिया गया है

@staticmethod फ़ंक्शन किसी वर्ग के अंदर परिभाषित फ़ंक्शन से अधिक कुछ नहीं है। यह पहली कक्षा को तत्काल किए बिना कॉल करने योग्य है। यह परिभाषा विरासत के माध्यम से अपरिवर्तनीय है।

@classmethod फ़ंक्शन भी क्लास को इंस्टेंट किए बिना कॉल करने योग्य है, लेकिन इसकी परिभाषा इनहेरिटेंस के माध्यम से सब क्लास, पेरेंट क्लास का अनुसरण करती है। ऐसा इसलिए है क्योंकि @classmethod फ़ंक्शन के लिए पहला तर्क हमेशा cls (क्लास) होना चाहिए।


1
तो क्या इसका मतलब यह है कि एक स्टेथमैथोड का उपयोग करके मैं हमेशा पेरेंट क्लास से जुड़ा रहता हूं और क्लासमेथोड के साथ मैं उस क्लास को बाध्य करता हूं जिसे मैं क्लासमैथोड घोषित करता हूं (इस मामले में सब क्लास)?
मोहन गुलाटी

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

6
यह दिखाने के लिए थोड़ा विस्तार किया जा सकता है कि, पहले तर्क के रूप में एक वर्ग होने से, क्लास के तरीकों का अन्य क्लास एट्रिब्यूट्स और विधियों तक सीधी पहुँच होती है, जबकि स्टैटिक मेथड्स नहीं हैं (उन्हें इसके लिए
MyClass.attr

"यह परिभाषा विरासत के माध्यम से अपरिवर्तनीय है।" पायथन में कोई मतलब नहीं है, आप एक स्थिर विधि को ठीक से ओवरराइड कर सकते हैं।
cz

68

यह तय करने के लिए कि @staticmethod या @classmethod का उपयोग करना है या नहीं, आपको अपनी विधि के अंदर देखना होगा। यदि आपकी विधि आपकी कक्षा में अन्य चर / विधियों तक पहुँचती है, तो @classmethod का उपयोग करें । दूसरी ओर, यदि आपकी विधि कक्षा के किसी अन्य भाग को नहीं छूती है, तो @staticmethod का उपयोग करें।

class Apple:

    _counter = 0

    @staticmethod
    def about_apple():
        print('Apple is good for you.')

        # note you can still access other member of the class
        # but you have to use the class instance 
        # which is not very nice, because you have repeat yourself
        # 
        # For example:
        # @staticmethod
        #    print('Number of apples have been juiced: %s' % Apple._counter)
        #
        # @classmethod
        #    print('Number of apples have been juiced: %s' % cls._counter)
        #
        #    @classmethod is especially useful when you move your function to other class,
        #       you don't have to rename the class reference 

    @classmethod
    def make_apple_juice(cls, number_of_apples):
        print('Make juice:')
        for i in range(number_of_apples):
            cls._juice_this(i)

    @classmethod
    def _juice_this(cls, apple):
        print('Juicing %d...' % apple)
        cls._counter += 1

क्लासमैथोड और cls._counter बनाम staticmethod और Apple._counter का क्या फ़ायदा होगा
राबर्ट नोवाक

1
cls._counterअभी भी होगा cls._counter, भले ही कोड एक अलग वर्ग में रखा जाता है, या वर्ग के नाम बदल दिया गया है। वर्ग के Apple._counterलिए विशिष्ट है Apple; एक अलग वर्ग के लिए, या जब कक्षा का नाम बदला जाता है, तो आपको संदर्भित वर्ग को बदलना होगा।
kiamlaluno

52

पायथन में @staticmethod और @classmethod में क्या अंतर है?

आपने पायस कोड को इस छद्म कोड की तरह देखा होगा, जो विभिन्न प्रकारों के हस्ताक्षरों को प्रदर्शित करता है और प्रत्येक को समझाने के लिए एक डॉकस्ट्रिंग प्रदान करता है:

class Foo(object):

    def a_normal_instance_method(self, arg_1, kwarg_2=None):
        '''
        Return a value that is a function of the instance with its
        attributes, and other arguments such as arg_1 and kwarg2
        '''

    @staticmethod
    def a_static_method(arg_0):
        '''
        Return a value that is a function of arg_0. It does not know the 
        instance or class it is called from.
        '''

    @classmethod
    def a_class_method(cls, arg1):
        '''
        Return a value that is a function of the class and other arguments.
        respects subclassing, it is called with the class it is called from.
        '''

सामान्य उदाहरण विधि

पहले मैं समझाता हूँ a_normal_instance_method। इसे सटीक रूप से " उदाहरण विधि " कहा जाता है । जब एक आवृत्ति विधि का उपयोग किया जाता है, तो इसका उपयोग आंशिक फ़ंक्शन के रूप में किया जाता है (कुल फ़ंक्शन के विपरीत, सभी मूल्यों के लिए परिभाषित जब स्रोत कोड में देखा जाता है), जब उपयोग किया जाता है, तो पहले तर्क को उदाहरण के रूप में पूर्वनिर्धारित किया जाता है ऑब्जेक्ट, इसके दिए गए सभी गुणों के साथ। इसमें वस्तु का उदाहरण दिया गया है, और इसे वस्तु के उदाहरण से बुलाया जाना चाहिए। आमतौर पर, यह उदाहरण की विभिन्न विशेषताओं तक पहुँच प्राप्त करेगा।

उदाहरण के लिए, यह एक स्ट्रिंग का एक उदाहरण है:

', '

यदि हम joinइस स्ट्रिंग पर इंस्टेंस मेथड का उपयोग करते हैं , तो एक और पुनरावृत्ति में शामिल होने के लिए, यह स्पष्ट रूप से एरे का एक फ़ंक्शन है, इसके अलावा, इट्रेबल लिस्ट का एक फंक्शन है ['a', 'b', 'c']:

>>> ', '.join(['a', 'b', 'c'])
'a, b, c'

बंधे हुए तरीके

उदाहरण के तरीकों को बाद में उपयोग के लिए एक बिंदीदार लुकअप के माध्यम से बाध्य किया जा सकता है।

उदाहरण के लिए, यह उदाहरण के लिए str.joinविधि को बांधता है ':':

>>> join_with_colons = ':'.join 

और बाद में हम इसे एक फ़ंक्शन के रूप में उपयोग कर सकते हैं, जिसके पास पहले से ही पहला तर्क है। इस तरह, यह उदाहरण पर एक आंशिक कार्य की तरह काम करता है:

>>> join_with_colons('abcde')
'a:b:c:d:e'
>>> join_with_colons(['FF', 'FF', 'FF', 'FF', 'FF', 'FF'])
'FF:FF:FF:FF:FF:FF'

स्थैतिक विधि

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

यह एक मॉड्यूल स्तर फ़ंक्शन के समान है।

हालाँकि, मॉड्यूल स्तर फ़ंक्शन को मॉड्यूल में रहना चाहिए और विशेष रूप से अन्य स्थानों पर आयात किया जाना चाहिए जहां इसका उपयोग किया जाता है।

यदि यह ऑब्जेक्ट से जुड़ा हुआ है, हालांकि, यह आयात और विरासत के साथ-साथ ऑब्जेक्ट का आसानी से पालन करेगा।

स्थैतिक विधि का एक उदाहरण है str.maketrans, stringजिसे पायथन 3 में मॉड्यूल से स्थानांतरित किया गया है । यह अनुवाद तालिका को उपभोग के लिए उपयुक्त बनाता है str.translate। यह स्ट्रिंग के उदाहरण से उपयोग किए जाने पर मूर्खतापूर्ण प्रतीत होता है, जैसा कि नीचे दिखाया गया है, लेकिन stringमॉड्यूल से फ़ंक्शन आयात करना अनाड़ी है, और इसे कक्षा से कॉल करने में सक्षम होने के लिए अच्छा है, जैसे किstr.maketrans

# demonstrate same function whether called from instance or not:
>>> ', '.maketrans('ABC', 'abc')
{65: 97, 66: 98, 67: 99}
>>> str.maketrans('ABC', 'abc')
{65: 97, 66: 98, 67: 99}

अजगर 2 में, आपको इस फ़ंक्शन को तेजी से कम उपयोगी स्ट्रिंग मॉड्यूल से आयात करना होगा:

>>> import string
>>> 'ABCDEFG'.translate(string.maketrans('ABC', 'abc'))
'abcDEFG'

कक्षा विधि

एक वर्ग विधि एक उदाहरण विधि के समान है जिसमें यह एक अंतर्निहित पहला तर्क लेता है, लेकिन उदाहरण लेने के बजाय, यह कक्षा लेता है। बेहतर अर्थ प्रयोग के लिए अक्सर इन्हें वैकल्पिक निर्माणकर्ताओं के रूप में उपयोग किया जाता है और यह विरासत का समर्थन करेगा।

बिलियन क्लासमेथोड का सबसे विहित उदाहरण है dict.fromkeys। यह तानाशाह के एक वैकल्पिक निर्माणकर्ता के रूप में उपयोग किया जाता है, (जब आप जानते हैं कि आपकी कुंजी क्या है और उनके लिए डिफ़ॉल्ट मान चाहते हैं, तो आपके लिए उपयुक्त है।)

>>> dict.fromkeys(['a', 'b', 'c'])
{'c': None, 'b': None, 'a': None}

जब हम तानाशाही को कम करते हैं, तो हम उसी निर्माणकर्ता का उपयोग कर सकते हैं, जो उपवर्ग का एक उदाहरण बनाता है।

>>> class MyDict(dict): 'A dict subclass, use to demo classmethods'
>>> md = MyDict.fromkeys(['a', 'b', 'c'])
>>> md
{'a': None, 'c': None, 'b': None}
>>> type(md)
<class '__main__.MyDict'>

वैकल्पिक कंस्ट्रक्टरों के अन्य समान उदाहरणों के लिए पांडा स्रोत कोड देखें , और पर classmethodऔर आधिकारिक पायथन प्रलेखन भी देखें staticmethod


43

मैंने C ++ और फिर जावा और फिर पायथन के साथ प्रोग्रामिंग भाषा सीखना शुरू किया और इसलिए इस सवाल ने मुझे बहुत परेशान किया, जब तक कि मैंने प्रत्येक के सरल उपयोग को नहीं समझा।

कक्षा विधि: जावा और C ++ के विपरीत पायथन में कंस्ट्रक्टर ओवरलोडिंग नहीं है। और इसलिए इसे हासिल करने के लिए आप इसका इस्तेमाल कर सकते हैं classmethod। निम्नलिखित उदाहरण यह समझाएंगे

आइए विचार करें कि हमारे पास एक Personवर्ग है जो दो तर्क लेता है first_nameऔर last_nameइसका उदाहरण बनाता है Person

class Person(object):

    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

अब, यदि आवश्यकता आती है तो आपको केवल एक नाम का उपयोग करके एक वर्ग बनाने की आवश्यकता है, बस first_name, आप पायथन में ऐसा कुछ नहीं कर सकते

यह आपको एक त्रुटि देगा जब आप एक ऑब्जेक्ट (उदाहरण) बनाने की कोशिश करेंगे।

class Person(object):

    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

    def __init__(self, first_name):
        self.first_name = first_name

हालाँकि, आप @classmethodनीचे बताए अनुसार उसी चीज़ को प्राप्त कर सकते हैं

class Person(object):

    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

    @classmethod
    def get_person(cls, first_name):
        return cls(first_name, "")

स्टैटिक विधि: यह बल्कि सरल है, यह उदाहरण या वर्ग के लिए बाध्य नहीं है और आप बस क्लास नाम का उपयोग करके कॉल कर सकते हैं।

तो चलिए उपरोक्त उदाहरण में आपको एक मान्यता की आवश्यकता है जो first_name20 वर्णों से अधिक नहीं होनी चाहिए, आप बस ऐसा कर सकते हैं।

@staticmethod  
def validate_name(name):
    return len(name) <= 20

और आप बस का उपयोग कर कॉल कर सकते हैं class name

Person.validate_name("Gaurang Shah")

2
यह एक पुरानी पोस्ट है, लेकिन एक या दो तर्कों को स्वीकार करने वाले कंस्ट्रक्टर को प्राप्त करने के लिए अधिक पायथोनिक तरीका def __init__(self, first_name, last_name="")क्लासथेथोड के बजाय उपयोग करना होगा get_person। परिणाम भी इस मामले में बिल्कुल वैसा ही होगा।
ऐकरिलिमानो

31

मुझे लगता है कि एक बेहतर सवाल है "आप कब @classmethod बनाम @staticmethod का उपयोग करेंगे?"

@classmethod आपको निजी सदस्यों के लिए आसान पहुँच की अनुमति देता है जो वर्ग परिभाषा से जुड़े हैं। यह एकल, या फैक्ट्री कक्षाएं करने का एक शानदार तरीका है जो निर्मित वस्तुओं के उदाहरणों की संख्या को नियंत्रित करता है।

@staticmethod सीमांत प्रदर्शन लाभ प्रदान करता है, लेकिन मुझे अभी तक एक वर्ग के भीतर एक स्थिर पद्धति का उत्पादक उपयोग देखना है जो वर्ग के बाहर एक स्टैंडअलोन फ़ंक्शन के रूप में प्राप्त नहीं किया जा सकता है।


31

@decorators को python 2.4 में जोड़ा गया था। यदि आप python <2.4 का उपयोग कर रहे हैं, तो आप classmethod () और staticmethod () फ़ंक्शन का उपयोग कर सकते हैं।

उदाहरण के लिए, यदि आप एक फैक्ट्री मेथड बनाना चाहते हैं (ए फंक्शन इस बात पर निर्भर करता है कि किसी वर्ग के अलग-अलग क्रियान्वयन का एक उदाहरण किस तर्क के आधार पर मिलता है) तो आप कुछ ऐसा कर सकते हैं:

class Cluster(object):

    def _is_cluster_for(cls, name):
        """
        see if this class is the cluster with this name
        this is a classmethod
        """ 
        return cls.__name__ == name
    _is_cluster_for = classmethod(_is_cluster_for)

    #static method
    def getCluster(name):
        """
        static factory method, should be in Cluster class
        returns a cluster object for the given name
        """
        for cls in Cluster.__subclasses__():
            if cls._is_cluster_for(name):
                return cls()
    getCluster = staticmethod(getCluster)

यह भी देखें कि यह एक उत्तम श्रेणी और स्थिर विधि का उपयोग करने के लिए एक अच्छा उदाहरण है, स्थैतिक विधि स्पष्ट रूप से वर्ग से संबंधित है, क्योंकि यह आंतरिक रूप से वर्ग क्लस्टर का उपयोग करता है। Classmethod को केवल कक्षा के बारे में जानकारी चाहिए, और ऑब्जेक्ट का कोई उदाहरण नहीं।

_is_cluster_forविधि बनाने का एक अन्य लाभ यह है कि क्लासमेथोड इतना उप-वर्ग है जो इसे लागू करने का निर्णय ले सकता है, हो सकता है क्योंकि यह बहुत सामान्य है और एक से अधिक प्रकार के क्लस्टर को संभाल सकता है, इसलिए केवल कक्षा के नाम की जांच करना पर्याप्त नहीं होगा।


28

स्थैतिक तरीके:

  • बिना किसी आत्म तर्क के सरल कार्य।
  • वर्ग विशेषताओं पर काम; उदाहरण की विशेषताओं पर नहीं।
  • वर्ग और उदाहरण दोनों के माध्यम से बुलाया जा सकता है।
  • इनको बनाने के लिए बिल्ट-इन फंक्शन staticmethod () का उपयोग किया जाता है।

स्थैतिक तरीकों के लाभ:

  • यह classscope में फ़ंक्शन नाम को स्थानीय करता है
  • यह फ़ंक्शन कोड को जहां उपयोग किया जाता है, उसके करीब ले जाता है
  • मॉड्यूल-स्तर के कार्यों को आयात करने के लिए अधिक सुविधाजनक है क्योंकि प्रत्येक विधि को विशेष रूप से आयात करने की आवश्यकता नहीं है

    @staticmethod
    def some_static_method(*args, **kwds):
        pass

कक्षा के तरीके:

  • फ़ंक्शंस जिसमें classname के रूप में पहला तर्क है।
  • वर्ग और उदाहरण दोनों के माध्यम से बुलाया जा सकता है।
  • ये classmethod इन-बिल्ट फ़ंक्शन के साथ बनाए गए हैं।

     @classmethod
     def some_class_method(cls, *args, **kwds):
         pass

22

@staticmethodकेवल विधि डिस्क्रिप्टर के रूप में डिफ़ॉल्ट फ़ंक्शन को अक्षम करता है। classmethod आपके फ़ंक्शन को एक कंटेनर कॉलेबल में लपेटता है जो पहले तर्क के रूप में स्वयं के वर्ग के लिए एक संदर्भ देता है:

>>> class C(object):
...  pass
... 
>>> def f():
...  pass
... 
>>> staticmethod(f).__get__(None, C)
<function f at 0x5c1cf0>
>>> classmethod(f).__get__(None, C)
<bound method type.f of <class '__main__.C'>>

तथ्य की बात के रूप में, classmethodएक रनटाइम ओवरहेड है, लेकिन मालिक वर्ग तक पहुंचना संभव बनाता है। वैकल्पिक रूप से मैं एक मेटाकाॅल का उपयोग करने और उस मेटाक्लास पर कक्षा के तरीकों को रखने की सलाह देता हूं:

>>> class CMeta(type):
...  def foo(cls):
...   print cls
... 
>>> class C(object):
...  __metaclass__ = CMeta
... 
>>> C.foo()
<class '__main__.C'>

1
इसके लिए मेटाक्लस का एक संभावित नकारात्मक पहलू जो मुझे तुरंत होता है, वह यह है कि आप क्लासमेट को सीधे इंस्टेंस पर कॉल नहीं कर सकते। c = C(); c.foo()विशेषता को बढ़ाता है, आपको करना होगा type(c).foo()। इसे एक विशेषता भी माना जा सकता है - मैं सोच भी नहीं सकता कि आप क्यों करना चाहते हैं।
हारून हॉल

20

पायथन में स्थैतिक, वर्ग या अमूर्त विधियों का उपयोग करने के बारे में निश्चित गाइड इस विषय के लिए एक अच्छी कड़ी है, और इसे निम्न रूप में सारांशित करें।

@staticmethodफ़ंक्शन एक वर्ग के अंदर परिभाषित फ़ंक्शन से ज्यादा कुछ नहीं है। यह पहली कक्षा को तत्काल किए बिना कॉल करने योग्य है। यह परिभाषा विरासत के माध्यम से अपरिवर्तनीय है।

  • पाइथन को ऑब्जेक्ट के लिए बाउंड-मेथड इंस्टेंट करने की जरूरत नहीं है।
  • यह कोड की पठनीयता को कम करता है, और यह स्वयं वस्तु की स्थिति पर निर्भर नहीं करता है;

@classmethodफ़ंक्शन भी क्लास को तुरंत किए बिना कॉल करने योग्य है, लेकिन इसकी परिभाषा सब क्लास का अनुसरण करती है, अभिभावक वर्ग नहीं, विरासत के माध्यम से, उपवर्ग द्वारा ओवरराइड किया जा सकता है। ऐसा इसलिए है क्योंकि @classmethodफ़ंक्शन के लिए पहला तर्क हमेशा cls (क्लास) होना चाहिए ।

  • फ़ैक्टरी विधियाँ , जिनका उपयोग वर्ग के लिए एक उदाहरण बनाने के लिए किया जाता है, उदाहरण के लिए पूर्व-प्रसंस्करण के कुछ प्रकार।
  • स्टेटिक तरीकों को कॉल करने वाले स्टेटिक तरीके : यदि आप कई स्टैटिक तरीकों में स्टेटिक तरीकों को विभाजित करते हैं, तो आपको क्लास के नाम को हार्ड-कोड नहीं करना चाहिए, लेकिन क्लास के तरीकों का उपयोग करना चाहिए

धन्यवाद @zangw - स्थिर समारोह की विरासत में मिली अपरिवर्तनीयता से लगता है कि महत्वपूर्ण अंतर है
hard_working_ant

18

केवल पहला तर्क अलग है :

  • सामान्य विधि: वर्तमान वस्तु यदि स्वचालित रूप से एक (अतिरिक्त) पहले तर्क के रूप में पारित हो जाती है
  • क्लासमेथोड: वर्तमान वस्तु का वर्ग स्वचालित रूप से एक (अतिरिक्त) मुट्ठी तर्क के रूप में पारित हो जाता है
  • स्टेटमिथोड: कोई अतिरिक्त तर्क स्वचालित रूप से पारित नहीं होता है। समारोह में आप जो पास करते हैं वही आपको मिलता है।

विस्तृत रूप में...

सामान्य विधि

जब किसी ऑब्जेक्ट की विधि को कॉल किया जाता है, तो इसे स्वचालित selfरूप से इसके पहले तर्क के रूप में एक अतिरिक्त तर्क दिया जाता है। वह है, विधि

def f(self, x, y)

2 तर्कों के साथ बुलाया जाना चाहिए। selfस्वचालित रूप से पारित हो गया है, और यह वस्तु ही है

कक्षा विधि

जब विधि सजाई जाती है

@classmethod
def f(cls, x, y)

स्वचालित रूप से प्रदान की जाती तर्क नहीं है self , लेकिन के वर्ग self

स्थैतिक विधि

जब विधि सजाई जाती है

@staticmethod
def f(x, y)

विधि को कोई स्वचालित तर्क नहीं दिया गया है । यह केवल उन मापदंडों को दिया जाता है जिनके साथ इसे बुलाया जाता है।

उपयोगों

  • classmethod ज्यादातर वैकल्पिक निर्माणकर्ताओं के लिए उपयोग किया जाता है।
  • staticmethodवस्तु की स्थिति का उपयोग नहीं करता है। यह एक वर्ग के लिए एक बाहरी कार्य हो सकता है। यह केवल इसी तरह की कार्यक्षमता के साथ कार्य करने के लिए वर्ग के अंदर रखता है (उदाहरण के लिए, जावा की Mathकक्षा स्थिर विधियों की तरह)
class Point
    def __init__(self, x, y):
        self.x = x
        self.y = y

    @classmethod
    def frompolar(cls, radius, angle):
        """The `cls` argument is the `Point` class itself"""
        return cls(radius * cos(angle), radius * sin(angle))

    @staticmethod
    def angle(x, y):
        """this could be outside the class, but we put it here 
just because we think it is logically related to the class."""
        return atan(y, x)


p1 = Point(3, 2)
p2 = Point.frompolar(3, pi/4)

angle = Point.angle(3, 2)

17

मुझे पहले @classmethod बनाम @staticmethod से सजाए गए एक विधि के बीच समानता बताएं।

समानता: इन दोनों को केवल कक्षा के उदाहरण के बजाय कक्षा में ही बुलाया जा सकता है । तो, दोनों एक तरह से क्लास के तरीके हैं

अंतर: एक क्लासमेथोड कक्षा को पहले तर्क के रूप में प्राप्त करेगा, जबकि एक स्टेथमिथोड नहीं करता है।

तो एक स्थिर विधि एक अर्थ में, क्लास के लिए बाध्य नहीं है और सिर्फ इसलिए लटकी हुई है क्योंकि इसमें संबंधित कार्यक्षमता हो सकती है।

>>> class Klaus:
        @classmethod
        def classmthd(*args):
            return args

        @staticmethod
        def staticmthd(*args):
            return args

# 1. Call classmethod without any arg
>>> Klaus.classmthd()  
(__main__.Klaus,)  # the class gets passed as the first argument

# 2. Call classmethod with 1 arg
>>> Klaus.classmthd('chumma')
(__main__.Klaus, 'chumma')

# 3. Call staticmethod without any arg
>>> Klaus.staticmthd()  
()

# 4. Call staticmethod with 1 arg
>>> Klaus.staticmthd('chumma')
('chumma',)

11

स्टैक्मेमेथोड बनाम क्लासमेथोड के संबंध में एक और विचार विरासत के साथ आता है। कहो कि आपके पास निम्न वर्ग है:

class Foo(object):
    @staticmethod
    def bar():
        return "In Foo"

और फिर आप bar()एक बच्चे की कक्षा में ओवरराइड करना चाहते हैं :

class Foo2(Foo):
    @staticmethod
    def bar():
        return "In Foo2"

यह काम करता है, लेकिन ध्यान दें कि अब bar()चाइल्ड क्लास में कार्यान्वयन ( Foo2) अब उस क्लास के लिए कुछ खास नहीं कर सकता है। उदाहरण के लिए, कहते हैं Foo2कि एक विधि थी जिसे magic()आप के Foo2कार्यान्वयन में उपयोग करना चाहते हैं bar():

class Foo2(Foo):
    @staticmethod
    def bar():
        return "In Foo2"
    @staticmethod
    def magic():
        return "Something useful you'd like to use in bar, but now can't" 

वैकल्पिक हल यहां कॉल करने के लिए किया जाएगा Foo2.magic()में bar()है, लेकिन फिर आप अपने आप को दोहरा रहे हैं (यदि का नाम Foo2परिवर्तन, आपको लगता है कि अद्यतन करने के लिए याद रखना होगा bar()विधि)।

मेरे लिए, यह खुले / बंद सिद्धांत का एक मामूली उल्लंघन है , क्योंकि किए गए एक निर्णय से Fooव्युत्पन्न वर्ग में आम कोड को फिर से भरने की आपकी क्षमता को प्रभावित कर रहा है (यानी यह विस्तार के लिए कम खुला है)। यदि bar()एक थे classmethodहम ठीक हो जाएगा:

class Foo(object):
    @classmethod
    def bar(cls):
        return "In Foo"

class Foo2(Foo):
    @classmethod
    def bar(cls):
        return "In Foo2 " + cls.magic()
    @classmethod
    def magic(cls):
        return "MAGIC"

print Foo2().bar()

देता है: In Foo2 MAGIC


7

मैं एक उदाहरण का उपयोग करके मूल अंतर को समझाने की कोशिश करूंगा।

class A(object):
    x = 0

    def say_hi(self):
        pass

    @staticmethod
    def say_hi_static():
        pass

    @classmethod
    def say_hi_class(cls):
        pass

    def run_self(self):
        self.x += 1
        print self.x # outputs 1
        self.say_hi()
        self.say_hi_static()
        self.say_hi_class()

    @staticmethod
    def run_static():
        print A.x  # outputs 0
        # A.say_hi() #  wrong
        A.say_hi_static()
        A.say_hi_class()

    @classmethod
    def run_class(cls):
        print cls.x # outputs 0
        # cls.say_hi() #  wrong
        cls.say_hi_static()
        cls.say_hi_class()

1 - हम सीधे इनिशिएटिव के बिना स्टैटिक और क्लासमेथोड कह सकते हैं

# A.run_self() #  wrong
A.run_static()
A.run_class()

2- स्थैतिक विधि स्वयं विधि को नहीं कह सकती है लेकिन अन्य स्थैतिक और वर्गमित्र कह सकते हैं

3- स्थैतिक विधि कक्षा से संबंधित होती है और वह वस्तु का उपयोग बिल्कुल नहीं करेगी।

4- कक्षा पद्धति किसी वस्तु से नहीं बल्कि एक वर्ग से जुड़ी होती है।


विज्ञापन 2: क्या आपको यकीन है? स्थैतिकमथ क्लासमिथोड कैसे कह सकता है? इसका (इसकी कक्षा के लिए) कोई संदर्भ नहीं है।
मेरीक

7

@classmethod: का उपयोग उस वर्ग के बनाए गए सभी उदाहरणों के लिए एक साझा वैश्विक पहुंच बनाने के लिए किया जा सकता है ..... जैसे कई उपयोगकर्ताओं द्वारा रिकॉर्ड को अपडेट करना .... मुझे लगता है कि यह एकल का उपयोग करते समय पूर्ण का उपयोग करता है। )

@ अस्थिर विधि: वर्ग या उदाहरण के साथ जुड़े होने के साथ कुछ नहीं करना है ... लेकिन पठनीयता के लिए स्थैतिक विधि का उपयोग कर सकते हैं


5

आप इसके बीच के अंतर पर विचार करना चाह सकते हैं:

Class A:
    def foo():  # no self parameter, no decorator
        pass

तथा

Class B:
    @staticmethod
    def foo():  # no self parameter
        pass

यह python2 और python3 के बीच बदल गया है:

को Python2:

>>> A.foo()
TypeError
>>> A().foo()
TypeError
>>> B.foo()
>>> B().foo()

python3:

>>> A.foo()
>>> A().foo()
TypeError
>>> B.foo()
>>> B().foo()

इसलिए @staticmethodकेवल कक्षा से सीधे बुलाए गए तरीकों के लिए उपयोग करना python3 में वैकल्पिक हो गया है। यदि आप उन्हें कक्षा और उदाहरण दोनों से कॉल करना चाहते हैं, तो आपको अभी भी उपयोग करने की आवश्यकता है@staticmethod डेकोरेटर ।

अन्य मामलों को निष्पक्ष उत्तर द्वारा अच्छी तरह से कवर किया गया है।


5

एक क्लास मेथड को इंप्लिमेंट फस्र्ट लॉजिक के रूप में प्राप्त होता है, ठीक उसी तरह जैसे इंस्टेंस मेथड को इंस्टेंस प्राप्त होता है। यह एक ऐसी विधि है जो कक्षा के लिए बाध्य होती है न कि कक्षा की वस्तु के रूप में। यह कक्षा की स्थिति तक पहुंच रखती है क्योंकि यह एक क्लास पैरामीटर लेती है जो क्लास को इंगित करता है न कि ऑब्जेक्ट इंस्टेंस को। यह एक वर्ग राज्य को संशोधित कर सकता है जो कक्षा के सभी उदाहरणों पर लागू होगा। उदाहरण के लिए यह एक वर्ग चर को संशोधित कर सकता है जो सभी उदाहरणों पर लागू होगा।

दूसरी ओर, क्लास पद्धतियों या उदाहरण विधियों की तुलना में एक स्टैटिक विधि में निहित पहला तर्क नहीं मिलता है। और कक्षा अवस्था तक पहुँच या संशोधन नहीं कर सकता। यह केवल कक्षा से संबंधित है क्योंकि डिजाइन के दृष्टिकोण से यह सही तरीका है। लेकिन कार्यक्षमता के मामले में बाध्य नहीं है, रनटाइम पर, वर्ग के लिए।

एक दिशानिर्देश के रूप में, उपयोगिताओं के रूप में स्थिर तरीकों का उपयोग करें, कारखाने के रूप में उदाहरण के लिए वर्ग विधियों का उपयोग करें। या शायद एक सिंगलटन को परिभाषित करने के लिए। और उदाहरण के तरीकों और राज्य और व्यवहार के उदाहरणों का उपयोग करें।

आशा है कि मैं स्पष्ट था!


4

मेरे योगदान के बीच का अंतर बताता है @classmethod, @staticmethodकैसे एक उदाहरण परोक्ष रूप से एक कॉल कर सकते हैं शामिल है, और उदाहरण के तरीकों, @staticmethod। लेकिन अप्रत्यक्ष रूप @staticmethodसे एक उदाहरण से कॉल करने के बजाय , इसे निजी बनाने से अधिक "पाइथोनिक" हो सकता है। एक निजी विधि से कुछ प्राप्त करना यहाँ प्रदर्शित नहीं है, लेकिन यह मूल रूप से एक ही अवधारणा है।

#!python3

from os import system
system('cls')
# %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %

class DemoClass(object):
    # instance methods need a class instance and
    # can access the instance through 'self'
    def instance_method_1(self):
        return 'called from inside the instance_method_1()'

    def instance_method_2(self):
        # an instance outside the class indirectly calls the static_method
        return self.static_method() + ' via instance_method_2()'

    # class methods don't need a class instance, they can't access the
    # instance (self) but they have access to the class itself via 'cls'
    @classmethod
    def class_method(cls):
        return 'called from inside the class_method()'

    # static methods don't have access to 'cls' or 'self', they work like
    # regular functions but belong to the class' namespace
    @staticmethod
    def static_method():
        return 'called from inside the static_method()'
# %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %

# works even if the class hasn't been instantiated
print(DemoClass.class_method() + '\n')
''' called from inside the class_method() '''

# works even if the class hasn't been instantiated
print(DemoClass.static_method() + '\n')
''' called from inside the static_method() '''
# %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %

# >>>>> all methods types can be called on a class instance <<<<<
# instantiate the class
democlassObj = DemoClass()

# call instance_method_1()
print(democlassObj.instance_method_1() + '\n')
''' called from inside the instance_method_1() '''

# # indirectly call static_method through instance_method_2(), there's really no use
# for this since a @staticmethod can be called whether the class has been
# instantiated or not
print(democlassObj.instance_method_2() + '\n')
''' called from inside the static_method() via instance_method_2() '''

# call class_method()
print(democlassObj.class_method() + '\n')
'''  called from inside the class_method() '''

# call static_method()
print(democlassObj.static_method())
''' called from inside the static_method() '''

"""
# whether the class is instantiated or not, this doesn't work
print(DemoClass.instance_method_1() + '\n')
'''
TypeError: TypeError: unbound method instancemethod() must be called with
DemoClass instance as first argument (got nothing instead)
'''
"""

2

कक्षा के तरीकों, जैसा कि नाम से पता चलता है, का उपयोग कक्षाओं में परिवर्तन करने के लिए किया जाता है न कि वस्तुओं के लिए। कक्षाओं में परिवर्तन करने के लिए, वे कक्षा विशेषताओं (ऑब्जेक्ट विशेषताओं को नहीं) को संशोधित करेंगे, क्योंकि आप कक्षाओं को कैसे अपडेट करते हैं। यही कारण है कि वर्ग विधियाँ पहले तर्क के रूप में वर्ग (पारंपरिक रूप से 'cls' द्वारा निरूपित) लेती हैं।

class A(object):
    m=54

    @classmethod
    def class_method(cls):
        print "m is %d" % cls.m

दूसरी ओर स्थैतिक विधियों का उपयोग उन क्रियाकलापों को करने के लिए किया जाता है जो कक्षा के लिए बाध्य नहीं होते हैं अर्थात वे कक्षा चर को नहीं पढ़ते या लिखते हैं। इसलिए, स्थैतिक विधियाँ तर्क के रूप में कक्षाएं नहीं लेती हैं। उनका उपयोग किया जाता है ताकि कक्षाएं कार्यात्मकता का प्रदर्शन कर सकें जो सीधे वर्ग के उद्देश्य से संबंधित नहीं हैं।

class X(object):
    m=54 #will not be referenced

    @staticmethod
    def static_method():
        print "Referencing/calling a variable or function outside this class. E.g. Some global variable/function."

2

शाब्दिक रूप से @staticmethod का विश्लेषण करें विभिन्न अंतर्दृष्टि प्रदान करता है।

कक्षा की एक सामान्य विधि एक अंतर्निहित गतिशील विधि है जो उदाहरण को पहले तर्क के रूप में लेती है।
इसके विपरीत, एक staticmethod उदाहरण को पहले तर्क के रूप में नहीं लेता है, इसलिए इसे 'स्टेटिक' कहा जाता है ।

एक स्टैटिकमेथोड वास्तव में ऐसा सामान्य कार्य है जो एक वर्ग परिभाषा के बाहर के समान है।
यह सौभाग्य से वर्ग में वर्गीकृत किया गया है ताकि इसे लागू किया जा सके, या आप इसे खोजने के लिए चारों ओर स्क्रॉल कर सकते हैं।


2

मुझे लगता है कि विशुद्ध रूप से पायथन संस्करण देना staticmethodऔरclassmethod भाषा के स्तर पर उन दोनों के बीच के अंतर को समझना में मदद मिलेगी।

ये दोनों गैर-डेटा डिस्क्रिप्टर हैं (यदि आप पहले डिस्क्रिप्टर से परिचित हैं तो उन्हें समझना आसान होगा )।

class StaticMethod(object):
    "Emulate PyStaticMethod_Type() in Objects/funcobject.c"

    def __init__(self, f):
        self.f = f

    def __get__(self, obj, objtype=None):
        return self.f


class ClassMethod(object):
    "Emulate PyClassMethod_Type() in Objects/funcobject.c"
    def __init__(self, f):
        self.f = f

    def __get__(self, obj, cls=None):
        def inner(*args, **kwargs):
            if cls is None:
                cls = type(obj)
            return self.f(cls, *args, **kwargs)
        return inner

1

staticmethod के पास ऑब्जेक्ट के एटिट्यूड, क्लास की, या पैरेंट क्लासेस की वंशानुगत पदानुक्रम तक पहुंच नहीं है। इसे सीधे कक्षा में बुलाया जा सकता है (बिना वस्तु बनाए)।

classmethod के पास ऑब्जेक्ट की विशेषताओं तक कोई पहुंच नहीं है। हालाँकि यह वंशानुक्रम पदानुक्रम में वर्ग और मूल वर्गों की विशेषताओं तक पहुँच सकता है। इसे सीधे कक्षा में बुलाया जा सकता है (बिना वस्तु बनाए)। यदि ऑब्जेक्ट पर कॉल किया जाता है तो यह सामान्य विधि के समान है जो एक्सेस self.<attribute(s)>और एक्सेस नहीं करता हैself.__class__.<attribute(s)> केवल ।

हमें लगता है कि हमारे पास एक वर्ग है b=2, हम एक ऑब्जेक्ट बनाएंगे और इसमें इसे फिर से सेट b=4करेंगे। Staticmethod पिछले कुछ भी नहीं का उपयोग कर सकते हैं। Classmethod .b==2केवल, के माध्यम से उपयोग कर सकते हैं cls.b। सामान्य विधि दोनों का उपयोग कर सकती है: के .b==4माध्यम से self.bऔर के .b==2माध्यम से self.__class__.b

हम KISS शैली (यह आसान बेवकूफ रखने के लिए,) का पालन कर सकते हैं: Do staticmethods और classmethods का उपयोग नहीं है, उन्हें केवल वस्तु के गुणों instantiating, उपयोग के बिना वर्गों का उपयोग नहीं करते self.attribute(s)। ऐसी भाषाएं हैं जहां ओओपी को इस तरह लागू किया गया है और मुझे लगता है कि यह बुरा विचार नहीं है। :)


Classmethods के लिए एक और महत्वपूर्ण बात: यदि आप वर्ग विधि में एक विशेषता को संशोधित करते हैं, तो इस वर्ग के सभी मौजूदा ऑब्जेक्ट जो इस विशेषता को स्पष्ट रूप से सेट नहीं करते हैं, में संशोधित मूल्य होगा।
मेरीक

-4

IPython में एक त्वरित हैक अपोथैरवाइज़ समान तरीकों से पता चलता है कि @staticmethodसीमांत प्रदर्शन लाभ (नैनोसेकंड में) प्राप्त करता है, लेकिन अन्यथा यह बिना किसी फ़ंक्शन के काम करता है। इसके अलावा, किसी भी प्रदर्शन लाभ को संभवतः विधि के अतिरिक्त काम से मिटा दिया जाएगाstaticmethod() संकलन के दौरान (जो किसी स्क्रिप्ट को चलाने पर किसी भी कोड निष्पादन से पहले होता है)।

कोड पठनीयता की खातिर मैं @staticmethodतब तक टालूंगा जब तक कि आपके तरीके का इस्तेमाल काम के भार के लिए नहीं किया जाएगा, जहां नैनोसेकंड की गिनती होती है।


7
"अन्यथा कोई कार्य नहीं करने के लिए लगता है": सख्ती से सच नहीं है। ऊपर चर्चा देखें।
कीथ पिंसन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.