पायथन में स्थैतिक तरीके?


1719

क्या पायथन में स्थिर तरीके होना संभव है जिसे मैं एक वर्ग को शुरू किए बिना कॉल कर सकता हूं, जैसे:

ClassName.static_method()

जवाबों:


2026

हां, स्टेटिकमिथोड डेकोरेटर का उपयोग करना

class MyClass(object):
    @staticmethod
    def the_static_method(x):
        print(x)

MyClass.the_static_method(2)  # outputs 2

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

class MyClass(object):
    def the_static_method(x):
        print(x)
    the_static_method = staticmethod(the_static_method)

MyClass.the_static_method(2)  # outputs 2

यह पूरी तरह से पहले उदाहरण (उपयोग @staticmethod) के समान है , बस अच्छा डेकोरेटर सिंटैक्स का उपयोग नहीं कर रहा है

अंत में, staticmethod()संयम से उपयोग करें ! ऐसी बहुत कम स्थितियाँ हैं जहाँ पायथन में स्थैतिक-विधियाँ आवश्यक हैं, और मैंने उन्हें कई बार इस्तेमाल किया है जहाँ एक अलग "टॉप-लेवल" फ़ंक्शन स्पष्ट होता।


निम्नलिखित प्रलेखन से शब्दशः है :

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

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

@Staticmethod फॉर्म एक फ़ंक्शन डेकोरेटर है - विवरण के लिए फ़ंक्शन परिभाषाओं में फ़ंक्शन परिभाषा का विवरण देखें।

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

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

स्थिर तरीकों के बारे में अधिक जानकारी के लिए, में मानक प्रकार पदानुक्रम के लिए दस्तावेज़ देखें मानक प्रकार पदानुक्रम

संस्करण 2.2 में नया।

संस्करण 2.4 में परिवर्तित: फ़ंक्शन डेकोरेटर सिंटैक्स जोड़ा गया।


15
@staticmethodसजावट जोड़ना या फ़ंक्शन पॉइंटर का उपयोग क्यों करना , जब आप बस पहले selfपैरामीटर से बच सकते हैं ? खैर, एक वस्तु के लिए a, आप नहीं कॉल करने के लिए सक्षम हो जाएगा a.your_static_method(), जो अन्य भाषाओं में अनुमति दी है, लेकिन यह भी एक बुरा व्यवहार माना जाता है और संकलक हमेशा इसके बारे में चेतावनी दी है
SomethingSomething

1
मैं python 2.7.12 का उपयोग कर रहा हूं, @staticmethod डेकोरेटर के साथ मैं पहले स्थिर विधि को परिभाषित करने में असमर्थ हूं। इसके दूँगा त्रुटि: लेखन त्रुटि: 'staticmethod' ऑब्जेक्ट प्रतिदेय नहीं है
Supratim Samantray

सुप्रतिम सामन्त्रे, क्या आप सुनिश्चित हैं? क्योंकि यहाँ यह स्पष्ट रूप से कहा गया है कि इसका उपयोग 2.4 के बाद किया जा सकता है।
realslimshanky

11
@SomethingSomething, यदि आप चर नाम "स्व" का उपयोग नहीं करते हैं, लेकिन डेकोरेटर को नहीं जोड़ते हैं, तो पहला तर्क जैसे arg1 अभी भी आत्म उदाहरण का संदर्भ होगा। स्वयं नाम केवल एक सम्मेलन है।
जॉर्ज मौट्सपौलोस

1
@GeorgeMoutsopoulos - आम तौर पर सहमत हैं। लेकिन - आप वैसे भी विधि को कॉल करने में सक्षम होंगे ClassName.methodName(), जैसे कि यह एक स्थिर था, और फिर selfविधि को प्रदान नहीं किया जाएगा। जैसा कि आपने कहा, इस पद्धति को भी कॉल करना संभव होगा ClassInstance.methodName(), और selfइसके नाम के बिना, पहले पैरामीटर के रूप में प्रदान किया जाएगा।
SomethingSomething

220

मुझे लगता है कि स्टीवन वास्तव में सही है । मूल प्रश्न का उत्तर देने के लिए, फिर, क्लास विधि सेट करने के लिए, बस मान लें कि पहला तर्क कॉलिंग इंस्टेंस नहीं है, और फिर सुनिश्चित करें कि आप केवल क्लास से विधि को कॉल करते हैं।

(ध्यान दें कि यह उत्तर Python 3.x को संदर्भित करता है। Python 2.x में आपको TypeErrorकक्षा में ही विधि को कॉल करने के लिए मिलेगा ।)

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

