पायथन में "क्लास मेथड्स" और "इंस्टेंस मेथड्स" क्या हैं?


37

किसी प्रश्न से संबंधित चैट में एक चर्चा हुई है (यह प्रश्न स्वयं इस बात के लिए अप्रासंगिक है), यह पता चला है कि मैं पायथन को नहीं जानता हो।

मेरे दिमाग में, हालाँकि शब्दावली भाषाओं में भिन्न है, हम आम तौर पर इस तरह के कार्यों को वर्गीकृत कर सकते हैं:

  • [मुक्त] कार्य करता है
  • स्थिर तरीके / स्थिर सदस्य कार्य
  • गैर-स्थिर विधियाँ / गैर-स्थैतिक सदस्य फ़ंक्शन

जाहिरा तौर पर पायथन में एक अन्य प्रकार का फ़ंक्शन है जो उपरोक्त श्रेणियों में फिट नहीं होता है, एक यह एक तरीका है लेकिन "अपनी कक्षा को नहीं जानता"।

पायथन में "क्लास मेथड्स" और "इंस्टेंस मेथड्स" क्या हैं?


1
अगर कोई बातचीत चर्चा में रुचि रखते है, यहाँ शुरू: chat.stackexchange.com/transcript/message/26479002#26479002
Yannis

1
IMO एक अलग स्टैकएक्सचेंज वेबसाइट द्वारा एक बेहतर उत्तर दिया गया है: stackoverflow.com/questions/136097/…
ट्रेवर बॉयड स्मिथ

FYI करें लिंक स्वीकृत के नीचे प्रदान किया गया है ... लेकिन मुझे लगता है कि बहुत से लोग लिंक को याद करेंगे या कभी नहीं करेंगे और इसलिए मैंने इसे यहां कॉपी किया।
ट्रेवर बॉयड स्मिथ

जवाबों:


49

संक्षिप्त उत्तर

  • एक आवृत्ति विधि इसका उदाहरण जानती है (और उससे, इसकी कक्षा)
  • एक वर्ग विधि अपने वर्ग को जानती है
  • एक स्थिर विधि अपने वर्ग या उदाहरण को नहीं जानती है

लंबा जवाब

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

एक वर्ग विधि वह है जो कक्षा के रूप में संपूर्ण होती है। यह एक उदाहरण की आवश्यकता नहीं है। इसके बजाय, वर्ग स्वचालित रूप से पहले तर्क के रूप में भेजा जाएगा। @classmethodडेकोरेटर के साथ एक क्लास विधि घोषित की जाती है ।

उदाहरण के लिए:

class Foo(object):
    @classmethod
    def hello(cls):
        print("hello from %s" % cls.__name__)
Foo.hello()
-> "Hello from Foo"
Foo().hello()
-> "Hello from Foo"

उदाहरण के तरीके

दूसरी ओर, एक इंस्टेंस विधि को कॉल करने के लिए एक उदाहरण की आवश्यकता होती है, और किसी डेकोरेटर की आवश्यकता नहीं होती है। यह अब तक की सबसे आम प्रकार की विधि है।

class Foo(object):
    def hello(self):
        print("hello from %s" % self.__class__.__name__)
Foo.hello()
-> TypeError: hello() missing 1 required positional argument: 'self'

(नोट: ऊपर python3 के साथ है; python2 के साथ आपको थोड़ी अलग त्रुटि मिलेगी)

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

एक स्थिर विधि एक वर्ग विधि के समान है, लेकिन एक स्वचालित पैरामीटर के रूप में वर्ग ऑब्जेक्ट नहीं मिलेगा। यह @staticmethodडेकोरेटर का उपयोग करके बनाया गया है ।

class Foo(object):
    @staticmethod
    def hello(cls):
        print("hello from %s" % cls.__name__)

Foo.hello()
-> TypeError: hello() missing 1 required positional argument: 'cls'

दस्तावेज़ीकरण लिंक

यहाँ प्रासंगिक python3 डॉक्यूमेंटटन के लिंक दिए गए हैं:

डाटा मॉडल प्रलेखन इस वर्ग के तरीकों और स्थिर विधियों के बीच अंतर के बारे में क्या कहना है:

