On Sat, 22 Jun 2013 23:40:53 -0600, Ian Kelly wrote: > On Sat, Jun 22, 2013 at 11:23 PM, Steven D'Aprano > <steve+comp.lang.pyt...@pearwood.info> wrote: >> On Sat, 22 Jun 2013 22:27:10 -0600, Ian Kelly wrote: >>> I actually consider that an up side. Sure it's inconvenient that you >>> can't delegate all such methods at once just by overriding >>> __getattribute__, but it would be more troublesome to *accidentally* >>> implement such methods because you implemented __getattribute__. >> >> It's hard to see a case where that would be a bad thing. >> >> 1) If the proxied object doesn't include __dunder__ methods, then the >> proxy will just end up up calling the default object dunder methods, >> exactly as if they weren't proxied. >> >> 2) If the proxied object does include dunders, then you generally want >> the proxy to call them, with perhaps one or two exceptions, which need >> to be overridden regardless of whether they are dunders or not. > > Proxying objects is not the only use of __getattribute__.
Okay, fair point. Actually, I made a mistake... automatic delegation uses __getattr__, not __getattribute__. >>> And >>> then there are methods that really should not be delegated in the >>> first place, like __del__. >> >> If you're using __del__, you're probably doing something wrong :-) >> >> I suppose that __del__ is a good counter-example, but (1) hardly any >> classes use __del__, and (2) for those that do, it's *way* simpler to >> manually override __del__ in the proxy than to manually delegate every >> dunder method you care about. There are typically a lot of dunder >> methods you care about. > > If you manually override __del__ in the proxy, then as far as the > garbage collector is concerned, your proxy object has a __del__ method > (even if it does nothing), and so it will be treated differently from an > object without a __del__ method. Ack, I get that. A thought comes to mind... perhaps Python ought to treat a class with __del__ set to None as if there was no __del__ at all? At the moment the garbage collector blindly calls __del__ and gets a TypeError. >> It is not the case that dunder methods cannot be automatically proxied >> because somebody deliberately designed Python to work that way. It's an >> accidental side-effect of the way new-style classes resolve method >> calls, due to decisions made for other reasons having nothing to do >> with delegation. > > Can you elaborate or provide a link? I'm curious to know what other > reason there could be for magic methods to behave differently from > normal methods in this regard. It's an efficiency optimization. I don't quite get the details, but when you run something like "a + b", Python doesn't search for __add__ using the normal method lookup procedure. That allows it to skip checking the instance __dict__, as well as __getattribute__ and __getattr__. End result is that it's quite a bit faster than ordinary lookup, but the side- effect is that the semantics are a little different: - you can't proxy magic methods automatically; - __getattribute__ and __getattr__ are only called for explicit attribute access, not for implied calls to magic methods; - you can't override a magic method on a per instance basis. Note that explicit calls like "obj.__add__(thing)" take the regular method lookup, it's just "obj + thing" that takes the shortcut. -- Steven -- http://mail.python.org/mailman/listinfo/python-list