class Dog:
    count = 0 # this is a class variable
    dogs = [] # this is a class variable

    def __init__(self, name):
        self.name = name #self.name is an instance variable
        Dog.count += 1
        Dog.dogs.append(name)

    def bark(self, n): # this is an instance method
        print("{} says: {}".format(self.name, "woof! " * n))

    def rollCall(n): #this is implicitly a class method (see comments below)
        print("There are {} dogs.".format(Dog.count))
        if n >= len(Dog.dogs) or n < 0:
            print("They are:")
            for dog in Dog.dogs:
                print("  {}".format(dog))
        else:
            print("The dog indexed at {} is {}.".format(n, Dog.dogs[n]))

fido = Dog("Fido")
fido.bark(3)
Dog.rollCall(-1)
rex = Dog("Rex")
Dog.rollCall(0)

इस कोड में, "रोलकॉल" विधि मानती है कि पहला तर्क एक उदाहरण नहीं है (जैसा कि यह होगा यदि इसे एक वर्ग के बजाय एक उदाहरण द्वारा कहा जाता है)। जब तक "रोलकॉल" को एक उदाहरण के बजाय कक्षा से बुलाया जाता है, कोड ठीक काम करेगा। यदि हम एक उदाहरण से "रोल कॉल" को कॉल करने का प्रयास करते हैं, जैसे:

rex.rollCall(-1)

हालाँकि, यह एक अपवाद का कारण होगा क्योंकि यह दो तर्क भेजेगा: स्वयं और -1, और "रोलकॉल" केवल एक तर्क को स्वीकार करने के लिए परिभाषित किया गया है।

संयोग से, rex.rollCall () सही संख्या में तर्क भेजेगा, लेकिन एक अपवाद को भी जन्म देगा क्योंकि अब n एक डॉग उदाहरण (यानी, रेक्स) का प्रतिनिधित्व करेगा जब फ़ंक्शन को संख्यात्मक होने की उम्मीद है।

यह वह जगह है जहाँ सजावट आती है: अगर हम "रोलकॉल" विधि को पसंद करते हैं

@staticmethod

फिर, स्पष्ट रूप से यह कहते हुए कि विधि स्थिर है, हम इसे एक उदाहरण से भी कॉल कर सकते हैं। अभी,

rex.rollCall(-1)

काम करेगा। एक विधि परिभाषा से पहले @staticmethod का सम्मिलन, तब एक उदाहरण को तर्क के रूप में भेजने से रोकता है।

आप निम्न कोड की कोशिश करके और @staticmethod लाइन के बिना टिप्पणी करके यह सत्यापित कर सकते हैं।

class Dog:
    count = 0 # this is a class variable
    dogs = [] # this is a class variable

    def __init__(self, name):
        self.name = name #self.name is an instance variable
        Dog.count += 1
        Dog.dogs.append(name)

    def bark(self, n): # this is an instance method
        print("{} says: {}".format(self.name, "woof! " * n))

    @staticmethod
    def rollCall(n):
        print("There are {} dogs.".format(Dog.count))
        if n >= len(Dog.dogs) or n < 0:
            print("They are:")
            for dog in Dog.dogs:
                print("  {}".format(dog))
        else:
            print("The dog indexed at {} is {}.".format(n, Dog.dogs[n]))


fido = Dog("Fido")
fido.bark(3)
Dog.rollCall(-1)
rex = Dog("Rex")
Dog.rollCall(0)
rex.rollCall(-1)

8
पहला उदाहरण (@staticmethod के बिना कक्षा में कॉल करना) पायथन 2.7 पर मेरे लिए काम नहीं करता है। मुझे "TypeError: अनबाउंड मेथड रोल () को पहले उदाहरण के रूप में डॉग उदाहरण के साथ बुलाया जाना चाहिए (इसके बजाय int
इंस्टेंट

2
यह काम नहीं करता। दोनों Dog.rollCall (-1) और rex.rollCall (-1) एक ही वापसीTypeError: unbound method rollCall() must be called with Dog instance as first argument (got int instance instead)
Mittenchops

3
@MestreLion मुझे लगता है कि यह एक बहुत बड़ा लाभ नहीं है, क्योंकि यह सब स्थैतिक और उदाहरण के तरीकों में गड़बड़ी करता है और एक दूसरे की तरह दिखता है। यदि आप जानते हैं कि एक विधि स्थिर है, तो आपको इसे एक स्थिर विधि के रूप में उपयोग करना चाहिए। तथ्य यह है कि विधि की जरूरत नहीं है या अपने उदाहरण का उपयोग करने के लिए स्व-स्पष्ट होना चाहिए जहाँ भी आप विधि का उपयोग करते हैं। मैं हमेशा उपयोग करता हूं T.my_static_method()या type(my_t_instance).my_static_method(), क्योंकि यह स्पष्ट है और यह तुरंत स्पष्ट कर देता है कि मैं एक स्थिर विधि कह रहा हूं।
असद सईदुद्दीन


