पायथन @property: इसका उपयोग कैसे करें और क्यों? - प्रोग्रामिज़

इस ट्यूटोरियल में, आप पायथन @property डेकोरेटर के बारे में जानेंगे; ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग में गेटर्स और सेटर का उपयोग करने के लिए एक पायथोनिक तरीका।

पायथन प्रोग्रामिंग हमें एक बिल्ट-इन @propertyडेकोरेटर प्रदान करता है जो कि गेट्टर का उपयोग करता है और ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग में बहुत आसान बनाता है।

@propertyडेकोरेटर क्या है, इस बारे में विस्तार से जाने से पहले , आइए हम पहले एक अंतर्ज्ञान का निर्माण करें कि इसे पहली जगह की आवश्यकता क्यों होगी।

बिना गेटर्स और सेटर्स के क्लास

आइए मान लें कि हम एक ऐसा वर्ग बनाने का निर्णय लेते हैं जो तापमान को डिग्री सेल्सियस में संग्रहीत करता है। यह तापमान को डिग्री फ़ारेनहाइट में बदलने के लिए एक विधि भी लागू करेगा। इसे करने का एक तरीका इस प्रकार है:

 class Celsius: def __init__(self, temperature = 0): self.temperature = temperature def to_fahrenheit(self): return (self.temperature * 1.8) + 32

हम वस्तुओं को इस वर्ग से बाहर कर सकते हैं और अपनी temperatureइच्छानुसार विशेषता में फेरबदल कर सकते हैं:

 # Basic method of setting and getting attributes in Python class Celsius: def __init__(self, temperature=0): self.temperature = temperature def to_fahrenheit(self): return (self.temperature * 1.8) + 32 # Create a new object human = Celsius() # Set the temperature human.temperature = 37 # Get the temperature attribute print(human.temperature) # Get the to_fahrenheit method print(human.to_fahrenheit())

आउटपुट

 37 98.60000000000001

फ़ारेनहाइट में परिवर्तित होने पर अतिरिक्त दशमलव स्थान फ़्लोटिंग अंक अंकगणितीय त्रुटि के कारण होता है। अधिक जानने के लिए, Python Floating Point Arithmetic Error पर जाएँ।

जब भी हम temperatureऊपर दिखाए गए अनुसार किसी ऑब्जेक्ट विशेषता को असाइन या पुनर्प्राप्त करते हैं , तो पायथन ऑब्जेक्ट के अंतर्निहित __dict__शब्दकोश विशेषता में इसे खोजता है ।

 >>> human.__dict__ ('temperature': 37)

इसलिए, man.temperatureआंतरिक रूप से बन जाता है man.__dict__('temperature')

गेटर्स एंड सेटर्स का उपयोग करना

मान लीजिए कि हम ऊपर परिभाषित सेल्सियस वर्ग की उपयोगिता को बढ़ाना चाहते हैं। हम जानते हैं कि किसी भी वस्तु का तापमान -273.15 डिग्री सेल्सियस (थर्मोडायनामिक्स में निरपेक्ष शून्य) तक नहीं पहुँच सकता है

आइए इस मूल्य बाधा को लागू करने के लिए हमारे कोड को अपडेट करें।

उपरोक्त प्रतिबंध का एक स्पष्ट समाधान विशेषता को छिपाना temperature(इसे निजी बनाना) होगा और इसे हेरफेर करने के लिए नए गेटर और सेटर तरीकों को परिभाषित करना होगा। इसे इस प्रकार किया जा सकता है:

 # Making Getters and Setter methods class Celsius: def __init__(self, temperature=0): self.set_temperature(temperature) def to_fahrenheit(self): return (self.get_temperature() * 1.8) + 32 # getter method def get_temperature(self): return self._temperature # setter method def set_temperature(self, value): if value < -273.15: raise ValueError("Temperature below -273.15 is not possible.") self._temperature = value

जैसा कि हम देख सकते हैं, उपरोक्त विधि दो नए get_temperature()और set_temperature()तरीकों का परिचय देती है ।

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

