गेटर्स और सेटर का उपयोग करने के लिए पायथोनिक तरीका क्या है?
"पायथोनिक" तरीका "गेटर्स" और "सेटलर्स" का उपयोग नहीं करना है, बल्कि सादे विशेषताओं का उपयोग करना है, जैसे प्रश्न प्रदर्शित करता है, और del
हटाने के लिए (लेकिन नाम निर्दोष ... बिल्डिंस की सुरक्षा के लिए बदल दिए जाते हैं):
value = 'something'
obj.attribute = value
value = obj.attribute
del obj.attribute
यदि बाद में, आप सेटिंग को बदलना और प्राप्त करना चाहते हैं, तो आप property
डेकोरेटर का उपयोग करके उपयोगकर्ता कोड में बदलाव किए बिना ऐसा कर सकते हैं :
class Obj:
"""property demo"""
#
@property # first decorate the getter method
def attribute(self): # This getter method name is *the* name
return self._attribute
#
@attribute.setter # the property decorates with `.setter` now
def attribute(self, value): # name, e.g. "attribute", is the same
self._attribute = value # the "value" name isn't special
#
@attribute.deleter # decorate with `.deleter`
def attribute(self): # again, the method name is the same
del self._attribute
(प्रत्येक डेकोरेटर उपयोग की गई कॉपी और पूर्व की प्रॉपर्टी ऑब्जेक्ट को अपडेट करता है, इसलिए ध्यान दें कि आपको प्रत्येक सेट, फ़ंक्शन और विधि को एक ही नाम का उपयोग करना चाहिए।
उपरोक्त परिभाषित करने के बाद, मूल सेटिंग, कोड प्राप्त करना और हटाना एक समान है:
obj = Obj()
obj.attribute = value
the_value = obj.attribute
del obj.attribute
आपको इससे बचना चाहिए:
def set_property(property,value):
def get_property(property):
सबसे पहले, ऊपर काम नहीं करता है, क्योंकि आप उस उदाहरण के लिए एक तर्क प्रदान नहीं करते हैं जो संपत्ति को (आमतौर पर self
) सेट किया जाएगा, जो होगा:
class Obj:
def set_property(self, property, value): # don't do this
...
def get_property(self, property): # don't do this either
...
दूसरे, यह दो विशेष तरीकों के उद्देश्य को दोहराता है, __setattr__
और __getattr__
।
तीसरा, हमारे पास setattr
और getattr
अंतर्निहित कार्य भी हैं ।
setattr(object, 'property_name', value)
getattr(object, 'property_name', default_value) # default is optional
@property
डेकोरेटर getters और setters बनाने के लिए है।
उदाहरण के लिए, हम सेटिंग व्यवहार को संशोधित कर सकते हैं ताकि निर्धारित मूल्य पर प्रतिबंध लगाया जा सके:
class Protective(object):
@property
def protected_value(self):
return self._protected_value
@protected_value.setter
def protected_value(self, value):
if acceptable(value): # e.g. type or range check
self._protected_value = value
सामान्य तौर पर, हम उपयोग करने से बचना चाहते हैं property
और बस प्रत्यक्ष विशेषताओं का उपयोग करते हैं।
यह अजगर के उपयोगकर्ताओं द्वारा अपेक्षित है। कम से कम-आश्चर्य के नियम के बाद, आपको अपने उपयोगकर्ताओं को वे देने की कोशिश करनी चाहिए जब तक वे इसके विपरीत एक बहुत ही आकर्षक कारण न हों।
प्रदर्शन
उदाहरण के लिए, कहें कि हमें 0 और 100 समावेशी के बीच पूर्णांक बनने के लिए हमारी वस्तु की संरक्षित विशेषता की आवश्यकता है, और इसके उचित उपयोग के उपयोगकर्ता को सूचित करने के लिए उपयुक्त संदेशों के साथ इसके विलोपन को रोकें:
class Protective(object):
"""protected property demo"""
#
def __init__(self, start_protected_value=0):
self.protected_value = start_protected_value
#
@property
def protected_value(self):
return self._protected_value
#
@protected_value.setter
def protected_value(self, value):
if value != int(value):
raise TypeError("protected_value must be an integer")
if 0 <= value <= 100:
self._protected_value = int(value)
else:
raise ValueError("protected_value must be " +
"between 0 and 100 inclusive")
#
@protected_value.deleter
def protected_value(self):
raise AttributeError("do not delete, protected_value can be set to 0")
(ध्यान दें कि जो संपत्ति के तरीकों __init__
को संदर्भित करता है self.protected_value
लेकिन यह संदर्भित करता है self._protected_value
। यह ऐसा है जो __init__
सार्वजनिक एपीआई के माध्यम से संपत्ति का उपयोग करता है, यह सुनिश्चित करता है कि यह "संरक्षित" है।)
और उपयोग:
>>> p1 = Protective(3)
>>> p1.protected_value
3
>>> p1 = Protective(5.0)
>>> p1.protected_value
5
>>> p2 = Protective(-5)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in __init__
File "<stdin>", line 15, in protected_value
ValueError: protectected_value must be between 0 and 100 inclusive
>>> p1.protected_value = 7.3
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 17, in protected_value
TypeError: protected_value must be an integer
>>> p1.protected_value = 101
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 15, in protected_value
ValueError: protectected_value must be between 0 and 100 inclusive
>>> del p1.protected_value
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 18, in protected_value
AttributeError: do not delete, protected_value can be set to 0
क्या नाम मायने रखते हैं?
हाँ, वे करते हैं । .setter
और .deleter
मूल संपत्ति की प्रतियां बनाएं। यह उपवर्गों को माता-पिता के व्यवहार में बदलाव किए बिना व्यवहार को ठीक से संशोधित करने की अनुमति देता है।
class Obj:
"""property demo"""
#
@property
def get_only(self):
return self._attribute
#
@get_only.setter
def get_or_set(self, value):
self._attribute = value
#
@get_or_set.deleter
def get_set_or_delete(self):
del self._attribute
अब इसे काम करने के लिए, आपको संबंधित नामों का उपयोग करना होगा:
obj = Obj()
# obj.get_only = 'value' # would error
obj.get_or_set = 'value'
obj.get_set_or_delete = 'new value'
the_value = obj.get_only
del obj.get_set_or_delete
# del obj.get_or_set # would error
मुझे यकीन नहीं है कि यह कहाँ उपयोगी होगा, लेकिन उपयोग-मामला है, यदि आप केवल एक संपत्ति, सेट और / या हटाना चाहते हैं। संभवतः सबसे अच्छा एक ही नाम वाले शब्दार्थ संपत्ति से चिपके रहते हैं।
निष्कर्ष
सरल विशेषताओं के साथ शुरू करें।
यदि आपको बाद में सेटिंग, प्राप्त करने और हटाने के लिए कार्यक्षमता की आवश्यकता है, तो आप इसे प्रॉपर्टी डेकोरेटर के साथ जोड़ सकते हैं।
नामित कार्यों से बचें set_...
और get_...
यही गुण हैं।