54

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

अधिकतर, आप केवल कार्यों का उपयोग करते हैं, हालांकि ...


यह अजगर 2.5.2 class Dummy: def static1(): print "hello from static1" @staticmethod def static2(): print "hello from static2" Dummy.static2() Dummy.static1() आउटपुट के लिए काम नहीं करेगा : static2 ट्रैसबैक से हैलो <सबसे हाल ही में कॉल>: फ़ाइल "ll.py", पंक्ति 46, में <मॉड्यूल> Dummy.static1 () TypeError: अनबाउंड 1 static1 () होना चाहिए डमी उदाहरण के साथ पहले तर्क के रूप में कहा जाता है (इसके बजाय कुछ भी नहीं मिला)
महोरी

7
यह एक वर्ग के अंदर काम नहीं करता है। पायथन selfपहले तर्क के रूप में पारित करेगा जब तक कि आप इसे नहीं बताते हैं। (देखें: डेकोरेटर)
नवीं

9
वास्तव में यह 2.7 में गलत है और 3.X के रूप में कानूनी है (3.2 में परीक्षण ठीक है)। यही कारण है कि आप 2.7 और नीचे @staticmethod डेकोरेटर के बिना एक वर्ग के संदर्भ से एक विधि नहीं कह सकते । 3.2 में यह काम करता है और यह selfकैसे कहा जाता है के आधार पर एक रेफरल उचित रूप से सम्मिलित करेगा । टेस्ट मामला: pastebin.com/12DDV7DB
स्पिंकस

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

एक विधि को डॉट नोटेशन का उपयोग करके ऑब्जेक्ट के किसी अन्य विशेषता की तरह कहा जा सकता है। class C: def callme(): print('called'); C.callme()
पूय

32

पायथन में स्थैतिक तरीके?

क्या पायथन में स्थैतिक विधियां होना संभव है, इसलिए मैं उन्हें एक वर्ग को शुरू किए बिना कॉल कर सकता हूं, जैसे:

ClassName.StaticMethod()

हां, स्टैटिक तरीके इस तरह बनाए जा सकते हैं (हालाँकि कैमलकेस के बजाय अंडरस्कोर का इस्तेमाल करना थोड़ा अधिक पाइथोनिक है)

class ClassName(object):

    @staticmethod
    def static_method(kwarg1=None):
        '''return a value that is a function of kwarg1'''

ऊपर डेकोरेटर सिंटैक्स का उपयोग करता है। यह वाक्य रचना के बराबर है

class ClassName(object):

    def static_method(kwarg1=None):
        '''return a value that is a function of kwarg1'''

    static_method = staticmethod(static_method)

यह वर्णित के रूप में इस्तेमाल किया जा सकता है:

ClassName.static_method()

स्थैतिक विधि का एक अंतर्निहित उदाहरण str.maketrans()पायथन 3 में है, जो stringपायथन 2 में मॉड्यूल में एक फ़ंक्शन था ।


एक अन्य विकल्प जो आपके द्वारा वर्णित के रूप में इस्तेमाल किया जा सकता है classmethod, अंतर यह है कि क्लासमेथोड को एक अंतर्निहित प्रथम तर्क के रूप में वर्ग मिलता है, और यदि उप-वर्गित होता है, तो इसे उप-रूप में निहित पहले तर्क के रूप में प्राप्त होता है।

class ClassName(object):

    @classmethod
    def class_method(cls, kwarg1=None):
        '''return a value that is a function of the class and kwarg1'''

ध्यान दें कि clsपहले तर्क के लिए एक आवश्यक नाम नहीं है, लेकिन सबसे अनुभवी पायथन कोडर्स इसे बुरी तरह से विचार करेंगे यदि आप किसी और चीज का उपयोग करते हैं।

ये आमतौर पर वैकल्पिक कंस्ट्रक्टर के रूप में उपयोग किए जाते हैं।

new_instance = ClassName.class_method()

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

new_dict = dict.fromkeys(['key1', 'key2'])

11

स्थैतिक विधि वस्तुओं के व्यवहार की विशिष्टताओं के अलावा , एक निश्चित प्रकार की सुंदरता है, जो आपके मॉड्यूल-स्तरीय कोड को व्यवस्थित करने की बात आती है।

# garden.py
def trim(a):
    pass

def strip(a):
    pass

def bunch(a, b):
    pass

def _foo(foo):
    pass

class powertools(object):
    """
    Provides much regarded gardening power tools.
    """
    @staticmethod
    def answer_to_the_ultimate_question_of_life_the_universe_and_everything():
        return 42

    @staticmethod
    def random():
        return 13

    @staticmethod
    def promise():
        return True

def _bar(baz, quux):
    pass

