__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