[Zope3-dev] Re: Interface support in Python? (was Re:
[Zope3-dev] Proposal: Improving on __implements__)
Phillip J. Eby
pje@telecommunity.com
Wed, 22 Jan 2003 19:24:52 -0500
At 06:29 PM 1/22/03 -0500, Jim Fulton wrote:
>Phillip J. Eby wrote:
>
>..
>
>>I think for me, another issue would most definitely be proper support for
>>metaclasses, i.e. spelling the difference between what classes and
>>instances implement. While it may be true that "most people" will not
>>implement metaclasses, it is still quite possible for them to be bitten
>>by the difference when using metaclasses provided by someone else.
>>(Currently, __class_implements__ works reasonably well, but it can get
>>really hairy when you have metametaclasses in play.)
>
>I agree. I'll note that you don't need meta classes to have classes
>that implement interesting interfaces. Classes do have some methods
>of their own, most notably __call__, and can habve more with class
>and static methods.
Right; It's just that the hairy part is that a metaclass can't use
__implements__ to say what its instances implement! IIRC, it has to define
a __class_implements__ descriptor that returns different values for
instances and classes. Anyway, it's hairy because of the special casing
for classes.
>>If we were writing the interface package today -- assuming Python 2.2 and
>>up -- I'd suggest always asking an object's class for what it implements,
>>passing in either the instance or the class. That seems to be the only
>>way to be completely unambiguous as to whose interfaces you're asking
>>for, when the object in question might itself be a class or type. An
>>__implements__ descriptor can only be unambiguous if it's defined on the
>>meta-most metaclass of the system. So to do it cleanly it'd have to be
>>part of type 'type', which implies a language change.
>
>I'm not sure what you just said. ;)
I would try to show you an example of the problem, but my brain is too
fried right now. The problem has to do with distinguishing between "class
attributes" and "metaclass instance attributes" -- which are *not* the same
thing. Hopefully you are now confused about something more specifically
confusing. ;)
>I'll note that it is possible to design a descriptor for __implements__
>that will give different answers depending on whether you access it
>through a class or an instance.
I've done that; it didn't work nearly as well as fixing the Interface
package to properly support __class_implements__ did.
> You don't need __class_implements__.
>And you can get an object's implementation specification unambiguously.
>No meta-class is necessary. To make this work, you don't want people
>setting __implements__ directly.
But if you *do* have a metaclass, the metaclass can't make assertions about
its instances' interfaces, because the __implements__ slot on the metaclass
instance will be occupied by a descriptor that's there to get the metaclass
instance instance's interface assertions.
Maybe that one was more clear? Anyway, this is all the same problem I'm
describing throughout this message: class attribute descriptors take
precedence over metaclass instance descriptors, unless the latter are
"data" descriptors (i.e. that accept __set__ calls). I'm not saying it's
impossible to make it work, just that it's rather hairy, even with just one
meta-level. 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...