class _Dice(object):
    pass

class _6d(_Dice):
    pass

class _12d(_Dice):
    pass

class _Smarter:
    pass

class _MagicalPonies:
    pass

class _Samurai:
    pass

class Foo(_6d, _Samurai):
    pass

class Bar(_12d, _Smarter, _MagicalPonies):
    pass

...

# tests.py
import unittest
import garden

class GardenTests(unittest.TestCase):
    pass

class PowertoolsTests(unittest.TestCase):
    pass

class FooTests(unittest.TestCase):
    pass

class BarTests(unittest.TestCase):
    pass

...

# interactive.py
from garden import trim, bunch, Foo

f = trim(Foo())
bunch(f, Foo())

...

# my_garden.py
import garden
from garden import powertools

class _Cowboy(garden._Samurai):
    def hit():
        return powertools.promise() and powertools.random() or 0

class Foo(_Cowboy, garden.Foo):
    pass

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

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

# utils.py
class socket(object):
    @staticmethod
    def check_if_port_available(port):
        pass

    @staticmethod
    def get_free_port(port)
        pass

class image(object):
    @staticmethod
    def to_rgb(image):
        pass

    @staticmethod
    def to_cmyk(image):
        pass

10

शायद सबसे सरल विकल्प उन कार्यों को कक्षा के बाहर रखना है:

class Dog(object):
    def __init__(self, name):
        self.name = name

    def bark(self):
        if self.name == "Doggy":
            return barking_sound()
        else:
            return "yip yip"

def barking_sound():
    return "woof woof"

इस पद्धति का उपयोग करते हुए, आंतरिक ऑब्जेक्ट स्थिति (साइड इफेक्ट्स) को संशोधित करने या उपयोग करने वाले कार्यों को कक्षा में रखा जा सकता है, और पुन: प्रयोज्य उपयोगिता कार्यों को बाहर ले जाया जा सकता है।

मान लीजिए कि यह फ़ाइल कहा जाता है dogs.py। इनका उपयोग करने के लिए, आप dogs.barking_sound()इसके बजाय कॉल करेंगे dogs.Dog.barking_sound

यदि आपको कक्षा का हिस्सा बनने के लिए वास्तव में एक स्थिर विधि की आवश्यकता है, तो आप staticmethod डेकोरेटर का उपयोग कर सकते हैं ।


1

तो, स्थैतिक विधियाँ वे विधियाँ हैं जिन्हें किसी वर्ग की वस्तु बनाए बिना कहा जा सकता है। उदाहरण के लिए :-

    @staticmethod
    def add(a, b):
        return a + b

b = A.add(12,12)
print b

उपरोक्त उदाहरण विधि addमें वर्ग नाम से बुलाया जाता है Aन कि वस्तु नाम से।


-3

पायथन स्टैटिक विधियों को दो तरीकों से बनाया जा सकता है।

  1. Staticmethod () का उपयोग करना

    class Arithmetic:
        def add(x, y):
            return x + y
    # create add static method
    Arithmetic.add = staticmethod(Arithmetic.add)
    
    print('Result:', Arithmetic.add(15, 10))

आउटपुट:

परिणाम: 25

  1. @Staticmethod का उपयोग करना

    class Arithmetic:
    
    # create add static method
    @staticmethod
    def add(x, y):
        return x + y
    
    print('Result:', Arithmetic.add(15, 10))

आउटपुट:

परिणाम: 25


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

-4

मैं समय-समय पर इस सवाल का सामना करता हूं। उपयोग मामला और उदाहरण है कि मैं शौकीन हूं:

jeffs@jeffs-desktop:/home/jeffs  $ python36
Python 3.6.1 (default, Sep  7 2017, 16:36:03) 
[GCC 6.3.0 20170406] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import cmath
>>> print(cmath.sqrt(-4))
2j
>>>
>>> dir(cmath)
['__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atanh', 'cos', 'cosh', 'e', 'exp', 'inf', 'infj', 'isclose', 'isfinite', 'isinf', 'isnan', 'log', 'log10', 'nan', 'nanj', 'phase', 'pi', 'polar', 'rect', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'tau']
>>> 

वर्ग cmath का ऑब्जेक्ट बनाने का कोई मतलब नहीं है, क्योंकि cmath ऑब्जेक्ट में कोई स्थिति नहीं है। हालाँकि, cmath तरीकों का एक संग्रह है जो सभी किसी न किसी तरह से संबंधित हैं। ऊपर मेरे उदाहरण में, cmath में सभी कार्य किसी न किसी तरह से जटिल संख्याओं पर कार्य करते हैं।


आपने प्रश्न का उत्तर नहीं दिया, लेकिन आपने इसके बजाय एक उदाहरण दिया।
ज़िकुआन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.