What is the semantics meaning of 'object'?

Steven D'Aprano steve+comp.lang.python at pearwood.info
Sun Jun 23 13:29:50 EDT 2013


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.python at 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



More information about the Python-list mailing list