[Zope3-dev] Re: Interface support in Python? (was Re: [Zope3-dev] Proposal: Improving on __implements__)

Phillip J. Eby pje@telecommunity.com
Thu, 23 Jan 2003 09:23:22 -0500


At 11:17 AM 1/23/03 +0200, Steve Alexander wrote:

>>   You can't use the class dictionary's '__implements__' entry to hold 
>> the value, because that entry needs to be saved for the descriptor to 
>> say what the class provides to *its* instances.  So you have to come up 
>> with another name for the entry to hold the value.  Only, you can't use 
>> the same name for both instances and classes, because there might be 
>> another meta-level that needs to store an assertion for *its* instances...
>
>getattr seems to be a bit over-overloaded in this example.
>
>If I have an instance, its class, its metaclass, and its meta-metaclass, 
>is the following true?
>
>   getattr(instance, 'foo')
>    gets me the foo of the instance
>    or if there is none, the foo of the class
>    or if there is none, the foo of the metaclass,
>    or if there is none, the foo of the meta-metaclass,
>    or if there is none, a KeyError

No.  This stops at the foo of the class.  Also, if we're talking about a 
new-style class, then the class is first checked for a 'foo' data 
descriptor, and if present, that is called without looking at the instance 
dictionary.  If 'foo' is in the class, but not a data descriptor, the 
instance dictionary is checked, with fall back to the non-data descriptor 
in the class.


>   getattr(cls, 'foo')
>    gets me the foo of the class
>    or if there is none, the foo of the metaclass,
>    or if there is none, the foo of the meta-metaclass,
>    or if there is none, a KeyError

Nope.  Stops at the foo of the metaclass.  And actually, it works the same 
as above...  the metaclass is checked for 'foo' first, if it has a data 
descriptor, that's used, otherwise fall back to the class dictionary and 
base class dictionaries in __mro__ order, then use a metaclass non-data 
descriptor, if present.


>   getattr(metacls, 'foo')
>    gets me the foo of the metaclass,
>    or if there is none, the foo of the meta-metaclass,
>    or if there is none, a KeyError
>
>   getattr(metacls, 'foo')
>    gets me the foo of the meta-metaclass,
>    or if there is none, a KeyError

Pretty much, only it's AttributeError.


>Maybe a change in the way getattr and metaclasses work could accompany a 
>proposal to get interfaces into Python?

Actually, Python works just fine.  It's just that trying to have a thing 
that looks the same no matter what meta-level you're at gets tricky.  At 
any *one* level, or even two, you can have some clarity.

The tangling is at the level of "class attribute" (a value defined in a 
class) and "metaclass instance attribute" (defined in the metaclass to be 
an attribute of the class).  My experience has been that it's better to use 
the latter than the former, when expressing data about a class.  In other 
words, define a metaclass with a "data descriptor", rather than try to 
declare such information in the class.