अब, आइए इस कार्यान्वयन का उपयोग करें:

 # Making Getters and Setter methods class Celsius: def __init__(self, temperature=0): self.set_temperature(temperature) def to_fahrenheit(self): return (self.get_temperature() * 1.8) + 32 # getter method def get_temperature(self): return self._temperature # setter method def set_temperature(self, value): if value < -273.15: raise ValueError("Temperature below -273.15 is not possible.") self._temperature = value # Create a new object, set_temperature() internally called by __init__ human = Celsius(37) # Get the temperature attribute via a getter print(human.get_temperature()) # Get the to_fahrenheit method, get_temperature() called by the method itself print(human.to_fahrenheit()) # new constraint implementation human.set_temperature(-300) # Get the to_fahreheit method print(human.to_fahrenheit())

आउटपुट

 37 98.60000000000001 ट्रेसबैक (सबसे हालिया कॉल अंतिम): फाइल "", लाइन 30, फाइल में "", लाइन 16, सेट_टेंस वैल्यू में: -273.15 से नीचे तापमान संभव नहीं है।

इस अपडेट ने नए प्रतिबंध को सफलतापूर्वक लागू किया। अब हमें -273.15 डिग्री सेल्सियस से नीचे तापमान सेट करने की अनुमति नहीं है।

नोट : निजी चर वास्तव में अजगर में मौजूद नहीं हैं। बस नियमों का पालन किया जाना है। भाषा स्वयं कोई प्रतिबंध लागू नहीं करती है।

 >>> human._temperature = -300 >>> human.get_temperature() -300

हालांकि, उपरोक्त अद्यतन के साथ बड़ी समस्या यह है कि हमारे पिछले वर्ग को लागू करने वाले सभी कार्यक्रमों को अपने कोड obj.temperatureको obj.get_temperature()और से सभी अभिव्यक्तियों को संशोधित obj.temperature = valकरना होगा obj.set_temperature(val)

कोड के हजारों लाइनों के साथ काम करते समय यह रिफैक्टिंग समस्या पैदा कर सकता है।

कुल मिलाकर, हमारा नया अपडेट पीछे की ओर संगत नहीं था। यह वह जगह है जहाँ @propertyबचाव के लिए आता है।

संपत्ति वर्ग

उपरोक्त समस्या से निपटने के लिए एक पायथोनिक तरीका propertyवर्ग का उपयोग करना है । यहां बताया गया है कि हम अपना कोड कैसे अपडेट कर सकते हैं:

 # using property class class Celsius: def __init__(self, temperature=0): self.temperature = temperature def to_fahrenheit(self): return (self.temperature * 1.8) + 32 # getter def get_temperature(self): print("Getting value… ") return self._temperature # setter def set_temperature(self, value): print("Setting value… ") if value < -273.15: raise ValueError("Temperature below -273.15 is not possible") self._temperature = value # creating a property object temperature = property(get_temperature, set_temperature)

हमने एक print()फ़ंक्शन जोड़ा get_temperature()और set_temperature()स्पष्ट रूप से निरीक्षण किया कि उन्हें निष्पादित किया जा रहा है।

कोड की अंतिम पंक्ति एक संपत्ति वस्तु बनाती है temperature। सीधे शब्दों में कहें, संपत्ति सदस्य विशेषता एक्सेस ( ) में कुछ कोड ( get_temperatureऔर set_temperature) संलग्न करती है temperature

आइए इस अपडेट कोड का उपयोग करें:

 # using property class class Celsius: def __init__(self, temperature=0): self.temperature = temperature def to_fahrenheit(self): return (self.temperature * 1.8) + 32 # getter def get_temperature(self): print("Getting value… ") return self._temperature # setter def set_temperature(self, value): print("Setting value… ") if value < -273.15: raise ValueError("Temperature below -273.15 is not possible") self._temperature = value # creating a property object temperature = property(get_temperature, set_temperature) human = Celsius(37) print(human.temperature) print(human.to_fahrenheit()) human.temperature = -300

