python - @Staticmethod और @classmethod के बीच क्या अंतर है?




oop methods python-decorators (20)

@staticmethod सजाए गए फ़ंक्शन और @staticmethod साथ सजाए गए फ़ंक्शन के बीच क्या अंतर है?


Answers

@Staticmethod का विश्लेषण सचमुच विभिन्न अंतर्दृष्टि प्रदान करते हैं।

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

एक staticmethod वास्तव में एक सामान्य परिभाषा है जो कक्षा परिभाषा के बाहर के समान है।
यह भाग्यशाली रूप से क्लास में समूहित किया जाता है ताकि इसे जहां कहीं भी लागू किया जा सके, या आप इसे ढूंढने के लिए चारों ओर स्क्रॉल कर सकते हैं।


क्लास विधियों, जैसा कि नाम से पता चलता है, कक्षाओं में बदलाव करने के लिए उपयोग किया जाता है, न कि ऑब्जेक्ट्स। कक्षाओं में परिवर्तन करने के लिए, वे कक्षा विशेषताओं (ऑब्जेक्ट विशेषता नहीं) को संशोधित करेंगे, क्योंकि इस प्रकार आप कक्षाओं को अपडेट करते हैं। यही कारण है कि कक्षा के तरीके कक्षा (परंपरागत रूप से '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."

@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'>

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

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

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

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

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

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.magic() में Foo2.magic() को कॉल करना होगा, लेकिन फिर आप स्वयं को दोहरा रहे हैं (यदि Foo2 का नाम बदलता है, तो आपको उस bar() विधि को अपडेट करना याद रखना होगा)।

मेरे लिए, यह खुला / बंद सिद्धांत का मामूली उल्लंघन है, क्योंकि Foo में किए गए निर्णय व्युत्पन्न वर्ग में सामान्य कोड को दोबारा करने की आपकी क्षमता को प्रभावित कर रहे हैं (यानी यह विस्तार के लिए कम खुला है)। यदि bar() एक classmethod थे 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


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

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


@decorators python 2.4 में जोड़े गए थे यदि आप अजगर <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)

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

_is_cluster_for विधि को _is_cluster_for विधि बनाने का एक और लाभ यह है कि _is_cluster_for अपने कार्यान्वयन को बदलने का फैसला कर सकता है, शायद क्योंकि यह बहुत सामान्य है और एक से अधिक प्रकार के क्लस्टर को संभाल सकता है, इसलिए बस कक्षा का नाम जांचना पर्याप्त नहीं होगा।


स्टेटिक तरीके:

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

स्टेटिक तरीके के लाभ:

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

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

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

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

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

#!/usr/bin/python
#coding:utf-8

class Demo(object):
    def __init__(self,x):
        self.x = x

    @classmethod
    def addone(self, x):
        return x+1

    @staticmethod
    def addtwo(x):
        return x+2

    def addthree(self, x):
        return x+3

def main():
    print Demo.addone(2)
    print Demo.addtwo(2)

    #print Demo.addthree(2) #Error
    demo = Demo(2)
    print demo.addthree(2)


if __name__ == '__main__':
    main()

पाइथन में क्लास विधि बनाम स्थैतिक विधि

कक्षा विधि

@Classmethod सजावट, एक बिल्टिन फ़ंक्शन सजावट है जो एक अभिव्यक्ति है जिसे आपके फ़ंक्शन के परिभाषित होने के बाद मूल्यांकन किया जाता है। उस मूल्यांकन का नतीजा आपकी कार्य परिभाषा को छाया देता है।

एक क्लास विधि क्लास को पहले तर्क के रूप में प्राप्त करती है, जैसे इंस्टेंस विधि उदाहरण प्राप्त करती है

वाक्य - विन्यास:

class C(object):
    @staticmethod
    def fun(arg1, arg2, ...):
        ...
returns: a static method for function fun.
  • एक वर्ग विधि एक विधि है जो वर्ग के लिए बाध्य है, न कि वर्ग की वस्तु।
  • उनके पास कक्षा की स्थिति तक पहुंच है क्योंकि यह कक्षा पैरामीटर लेता है जो कक्षा को इंगित करता है न कि वस्तु उदाहरण।
  • यह एक वर्ग राज्य को संशोधित कर सकता है जो कक्षा के सभी उदाहरणों पर लागू होगा। उदाहरण के लिए यह एक वर्ग चर को संशोधित कर सकता है जो सभी मामलों पर लागू होगा।

स्टेटिक विधि

एक स्थैतिक विधि को एक निहित पहला तर्क प्राप्त नहीं होता है।

वाक्य - विन्यास:

# Python program to demonstrate 
# use of class method and static method.
from datetime import date

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    # a class method to create a Person object by birth year.
    @classmethod
    def fromBirthYear(cls, name, year):
        return cls(name, date.today().year - year)

    # a static method to check if a Person is adult or not.
    @staticmethod
    def isAdult(age):
        return age > 18