स्टेटिक मेथड ऑब्जेक्ट्स स्टैटिक मेथड ऑब्जेक्ट्स ऊपर वर्णित विधि ऑब्जेक्ट्स में फ़ंक्शन ऑब्जेक्ट्स के परिवर्तन को पराजित करने का एक तरीका प्रदान करते हैं। एक स्थिर विधि ऑब्जेक्ट किसी भी अन्य ऑब्जेक्ट के आसपास एक आवरण है, आमतौर पर उपयोगकर्ता-परिभाषित विधि ऑब्जेक्ट है। जब एक स्थिर विधि ऑब्जेक्ट को एक वर्ग या एक वर्ग उदाहरण से पुनर्प्राप्त किया जाता है, तो वास्तव में लौटी वस्तु लपेटी गई वस्तु है, जो किसी भी अन्य परिवर्तन के अधीन नहीं है। स्थैतिक विधि ऑब्जेक्ट्स स्वयं कॉल करने योग्य नहीं होते हैं, हालांकि वे जिन वस्तुओं को लपेटते हैं वे आमतौर पर होते हैं। स्टैटिक विधि ऑब्जेक्ट्स बिल्ट-इन staticmethod () कंस्ट्रक्टर द्वारा बनाए जाते हैं।

क्लास मेथड ऑब्जेक्ट एक क्लास मेथड ऑब्जेक्ट, स्टैटिक मेथड ऑब्जेक्ट की तरह, एक अन्य ऑब्जेक्ट के चारों ओर एक आवरण होता है, जो क्लास और क्लास इंस्टेंसेस से जिस तरह से ऑब्जेक्ट को पुनः प्राप्त करता है, उस तरह से बदल देता है। इस तरह की पुनर्प्राप्ति पर वर्ग पद्धति की वस्तुओं का व्यवहार "उपयोगकर्ता द्वारा परिभाषित विधियों" के तहत ऊपर वर्णित है। क्लास मेथड ऑब्जेक्ट्स बिल्ट-इन क्लासमेथोड () कंस्ट्रक्टर द्वारा बनाए जाते हैं।

संबंधित सवाल


4
@LightnessRacesinOrbit: मुझे नहीं लगता कि विशेष रूप से अक्सर अजगर में स्थिर तरीकों का उपयोग किया जाता है। एक यादृच्छिक नमूने के रूप में अपने सिस्टम का उपयोग करते हुए, जब मैं अपने द्वारा स्थापित सभी पैकेजों के माध्यम से खोज करता हूं, तो सभी विधियों का केवल 1% स्थिर तरीके हैं (जो स्पष्ट रूप से मेरी अपेक्षा से अधिक था)।
ब्रायन ओकले

1
"स्टेटिक तरीके" आमतौर पर एक कोड गंध होते हैं, और उदाहरण के लिए गोगोल पायथन शैली गाइड द्वारा हतोत्साहित किए जाते हैं।
9000

3
मुझे लगता है कि उत्तर बेहतर होगा यदि यह उपवर्गों पर ध्यान आकर्षित करता है, जहां क्लासमेथोड्स को कुछ उपयोगिता मिलती है।
विंस्टन इर्वर्ट

1
@ user2357112: मैंने बस के सभी उदाहरणों को "^ def("गिना, फिर सभी उदाहरणों को गिना @staticmethod। बहुत अवैज्ञानिक, लेकिन शायद बॉलपार्क के भीतर था।
ब्रायन ओकले

2
@ कश्यप: टीएल; डीआर पहले पैराग्राफ पर लागू होता है। मुझे लगता है कि यह नीचे की तुलना में शीर्ष पर बेहतर काम करता है।
ब्रायन ओकले

8

पायथन में "क्लास मेथड्स" और "इंस्टेंस मेथड्स" क्या हैं?

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

  • एक "क्लास मेथड" वर्ग के बारे में जानकारी का उपयोग करता है (और उस वर्ग का उदाहरण नहीं) यह प्रभावित करता है कि वे क्या करते हैं (वे आमतौर पर वैकल्पिक निर्माणकर्ताओं के रूप में नए उदाहरण बनाने के लिए उपयोग किए जाते हैं, और इस तरह अविश्वसनीय रूप से सामान्य नहीं हैं)।

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

एक्स का एक समारोह

गणित वर्ग याद रखें, "y x का एक कार्य है f(x)?" कि कोड में लागू करते हैं:

y = function(x)

ऊपर से आरोपित यह है कि जब से xपरिवर्तन हो सकता है, yतब बदल सकता है x। यह तब है जब हम कहते हैं कि " yका एक कार्य है x"

क्या होगा yहो जब zहै 1? 2? 'FooBarBaz'?

