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