An object is an instance (or not)?

Steven D'Aprano steve+comp.lang.python at pearwood.info
Fri Jan 30 18:45:44 EST 2015


Gregory Ewing wrote:

> Steven D'Aprano wrote:
>> Actually, if you look at my example, you will see that it is a method and
>> it does get the self argument. Here is the critical code again:
>> 
>> from types import MethodType
>> polly.talk = MethodType(
>>     lambda self: print("Polly wants a spam sandwich!"), polly)
> 
> Doing it by hand is cheating.

Smile when you say that, pardner :-)

I don't see why you think I'm cheating. What rule do you think is being
broken? I want to add a method to the instance itself, so I create a method
object and put it on the instance. What should I have done?

The default metaclass ("type") only applies the descriptor protocol to
attributes retrieved from the class itself, not those retrieved from the
instance. For instance, you can add a property object onto the instance,
but it won't behave as a property:

py> class K(object):
...     pass
...
py> x = K()
py> x.spam = property(lambda self: 23)
py> x.spam
<property object at 0xb7bbcb44>


But if I add it to the class, the descriptor magic happens:

py> K.eggs = x.spam
py> x.eggs
23

Functions are descriptors, just like property objects! So an alternative to
manually making a method object would be to use a metaclass that extended
the descriptor protocol to instance attributes. I suppose you would call
that "cheating" too?

But all of this is a side-show that distracts from my point, which is that
the lookup rules for instances and classes are such that you can override
behaviour defined in the class on a per-instance basis. The mechanics of
such aren't really relevant.


>> That's certainly not correct, because Python had classes and instances
>> before it had descriptors!
> 
> Before the descriptor protocol, a subset of its functionality
> was hard-wired into the interpreter. There has always been
> some magic going on across the instance-class boundary that
> doesn't occur across the class-baseclass boundary.

Yes, but that magic is effectively "implementation, not interface". I put
that in scare quotes because in actual pedantic fact, the descriptor
protocol is an interface: we can write our own custom descriptors. I don't
dispute that's important.

But from a birds eye view, and looking at just method and regular attribute
access, the relationship between instance-class and class-baseclass is very
similar, as is that between class-metaclass, and descriptor magic is merely
part of the implementation to make things work.

I daresay you are right that there are a few places where the interpreter
treats classes as a distinct and different kind of thing than non-class
instances. One obvious place is that dunder methods are not looked up on
the instance, unlike pretty much everything else. But I did preface my
comments about attribute lookup order as being simplified, so you can
probably find a lot more to criticise if you wish :-)



-- 
Steven




More information about the Python-list mailing list