__getattribute__विधि का उपयोग कैसे किया जाता है?
इसे सामान्य बिंदीदार लुकअप से पहले कहा जाता है। अगर यह उठता है AttributeError, तो हम कॉल करते हैं __getattr__।
इस विधि का उपयोग बल्कि दुर्लभ है। मानक पुस्तकालय में केवल दो परिभाषाएँ हैं:
$ grep -Erl "def __getattribute__\(self" cpython/Lib | grep -v "/test/"
cpython/Lib/_threading_local.py
cpython/Lib/importlib/util.py
सर्वश्रेष्ठ प्रणालियां
किसी एकल विशेषता तक प्रोग्रामेटिक रूप से पहुंच को नियंत्रित करने का उचित तरीका है property। क्लास Dको निम्नानुसार लिखा जाना चाहिए (स्पष्ट उद्देश्य व्यवहार को दोहराने के लिए सेटर और डिलेटर के साथ वैकल्पिक रूप से):
class D(object):
def __init__(self):
self.test2=21
@property
def test(self):
return 0.
@test.setter
def test(self, value):
'''dummy function to avoid AttributeError on setting property'''
@test.deleter
def test(self):
'''dummy function to avoid AttributeError on deleting property'''
और उपयोग:
>>> o = D()
>>> o.test
0.0
>>> o.test = 'foo'
>>> o.test
0.0
>>> del o.test
>>> o.test
0.0
एक संपत्ति एक डेटा डिस्क्रिप्टर है, इस प्रकार यह पहली चीज है जो सामान्य बिंदीदार लुकिंग एल्गोरिथ्म में देखी गई है।
के लिए विकल्प __getattribute__
यदि आपके पास हर विशेषता के लिए लुकअप को लागू करने की आवश्यकता है तो आपके पास कई विकल्प हैं __getattribute__।
- उठाएं
AttributeError, जिसके कारण __getattr__कॉल किया जाएगा (यदि कार्यान्वित किया गया है)
- इसके द्वारा कुछ लौटाओ
superमाता-पिता (शायद object) के कार्यान्वयन को कॉल करने के लिए उपयोग करना
- बुला
__getattr__
- किसी भी तरह से अपने स्वयं के बिंदीदार एल्गोरिथ्म को लागू करना
उदाहरण के लिए:
class NoisyAttributes(object):
def __init__(self):
self.test=20
self.test2=21
def __getattribute__(self, name):
print('getting: ' + name)
try:
return super(NoisyAttributes, self).__getattribute__(name)
except AttributeError:
print('oh no, AttributeError caught and reraising')
raise
def __getattr__(self, name):
"""Called if __getattribute__ raises AttributeError"""
return 'close but no ' + name
>>> n = NoisyAttributes()
>>> nfoo = n.foo
getting: foo
oh no, AttributeError caught and reraising
>>> nfoo
'close but no foo'
>>> n.test
getting: test
20
जो आप मूल रूप से चाहते थे।
और यह उदाहरण दिखाता है कि आप मूल रूप से जो चाहते थे, वह कैसे कर सकते हैं:
class D(object):
def __init__(self):
self.test=20
self.test2=21
def __getattribute__(self,name):
if name=='test':
return 0.
else:
return super(D, self).__getattribute__(name)
और इस तरह व्यवहार करेंगे:
>>> o = D()
>>> o.test = 'foo'
>>> o.test
0.0
>>> del o.test
>>> o.test
0.0
>>> del o.test
Traceback (most recent call last):
File "<pyshell#216>", line 1, in <module>
del o.test
AttributeError: test
को़ड समीक्षा
टिप्पणियों के साथ आपका कोड। आपके पास स्वयं में एक बिंदीदार खोज है __getattribute__। यही कारण है कि आपको एक पुनरावृत्ति त्रुटि मिलती है। आप देख सकते हैं कि नाम क्या है "__dict__"और superवर्कअराउंड का उपयोग करें, लेकिन यह कवर नहीं करता है __slots__। मैं पाठक को एक अभ्यास के रूप में छोड़ दूँगा।
class D(object):
def __init__(self):
self.test=20
self.test2=21
def __getattribute__(self,name):
if name=='test':
return 0.
else: # v--- Dotted lookup on self in __getattribute__
return self.__dict__[name]
>>> print D().test
0.0
>>> print D().test2
...
RuntimeError: maximum recursion depth exceeded in cmp