पायथन में स्व

यदि आप कुछ समय के लिए पायथन (ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग) में प्रोग्रामिंग कर रहे हैं, तो आप निश्चित selfरूप से उन तरीकों के पार आ गए हैं जो उनके पहले पैरामीटर के रूप में हैं।

आइए पहले यह समझने की कोशिश करें कि यह आवर्ती स्व पैरामीटर क्या है।

पायथन में स्व क्या है?

ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग में, जब भी हम किसी वर्ग के लिए तरीकों को परिभाषित करते हैं, हम selfप्रत्येक मामले में पहले पैरामीटर के रूप में उपयोग करते हैं। आइए नामक एक वर्ग की परिभाषा को देखें Cat

 class Cat: def __init__(self, name, age): self.name = name self.age = age def info(self): print(f"I am a cat. My name is (self.name). I am (self.age) years old.") def make_sound(self): print("Meow")

इस मामले में, सहित सभी विधियों __init__में पहला पैरामीटर है self

हम जानते हैं कि वर्ग वस्तुओं के लिए एक खाका है। इस ब्लूप्रिंट का उपयोग कई संख्या में ऑब्जेक्ट बनाने के लिए किया जा सकता है। उपरोक्त वर्ग से दो अलग-अलग ऑब्जेक्ट बनाते हैं।

 cat1 = Cat('Andy', 2) cat2 = Cat('Phoebe', 3)

selfकीवर्ड किसी वर्ग का एक उदाहरण (वस्तु) का प्रतिनिधित्व करने के लिए किया जाता है। इस मामले में, दो Catवस्तुओं cat1और cat2उनके अपने nameऔर ageगुण हैं। यदि कोई आत्म तर्क नहीं था, तो एक ही वर्ग इन दोनों वस्तुओं की जानकारी नहीं रख सकता था।

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

स्वयं को स्पष्ट रूप से हर बार परिभाषित क्यों किया जाता है?

यहां तक ​​कि जब हम इसके उपयोग को समझते हैं self, तब भी यह अजीब लग सकता है, विशेष रूप से अन्य भाषाओं से आने वाले प्रोग्रामर के लिए, जो selfएक पैरामीटर के रूप में स्पष्ट रूप से हर बार जब हम एक विधि को परिभाषित करते हैं, तब पारित किया जाता है। जैसा कि द ज़ेन ऑफ पायथन जाता है, " स्पष्ट है कि निहितार्थ से बेहतर है "।

तो, हमें ऐसा करने की आवश्यकता क्यों है? आइए एक सरल उदाहरण लेते हैं जिसके साथ शुरू करते हैं। हमारे पास एक Pointवर्ग है जो distanceमूल से दूरी की गणना करने के लिए एक विधि को परिभाषित करता है ।

 class Point(object): def __init__(self,x = 0,y = 0): self.x = x self.y = y def distance(self): """Find distance from origin""" return (self.x**2 + self.y**2) ** 0.5

आइए अब हम इस वर्ग को तुरंत समझें और दूरी का पता लगाएं।

 >>> p1 = Point(6,8) >>> p1.distance() 10.0

उपरोक्त उदाहरण में, __init__()तीन मापदंडों को परिभाषित करता है लेकिन हमने सिर्फ दो (6 और 8) पारित किए हैं। इसी तरह distance()एक की आवश्यकता है लेकिन शून्य तर्क पारित किए गए थे। पायथन इस तर्क संख्या बेमेल के बारे में शिकायत क्यों नहीं कर रहा है?

आंतरिक रूप से क्या होता है?

Point.distanceऔर p1.distanceउपरोक्त उदाहरण अलग हैं और बिल्कुल समान नहीं हैं।

 >>> type(Point.distance) >>> type(p1.distance) 

हम देख सकते हैं कि पहला एक फंक्शन है और दूसरा एक मेथड है। तरीकों (पायथन में) के बारे में एक अजीब बात यह है कि वस्तु स्वयं इसी फ़ंक्शन के पहले तर्क के रूप में पारित हो जाती है।

उपरोक्त उदाहरण के मामले में, विधि कॉल p1.distance()वास्तव में इसके बराबर है Point.distance(p1)

आमतौर पर, जब हम कुछ तर्कों के साथ एक विधि कहते हैं, तो पहले तर्क के पहले विधि के ऑब्जेक्ट को रखकर संबंधित वर्ग फ़ंक्शन को कहा जाता है। तो, जैसे कुछ भी obj.meth(args)बन जाता है Class.meth(obj, args)। कॉलिंग प्रक्रिया स्वचालित है जबकि प्राप्त करने की प्रक्रिया (इसकी स्पष्ट) नहीं है।

यही कारण है कि कक्षा में किसी फ़ंक्शन का पहला पैरामीटर ऑब्जेक्ट ही होना चाहिए। इस पैरामीटर को लिखना selfकेवल एक सम्मेलन है। यह एक कीवर्ड नहीं है और इसका पायथन में कोई विशेष अर्थ नहीं है। हम अन्य नामों (जैसे this) का उपयोग कर सकते हैं लेकिन यह बहुत हतोत्साहित है। के अलावा अन्य नामों का उपयोग करना selfअधिकांश डेवलपर्स द्वारा परिलक्षित होता है और कोड की पठनीयता ( पठनीयता मायने रखता है ) को कम करता है।

