जवाबों:
हां, स्टेटिकमिथोड डेकोरेटर का उपयोग करना
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 में परिवर्तित: फ़ंक्शन डेकोरेटर सिंटैक्स जोड़ा गया।
ClassName.methodName()
, जैसे कि यह एक स्थिर था, और फिर self
विधि को प्रदान नहीं किया जाएगा। जैसा कि आपने कहा, इस पद्धति को भी कॉल करना संभव होगा ClassInstance.methodName()
, और self
इसके नाम के बिना, पहले पैरामीटर के रूप में प्रदान किया जाएगा।
मुझे लगता है कि स्टीवन वास्तव में सही है । मूल प्रश्न का उत्तर देने के लिए, फिर, क्लास विधि सेट करने के लिए, बस मान लें कि पहला तर्क कॉलिंग इंस्टेंस नहीं है, और फिर सुनिश्चित करें कि आप केवल क्लास से विधि को कॉल करते हैं।
(ध्यान दें कि यह उत्तर 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)
TypeError: unbound method rollCall() must be called with Dog instance as first argument (got int instance instead)
T.my_static_method()
या type(my_t_instance).my_static_method()
, क्योंकि यह स्पष्ट है और यह तुरंत स्पष्ट कर देता है कि मैं एक स्थिर विधि कह रहा हूं।
हाँ, स्टेटमिथोड डेकोरेटर की जाँच करें :
>>> class C:
... @staticmethod
... def hello():
... print "Hello World"
...
>>> C.hello()
Hello World
आपको वास्तव में @staticmethod
डेकोरेटर का उपयोग करने की आवश्यकता नहीं है । बस एक विधि की घोषणा (जो स्वयं पैरामीटर की उम्मीद नहीं करता है) और इसे कक्षा से कॉल करें। डेकोरेटर केवल उसी स्थिति में होता है, जब आप उसे एक उदाहरण से कॉल करना चाहते हैं (जो आप करना नहीं चाहते थे)
अधिकतर, आप केवल कार्यों का उपयोग करते हैं, हालांकि ...
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 () होना चाहिए डमी उदाहरण के साथ पहले तर्क के रूप में कहा जाता है (इसके बजाय कुछ भी नहीं मिला)
self
पहले तर्क के रूप में पारित करेगा जब तक कि आप इसे नहीं बताते हैं। (देखें: डेकोरेटर)
self
कैसे कहा जाता है के आधार पर एक रेफरल उचित रूप से सम्मिलित करेगा । टेस्ट मामला: pastebin.com/12DDV7DB ।
staticmethod
डेकोरेटर एक दोनों वर्ग और एक उदाहरण (इस समाधान में विफल रहता है जब एक उदाहरण पर फ़ंक्शन को कॉल) पर समारोह कॉल करने के लिए अनुमति देता है।
class C: def callme(): print('called'); C.callme()
पायथन में स्थैतिक तरीके?
क्या पायथन में स्थैतिक विधियां होना संभव है, इसलिए मैं उन्हें एक वर्ग को शुरू किए बिना कॉल कर सकता हूं, जैसे:
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'])
स्थैतिक विधि वस्तुओं के व्यवहार की विशिष्टताओं के अलावा , एक निश्चित प्रकार की सुंदरता है, जो आपके मॉड्यूल-स्तरीय कोड को व्यवस्थित करने की बात आती है।
# 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
शायद सबसे सरल विकल्प उन कार्यों को कक्षा के बाहर रखना है:
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 डेकोरेटर का उपयोग कर सकते हैं ।
पायथन स्टैटिक विधियों को दो तरीकों से बनाया जा सकता है।
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
@Staticmethod का उपयोग करना
class Arithmetic:
# create add static method
@staticmethod
def add(x, y):
return x + y
print('Result:', Arithmetic.add(15, 10))
आउटपुट:
परिणाम: 25
मैं समय-समय पर इस सवाल का सामना करता हूं। उपयोग मामला और उदाहरण है कि मैं शौकीन हूं:
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 में सभी कार्य किसी न किसी तरह से जटिल संख्याओं पर कार्य करते हैं।
@staticmethod
सजावट जोड़ना या फ़ंक्शन पॉइंटर का उपयोग क्यों करना , जब आप बस पहलेself
पैरामीटर से बच सकते हैं ? खैर, एक वस्तु के लिएa
, आप नहीं कॉल करने के लिए सक्षम हो जाएगाa.your_static_method()
, जो अन्य भाषाओं में अनुमति दी है, लेकिन यह भी एक बुरा व्यवहार माना जाता है और संकलक हमेशा इसके बारे में चेतावनी दी है