yएक फ़ंक्शन नहीं है z, इसलिए zकुछ भी हो सकता है और फ़ंक्शन के परिणाम को प्रभावित नहीं करता है मान लें कि हमारा functionशुद्ध कार्य है। (यदि यह zएक वैश्विक चर के रूप में पहुंचता है , तो यह एक शुद्ध कार्य नहीं है - यह वही है जो कार्यात्मक शुद्धता से है।)

उपरोक्त विवरणों को पढ़ते हुए उपरोक्त बातों को ध्यान में रखें:

उदाहरण के तरीके

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

एक उदाहरण विधि का एक अंतर्निहित उदाहरण str.lower है:

>>> 'ABC'.lower()
'abc'

str.lower इसे स्ट्रिंग की आवृत्ति पर कहा जाता है, और यह उदाहरण में निहित जानकारी का उपयोग करता है कि किस नए स्ट्रिंग को वापस करने के लिए।

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

याद रखें, पायथन में, सब कुछ एक वस्तु है। इसका मतलब है कि कक्षा एक वस्तु है, और इसे एक फ़ंक्शन के तर्क के रूप में पारित किया जा सकता है।

एक वर्ग विधि एक समारोह है कि एक समारोह है की क्लास । यह वर्ग को एक तर्क के रूप में स्वीकार करता है।

एक अंतर्निहित उदाहरण है dict.fromkeys:

>>> dict.fromkeys('ABC')
{'C': None, 'B': None, 'A': None}

फ़ंक्शन स्पष्ट रूप से अपने स्वयं के वर्ग को जानता है, फ़ंक्शन फ़ंक्शन के आउटपुट को प्रभावित करने के लिए फ़ंक्शन वर्ग का उपयोग करता है, और यह पुनरावृत्ति से उस वर्ग का एक नया बनाता है। जब कोई समान विधि का उपयोग करता है, तब एक आदेश प्रदर्शित करता है:

>>> from collections import OrderedDict
>>> OrderedDict.fromkeys('ABC')
OrderedDict([('A', None), ('B', None), ('C', None)])

कक्षा पद्धति किस प्रकार की कक्षा (और उस कक्षा का उदाहरण नहीं) के बारे में जानकारी का उपयोग करती है ताकि किस प्रकार के वर्ग को वापस लौटाया जा सके।

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

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

एक स्थिर विधि न तो वर्ग और न ही वस्तु का एक कार्य है।

एक स्थिर विधि का एक अंतर्निहित उदाहरण पायथन 3 से str.maketrans है।

>>> str.maketrans('abc', 'bca')
{97: 98, 98: 99, 99: 97}

कुछ तर्कों को देखते हुए, यह एक ऐसा शब्दकोश बनाता है जो अपने वर्ग का कार्य नहीं है।

यह सुविधाजनक है क्योंकि strयह हमेशा वैश्विक नामस्थान में उपलब्ध है, इसलिए आप इसे आसानी से अनुवाद फ़ंक्शन के साथ उपयोग कर सकते हैं:

>>> 'abracadabra'.translate(str.maketrans('abc', 'bca'))
'bcrbabdbcrb'

पायथन 2 में, आपको इसे stringमॉड्यूल से एक्सेस करना होगा :

>>> 'abracadabra'.translate(str.maketrans('abc', 'bca'))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: type object 'str' has no attribute 'maketrans'
>>> import string
>>> 'abracadabra'.translate(string.maketrans('abc', 'bca'))
'bcrbabdbcrb'

उदाहरण

class AClass(object):
    """In Python, a class may have several types of methods: 
    instance methods, class methods, and static methods
    """

    def an_instance_method(self, x, y, z=None):
        """this is a function of the instance of the object
        self is the object's instance
        """
        return self.a_class_method(x, y)

    @classmethod
    def a_class_method(cls, x, y, z=None):
        """this is a function of the class of the object
        cls is the object's class
        """
        return cls.a_static_method(x, y, z=z)

    @staticmethod
    def a_static_method(x, y, z=None):
        """this is neither a function of the instance or class to 
        which it is attached
        """
        return x, y, z

आइए झटपट करें:

>>> instance = AClass()

अब उदाहरण सभी तरीकों को कॉल कर सकता है:

>>> instance.an_instance_method('x', 'y')
('x', 'y', None)
>>> instance.a_static_method('x', 'y')
('x', 'y', None)
>>> instance.a_class_method('x', 'y')
('x', 'y', None)

लेकिन वर्ग आमतौर पर उदाहरण विधि को कॉल करने के लिए अभिप्रेत नहीं है, हालांकि यह दूसरों को कॉल करने की उम्मीद है:

