__getattr__ Confusion

Saul Spatz saul.spatz at gmail.com
Mon Feb 4 14:44:48 CET 2013


On Sunday, February 3, 2013 10:35:30 PM UTC-6, Steven D'Aprano wrote:
> On Sun, 03 Feb 2013 17:08:47 -0800, Saul Spatz wrote:
> 
> 
> 
> > I don't understand what's going on at all.  Can't I dynamically define
> 
> > __getattr__?  How should I go about it?  
> 
> 
> 
> Special "dunder" methods (DoubleUNDERscore) are looked up only on the 
> 
> class, not on instances. That means that if you try to dynamically 
> 
> provide a dunder method by assigning it to an instance, say with:
> 
> 
> 
>     self.__nonzero__ = lambda self: True
> 
> 
> 
> it will *not* be automatically used by Python. The only way to 
> 
> dynamically add dunder methods is to add them to the class, but of course 
> 
> that means that all instances see the same method.
> 
> 
> 
> 
> 
> In your case, you try doing this inside the __init__:
> 
> 
> 
>     self.__getattr__ = lambda x, name: getattr(self.canvas, name)
> 
> 
> 
> 
> 
> Why not just define a __getattr__ method the normal way? In your class, 
> 
> define a method:
> 
> 
> 
>     def __getattr__(self, name):
> 
>         return getattr(self.canvas, name)
> 
> 
> 
> This technique is called automatic delegation.
> 
> 
> 
> Even if this does not quite do what you are trying to do, you will 
> 
> eliminate one major stumbling block and be that much closer to a working 
> 
> solution.
> 
> 
> 
> 
> 
> > By the way, another thing that
> 
> > didn't work was calling the method delegate instead of __getattr__. 
> 
> > Then after the constructor call, I wrote self.__getattr__ =
> 
> > self.delegate.  This crashed as before on self.create_text.
> 
> 
> 
> It is pointless to tell us that Python "crashed" if you don't show us 
> 
> *exactly* what you did, by copying and pasting the *actual* code, 
> 
> complete with the full traceback. Otherwise we are just guessing what you 
> 
> did and what error you saw.
> 
> 
> 
> I'm pretty confident that Python didn't "crash", in the commonly accepted 
> 
> meaning of the word meaning a core dump or equivalent. I'm guessing you 
> 
> meant that Python raised a perfectly normal exception, like
> 
> 
> 
> 
> 
> Traceback (most recent call last):
> 
>   ...
> 
> NameError: name 'self' is not defined
> 
> 
> 
> 
> 
> If you pay attention to the exception messages that Python prints for 
> 
> you, you will not only find it easier to debug your code, but you can 
> 
> also ask more sensible questions using accepted terminology.
> 
> 
> 
> 
> 
> 
> 
> -- 
> 
> Steven

Thanks.  The class versus instance lookup explains it.  

I didn't mean that python crashed, but that my app did.  

Now I have another question.  If dunder methods are looked up only in the class, not the instance, why did defining __nonzero__ the way I did work?  Shouldn't I have had to define it with a def?  Is __nonzero__ a special case?
 



More information about the Python-list mailing list