person1 = Person('mayank', 21)
person2 = Person.fromBirthYear('mayank', 1996)

print person1.age
print person2.age

# print the result
print Person.isAdult(22)
  • एक स्थैतिक विधि भी एक विधि है जो वर्ग के लिए बाध्य है, न कि वर्ग की वस्तु।
  • एक स्थैतिक विधि कक्षा राज्य तक पहुंच या संशोधित नहीं कर सकती है।
  • यह एक वर्ग में मौजूद है क्योंकि यह कक्षा में मौजूद होने के तरीके के लिए समझ में आता है।

कक्षा विधि बनाम स्टेटिक विधि

  • एक वर्ग विधि पहले पैरामीटर के रूप में cls लेता है जबकि स्थिर विधि को कोई विशिष्ट पैरामीटर की आवश्यकता नहीं होती है।
  • एक क्लास विधि कक्षा स्थिति तक पहुंच या संशोधित कर सकती है जबकि स्थिर विधि इसे एक्सेस या संशोधित नहीं कर सकती है।
  • हम क्लास विधि बनाने के लिए पाइथन में @classmethod सजावट का उपयोग करते हैं और हम अजगर में एक स्थिर विधि बनाने के लिए @staticmethod सजावट का उपयोग करते हैं।

कब उपयोग करें?

  • हम आम तौर पर कारखाने के तरीकों को बनाने के लिए कक्षा विधि का उपयोग करते हैं। विभिन्न उपयोग मामलों के लिए कारखाने के तरीके कक्षा वस्तु (एक कन्स्ट्रक्टर के समान) लौटते हैं।
  • हम आमतौर पर उपयोगिता कार्यों को बनाने के लिए स्थिर तरीकों का उपयोग करते हैं।

कक्षा विधि और स्थैतिक विधि को कैसे परिभाषित किया जाए?

पायथन में कक्षा विधि को परिभाषित करने के लिए, हम @classmethod सजावट का उपयोग करते हैं और एक स्थिर विधि को परिभाषित करने के लिए हम @staticmethod सजावट का उपयोग करते हैं।

आइए हम दोनों के बीच अंतर को समझने के लिए एक उदाहरण देखें। आइए हम कहते हैं कि हम एक वर्ग व्यक्ति बनाना चाहते हैं। अब, पायथन सी ++ या जावा जैसे विधि ओवरलोडिंग का समर्थन नहीं करता है, इसलिए हम कारखाने के तरीकों को बनाने के लिए कक्षा विधियों का उपयोग करते हैं। नीचे दिए गए उदाहरण में हम जन्म वर्ष से व्यक्ति वस्तु बनाने के लिए कक्षा विधि का उपयोग करते हैं।

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

कार्यान्वयन

21
21
True

उत्पादन

>>> 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',)

Reference


पायथन में @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 । इसे ठीक से " इंस्टेंस विधि " कहा जाता है। जब एक आवृत्ति विधि का उपयोग किया जाता है, तो इसे आंशिक फ़ंक्शन के रूप में उपयोग किया जाता है (कुल फ़ंक्शन के विपरीत, स्रोत कोड में देखे जाने वाले सभी मानों के लिए परिभाषित), जिसका उपयोग किया जाता है, तर्कों में से पहला को पूर्व के रूप में पूर्वनिर्धारित किया जाता है ऑब्जेक्ट, इसके सभी दिए गए गुणों के साथ। इसमें ऑब्जेक्ट का उदाहरण है, और इसे ऑब्जेक्ट के उदाहरण से बुलाया जाना चाहिए। आमतौर पर, यह उदाहरण के विभिन्न गुणों तक पहुंच जाएगा।

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

', '