>>> AClass.a_class_method('x', 'y')
('x', 'y', None)
>>> AClass.a_static_method('x', 'y')
('x', 'y', None)
>>> AClass.an_instance_method('x', 'y')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: an_instance_method() missing 1 required positional argument: 'y'

आपको उदाहरण विधि को कॉल करने के लिए स्पष्ट रूप से उदाहरण पास करना होगा:

>>> AClass.an_instance_method(instance, 'x', 'y')
('x', 'y', None)

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

@LightnessRacesinOrbit मैंने प्रत्येक बिंदु पर विस्तृत किया है
हारून हॉल

व्यक्तिगत रूप से, मैंने हमेशा जिस तरह से देखा है वह यह है कि एक इंस्टेंस विधि एक विशेष उदाहरण पर एक ऑपरेशन है, एक क्लास विधि एक प्रकार का कंस्ट्रक्टर है (सुविधा के लिए, MyClass(1,2,3)इसके अलावा MyClass.get_special(1,2,3)और कुछ नहीं, जैसे ), और एक स्थिर तरीका है एक सामान्य कार्य है जो वैसे भी अकेला खड़ा हो सकता है।
Zizouz212 22

हां, क्लासमेथोड्स आमतौर पर वैकल्पिक कंस्ट्रक्टरों के लिए उपयोग किए जाते हैं (ऊपर मेरा तानाशाही उदाहरण देखें। pandas.DataFrame स्रोत कोड भी देखें), लेकिन यह एक परिभाषित विशेषता नहीं है। मुझे कभी-कभी केवल एक विधि से वर्ग स्तर पर संग्रहीत डेटा तक पहुंचने की आवश्यकता होती है, उदाहरण के बिना। यदि आप टाइप कर रहे हैं (स्व) (या इससे भी बदतर, स्वयं .__ class__) और अन्यथा स्वयं को सीधे इंस्टेंस विधि में उपयोग नहीं कर रहे हैं, तो यह एक अच्छा संकेत है कि आपको इसे एक क्लासमेथोड मानना ​​चाहिए। जैसा कि क्लासमैथोड्स को उदाहरणों की आवश्यकता नहीं होती है, इससे उन्हें एकजुट होना आसान हो जाता है।
आरोन हॉल

4
  • एक "इंस्टेंस विधि" एक ऐसी विधि है जो इंस्टेंस ऑब्जेक्ट को इसके पहले पैरामीटर के रूप में पास करती है, जिसे कन्वेंशन कहा जाता है self। यह डिफ़ॉल्ट है।

  • एक "स्थिर विधि" प्रारंभिक selfपैरामीटर के बिना एक विधि है । इसे @staticmethod डेकोरेटर के साथ लागू किया गया है

  • एक "क्लास मेथड" एक ऐसी विधि है जहाँ प्रारंभिक पैरामीटर एक उदाहरण ऑब्जेक्ट नहीं है, लेकिन क्लास ऑब्जेक्ट ( "क्लास ऑब्जेक्ट" के लिए पायथन डॉक्स का यह हिस्सा देखें ), जिसे कन्वेंशन कहा जाता है cls। यह @classmethod डेकोरेटर के साथ लागू किया गया है

C / C ++ / etc में "स्टैटिक मेथड" शब्द का विशिष्ट उपयोग पायथन "स्टैटिक" और पाइथन "क्लास" दोनों तरीकों पर लागू होता है, क्योंकि उन दोनों प्रकार के तरीकों का उदाहरण के संदर्भ में अभाव है। C / C ++ / etc में, विधियों में सामान्य रूप से कक्षा के सभी गैर-आवृत्ति सदस्यों / विधियों तक अंतर्निहित पहुंच होती है, यही वजह है कि शायद यह अंतर केवल पायथन / रूबी / आदि जैसी भाषाओं में मौजूद है।


क्या C / C ++ में एक स्थिर विधि में क्लास ऑब्जेक्ट का संदर्भ है? या सिर्फ कक्षा के "सदस्य"? क्या वे कक्षा के नए सदस्य बना सकते हैं? :)
हारून हॉल

3
@AaronHall C / C ++ में, क्लास ऑब्जेक्ट जैसी कोई चीज नहीं है, और स्टैटिक मेथड्स को कॉल करने के लिए आपको इसके संदर्भ की आवश्यकता नहीं है। आप बस लिखते हैं Class::staticMethod()और यह वह है (जब तक कि आप इसे staticMethod()निजी या कुछ और कहने से मना नहीं करते हैं )।
Ixrec
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.