2010-03-08 13 views
152

मैं कुछ फैंसी करने के लिए कक्षा में __getattr__ विधि को ओवरराइड करना चाहता हूं लेकिन मैं डिफ़ॉल्ट व्यवहार को तोड़ना नहीं चाहता हूं।मैं डिफ़ॉल्ट व्यवहार को तोड़ने के बिना पायथन में __getattr__ को ओवरराइड कैसे करूं?

ऐसा करने का सही तरीका क्या है?

+20

"ब्रेक," यह पूछता है, "परिवर्तन" नहीं। यह काफी स्पष्ट है: "फैंसी" विशेषताओं में अंतर्निर्मित विशेषताओं में हस्तक्षेप नहीं करना चाहिए और उन्हें जितना संभव हो उतना व्यवहार करना चाहिए। माइकल का जवाब सही और सहायक दोनों है। – olooney

उत्तर

228

ओवरराइडिंग __getattr__ ठीक होना चाहिए - __getattr__ केवल अंतिम उपाय के रूप में जाना जाता है यानी अगर नाम से मेल खाने वाले उदाहरण में कोई विशेषता नहीं है। उदाहरण के लिए, यदि आप foo.bar तक पहुंचते हैं, तो __getattr__ केवल तभी बुलाया जाएगा जब foo में bar नामक कोई विशेषता नहीं है। यदि विशेषता एक आप को संभाल नहीं करना चाहती है, बढ़ा AttributeError:

class Foo(object): 
    def __getattr__(self, name): 
     if some_predicate(name): 
      # ... 
     else: 
      # Default behaviour 
      raise AttributeError 

हालांकि, __getattr__ के विपरीत, __getattribute__ पहले बुलाया जाएगा (केवल नई शैली वर्गों अर्थात उन है कि वस्तु से विरासत के लिए काम करता है)। इस मामले में, तुम इतनी तरह डिफ़ॉल्ट व्यवहार की रक्षा कर सकते हैं:

class Foo(object): 
    def __getattribute__(self, name): 
     if some_predicate(name): 
      # ... 
     else: 
      # Default behaviour 
      return object.__getattribute__(self, name) 

the Python docs for more देखें।

+0

बह, आपके संपादन में वही बात है जो मैं अपने उत्तर में दिखा रहा था, +1। –

+7

कूल, पाइथन सुपर को '__getattr__' में कॉल करना पसंद नहीं करता है - किसी भी विचार को क्या करना है? ('विशेषता त्रुटि:' सुपर 'ऑब्जेक्ट में कोई विशेषता नहीं है' __getattr __ '') – gatoatigrado

+1

अपना कोड देखे बिना यह कहना मुश्किल है, लेकिन ऐसा लगता है कि आपके किसी भी सुपरक्लास ने __getattr__ को परिभाषित नहीं किया है। –

26
class A(object): 
    def __init__(self): 
    self.a = 42 

    def __getattr__(self, attr): 
    if attr in ["b", "c"]: 
     return 42 
    raise AttributeError("%r object has no attribute %r" % 
         (self.__class__, attr)) 
    # exception text copied from Python2.6 

>>> a = A() 
>>> a.a 
42 
>>> a.b 
42 
>>> a.missing 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 8, in __getattr__ 
AttributeError: 'A' object has no attribute 'missing' 
>>> hasattr(a, "b") 
True 
>>> hasattr(a, "missing") 
False 
+0

इसके लिए धन्यवाद। बस यह सुनिश्चित करना चाहता था कि मेरे पास स्रोत में खुदाई किए बिना डिफ़ॉल्ट संदेश सही है। – ShawnFumo

+2

मुझे लगता है कि वर्ग '__repr__' –

2

माइकल जवाब विस्तार करने के लिए, यदि आप __getattr__ का उपयोग कर डिफ़ॉल्ट व्यवहार को बनाए रखना चाहते हैं, तो आप यह इतना की तरह कर सकते हैं:

class Foo(object): 
    def __getattr__(self, name): 
     if name == 'something': 
      return 42 

     # Default behaviour 
     return self.__getattribute__(name) 

अब अपवाद संदेश और वर्णनात्मक है :

>>> foo.something 
42 
>>> foo.error 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 5, in __getattr__ 
AttributeError: 'Foo' object has no attribute 'error' 
+1

@ fed.pavlo ओवरराइड होने पर' स्वयं .__ वर्ग __.__ name__' का उपयोग 'self.__ class__'' के बजाय किया जाना चाहिए। हो सकता है कि आपने '__getattr__' और '__getattribute__' मिश्रित किया हो? –

+0

मेरा बुरा। मैं स्वयं से अलग तरीके से कॉल चूक गया। ; ( –

संबंधित मुद्दे