सेल्फ कैन बी अवॉइड

अब तक आप स्पष्ट हैं कि ऑब्जेक्ट (उदाहरण) अपने आप पहले तर्क के रूप में पारित हो जाता है, स्वचालित रूप से। स्थैतिक विधि बनाते समय इस निहित व्यवहार से बचा जा सकता है । निम्नलिखित सरल उदाहरण पर विचार करें:

 class A(object): @staticmethod def stat_meth(): print("Look no self was passed")

यहाँ, @staticmethodएक फ़ंक्शन डेकोरेटर है जो stat_meth()स्थिर बनाता है । आइए हम इस क्लास को तुरंत करें और विधि को कॉल करें।

 >>> a = A() >>> a.stat_meth() Look no self was passed

उपरोक्त उदाहरण से, हम देख सकते हैं कि स्थैतिक विधि का उपयोग करते समय पहले तर्क के रूप में वस्तु को पारित करने के निहित व्यवहार से बचा गया था। सभी में, स्थैतिक तरीके सादे पुराने कार्यों की तरह व्यवहार करते हैं (क्योंकि एक वर्ग की सभी वस्तुएं स्थिर तरीकों को साझा करती हैं)।

 >>> type(A.stat_meth) >>> type(a.stat_meth) 

स्व यहाँ रहने के लिए है

स्पष्ट selfअजगर के लिए अद्वितीय नहीं है। यह विचार मोडुला -3 से उधार लिया गया था । निम्नलिखित उपयोग का मामला है जहां यह मददगार हो जाता है।

पायथन में कोई स्पष्ट परिवर्तनशील घोषणा नहीं है। वे पहले असाइनमेंट पर कार्रवाई करते हैं। के उपयोग selfबनाता है यह आसान उदाहरण विशेषताएं (और तरीकों) स्थानीय चर से के बीच अंतर करना।

पहले उदाहरण में, self.x एक उदाहरण विशेषता है जबकि x एक स्थानीय चर है। वे समान नहीं हैं और वे विभिन्न नामस्थानों में स्थित हैं।

कई लोगों ने स्वयं को पायथन में एक कीवर्ड बनाने का प्रस्ताव दिया है, जैसे thisC ++ और जावा में। यह selfविधियों में औपचारिक पैरामीटर सूची से स्पष्ट के अनावश्यक उपयोग को समाप्त करेगा ।

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

__init __ () कंस्ट्रक्टर नहीं है

एक महत्वपूर्ण निष्कर्ष जो अब तक की जानकारी से खींचा जा सकता है वह यह है कि __init__()विधि एक रचनाकार नहीं है। कई भोले-भाले पायथन प्रोग्रामर इससे भ्रमित __init__()हो जाते हैं क्योंकि जब हम ऑब्जेक्ट बनाते हैं तो उसे कॉल किया जाता है।

A closer inspection will reveal that the first parameter in __init__() is the object itself (object already exists). The function __init__() is called immediately after the object is created and is used to initialize it.

Technically speaking, a constructor is a method which creates the object itself. In Python, this method is __new__(). A common signature of this method is:

 __new__(cls, *args, **kwargs)

When __new__() is called, the class itself is passed as the first argument automatically(cls).

Again, like self, cls is just a naming convention. Furthermore, *args and **kwargs are used to take an arbitrary number of arguments during method calls in Python.

Some important things to remember when implementing __new__() are:

  • __new__() is always called before __init__().
  • First argument is the class itself which is passed implicitly.
  • Always return a valid object from __new__(). Not mandatory, but its main use is to create and return an object.

Let's take a look at an example:

 class Point(object): def __new__(cls,*args,**kwargs): print("From new") print(cls) print(args) print(kwargs) # create our object and return it obj = super().__new__(cls) return obj def __init__(self,x = 0,y = 0): print("From init") self.x = x self.y = y

Now, let's now instantiate it.

 >>> p2 = Point(3,4) From new (3, 4) () From init

This example illustrates that __new__() is called before __init__(). We can also see that the parameter cls in __new__() is the class itself (Point). Finally, the object is created by calling the __new__() method on object base class.

In Python, object is the base class from which all other classes are derived. In the above example, we have done this using super().

Use __new__ or __init__?

You might have seen __init__() very often but the use of __new__() is rare. This is because most of the time you don't need to override it. Generally, __init__() is used to initialize a newly created object while __new__() is used to control the way an object is created.

We can also use __new__() to initialize attributes of an object, but logically it should be inside __init__().

One practical use of __new__(), however, could be to restrict the number of objects created from a class.

Suppose we wanted a class SqPoint for creating instances to represent the four vertices of a square. We can inherit from our previous class Point (the second example in this article) and use __new__() to implement this restriction. Here is an example to restrict a class to have only four instances.

 class SqPoint(Point): MAX_Inst = 4 Inst_created = 0 def __new__(cls,*args,**kwargs): if (cls.Inst_created>= cls.MAX_Inst): raise ValueError("Cannot create more objects") cls.Inst_created += 1 return super().__new__(cls)

एक नमूना रन:

 >>> p1 = SqPoint(0,0) >>> p2 = SqPoint(1,0) >>> p3 = SqPoint(1,1) >>> p4 = SqPoint(0,1) >>> >>> p5 = SqPoint(2,2) Traceback (most recent call last):… ValueError: Cannot create more objects

दिलचस्प लेख...