आउटपुट

 मान सेट करना… मूल्य प्राप्त करना… 37 मूल्य प्राप्त करना… 98.60000000000001 सेटिंग मूल्य… ट्रेसबैक (सबसे हालिया कॉल अंतिम): फ़ाइल "", पंक्ति 31, फ़ाइल में "", पंक्ति 18, सेट_टेंस वैल्यू में: -273 से नीचे तापमान संभव नहीं है

As we can see, any code that retrieves the value of temperature will automatically call get_temperature() instead of a dictionary (__dict__) look-up. Similarly, any code that assigns a value to temperature will automatically call set_temperature().

We can even see above that set_temperature() was called even when we created an object.

 >>> human = Celsius(37) Setting value… 

Can you guess why?

The reason is that when an object is created, the __init__() method gets called. This method has the line self.temperature = temperature. This expression automatically calls set_temperature().

Similarly, any access like c.temperature automatically calls get_temperature(). This is what property does. Here are a few more examples.

 >>> human.temperature Getting value 37 >>> human.temperature = 37 Setting value >>> c.to_fahrenheit() Getting value 98.60000000000001

By using property, we can see that no modification is required in the implementation of the value constraint. Thus, our implementation is backward compatible.

Note: The actual temperature value is stored in the private _temperature variable. The temperature attribute is a property object which provides an interface to this private variable.

The @property Decorator

In Python, property() is a built-in function that creates and returns a property object. The syntax of this function is:

 property(fget=None, fset=None, fdel=None, doc=None)

where,

  • fget is function to get value of the attribute
  • fset is function to set value of the attribute
  • fdel is function to delete the attribute
  • doc is a string (like a comment)

As seen from the implementation, these function arguments are optional. So, a property object can simply be created as follows.

 >>> property() 

A property object has three methods, getter(), setter(), and deleter() to specify fget, fset and fdel at a later point. This means, the line:

 temperature = property(get_temperature,set_temperature)

can be broken down as:

 # make empty property temperature = property() # assign fget temperature = temperature.getter(get_temperature) # assign fset temperature = temperature.setter(set_temperature)

कोड के ये दो टुकड़े बराबर हैं।

पायथन डेकोरेटर्स से परिचित प्रोग्रामर यह पहचान सकते हैं कि उपरोक्त निर्माण को डेकोरेटर्स के रूप में लागू किया जा सकता है।

हम नामों को परिभाषित भी नहीं कर सकते हैं get_temperatureऔर set_temperatureवे अनावश्यक हैं और वर्ग नाम स्थान को प्रदूषित करते हैं।

इसके लिए, हम temperatureअपने गेटटर और सेटर कार्यों को परिभाषित करते हुए नाम का पुन: उपयोग करते हैं। आइए देखें कि इसे एक डेकोरेटर के रूप में कैसे लागू किया जाए:

 # Using @property decorator class Celsius: def __init__(self, temperature=0): self.temperature = temperature def to_fahrenheit(self): return (self.temperature * 1.8) + 32 @property def temperature(self): print("Getting value… ") return self._temperature @temperature.setter def temperature(self, value): print("Setting value… ") if value < -273.15: raise ValueError("Temperature below -273 is not possible") self._temperature = value # create an object human = Celsius(37) print(human.temperature) print(human.to_fahrenheit()) coldest_thing = Celsius(-300)

आउटपुट

 मान सेट करना… मूल्य प्राप्त करना… 37 मूल्य प्राप्त करना… 98.60000000000001 सेटिंग मूल्य… Traceback (सबसे हाल का कॉल): फ़ाइल "", पंक्ति 29, फ़ाइल में "", पंक्ति 4, __init__ फ़ाइल में "", पंक्ति 18, तापमान में मान: -273 से नीचे तापमान संभव नहीं है

उपरोक्त कार्यान्वयन सरल और कुशल है। यह उपयोग करने के लिए अनुशंसित तरीका है property

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