यदि हम इंस्टेंस विधि का उपयोग करते हैं, तो इस स्ट्रिंग पर शामिल हों, किसी अन्य पुनरावर्तनीय में शामिल होने के लिए, यह स्पष्ट रूप से इंस्टेंस का एक फ़ंक्शन है, इसके अलावा पुनरावर्तनीय सूची का एक कार्य होने के अलावा, ['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 , जो Python 3 में string मॉड्यूल से स्थानांतरित हो जाता है। यह एक अनुवाद तालिका बनाता है जो str.translate द्वारा खपत के लिए उपयुक्त है। स्ट्रिंग के उदाहरण से उपयोग किए जाने पर यह मूर्खतापूर्ण प्रतीत होता है, जैसा कि नीचे दिखाया गया है, लेकिन string मॉड्यूल से फ़ंक्शन आयात करना str.maketrans , और यह वर्ग से कॉल करने में सक्षम होना अच्छा है, जैसा कि 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 के वैकल्पिक कन्स्ट्रक्टर के रूप में किया जाता है, (जब आप जानते हैं कि आपकी चाबियां क्या हैं और उनके लिए डिफ़ॉल्ट मान चाहते हैं तो अच्छी तरह उपयुक्त है।)

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

जब हम dictclass dict, हम उसी कन्स्ट्रक्टर का उपयोग कर सकते हैं, जो सबक्लास का एक उदाहरण बनाता है।

>>> 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 के अन्य समान उदाहरणों के लिए पांडा स्रोत कोड देखें, और classmethod और staticmethod पर आधिकारिक पायथन दस्तावेज़ भी देखें।


मेरे योगदान के बीच का अंतर बताता है @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)
'''
"""

असल में @classmethod एक विधि बनाता है जिसका पहला तर्क वह कक्षा है जिसे क्लास इंस्टेंस के बजाए कहा जाता है, @staticmethod में कोई अंतर्निहित तर्क नहीं है।


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

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

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

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_name 20 वर्णों से अधिक नहीं होनी चाहिए, आप बस यह कर सकते हैं।

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

और आप कक्षा नाम का उपयोग कर बस कॉल कर सकते हैं

Person.validate_name("Gaurang Shah")

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

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

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


इस प्रश्न पर एक संक्षिप्त लेख Here है

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

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


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

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- कक्षा विधि किसी वस्तु के लिए बाध्य नहीं है बल्कि कक्षा में है।


आधिकारिक पायथन दस्तावेज़:

@classmethod

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

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

@classmethod फॉर्म एक फ़ंक्शन decorator - विवरण के लिए फ़ंक्शन परिभाषाओं में फ़ंक्शन परिभाषाओं का विवरण देखें।

इसे कक्षा में (जैसे Cf() ) या उदाहरण पर (जैसे C().f() ) कहा जा सकता है। उदाहरण को कक्षा के अलावा अनदेखा किया जाता है। यदि व्युत्पन्न वर्ग के लिए क्लास विधि कहा जाता है, तो व्युत्पन्न क्लास ऑब्जेक्ट को अंतर्निहित प्रथम तर्क के रूप में पारित किया जाता है।

क्लास विधियां सी ++ या जावा स्थैतिक तरीकों से अलग हैं। यदि आप उन्हें चाहते हैं, तो इस खंड में staticmethod() देखें।

@staticmethod

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

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

@staticmethod फॉर्म एक फ़ंक्शन decorator - विवरण के लिए फ़ंक्शन परिभाषाओं में फ़ंक्शन परिभाषाओं का विवरण देखें।

इसे कक्षा में (जैसे Cf() ) या उदाहरण पर (जैसे C().f() ) कहा जा सकता है। उदाहरण को कक्षा के अलावा अनदेखा किया जाता है।

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


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

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

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

हो सकता है कि उदाहरण का थोड़ा सा कोड मदद करेगा: foo , class_foo और static_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) ने A.class_foo(1) उठाया होगा, लेकिन A.class_foo(1) बस ठीक काम करता है:

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

क्लास विधियों के लिए लोगों द्वारा उपयोग किए जाने वाले लोगों का उपयोग विरासत वैकल्पिक रचनाकारों को बनाना है।

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

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

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

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

foo सिर्फ एक फ़ंक्शन है, लेकिन जब आप a.foo कॉल a.foo हैं तो आपको फ़ंक्शन नहीं मिलता है, आपको फ़ंक्शन का "आंशिक रूप से लागू" संस्करण मिलता है जिसमें ऑब्जेक्ट इंस्टेंस फ़ंक्शन के पहले तर्क के रूप में बाध्य होता है। foo 2 तर्कों की अपेक्षा करता है, जबकि 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 से class_foo

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

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

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

और निश्चित रूप से वही होता है जब आप static_foo को कक्षा A साथ कॉल करते हैं।

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

सभी ईमानदारी में, eval(repr(obj)) का कभी भी उपयोग नहीं किया जाता है। यदि आप इसे स्वयं का उपयोग करते हैं, तो आपको रोकना चाहिए, क्योंकि eval खतरनाक है, और तार आपके ऑब्जेक्ट्स को क्रमबद्ध करने के लिए एक बहुत ही अक्षम तरीका है (इसके बजाय pickle उपयोग करें)।

इसलिए, मैं __repr__ = __str__ सेटिंग की अनुशंसा करता हूं। कारण यह है कि str(list) तत्वों पर repr कहते हैं (मैं इसे पायथन की सबसे बड़ी डिजाइन त्रुटियों में से एक माना जाता है जिसे पायथन 3 द्वारा संबोधित नहीं किया गया था)। print [your, objects] आउटपुट print [your, objects] के आउटपुट के रूप में एक वास्तविक repr शायद बहुत उपयोगी नहीं होगा।

इसे अर्हता प्राप्त करने के लिए, मेरे अनुभव में, repr फ़ंक्शन का सबसे उपयोगी उपयोग केस स्ट्रिंग स्वरूपण का उपयोग करके स्ट्रिंग को अन्य स्ट्रिंग के अंदर रखना है। इस तरह, आपको उद्धरण या कुछ भी बचने की चिंता करने की ज़रूरत नहीं है। लेकिन ध्यान दें कि यहां कोई eval नहीं हुआ है।





python oop methods python-decorators