properties + types, implementing meta-class desciptors elegantly?

Aahz aahz at pythoncraft.com
Fri Jul 25 19:48:11 EDT 2003


In article <mailman.1058713111.11669.python-list at python.org>,
Mike C. Fletcher <mcfletch at rogers.com> wrote:
>Aahz wrote:
>>In article <mailman.1058654317.6488.python-list at python.org>,
>>Mike C. Fletcher <mcfletch at rogers.com> wrote:
>>>
>>>   * finally, stores the value
>>>         o tries to do what would have been done if there were no
>>>           descriptor (with the new, coerced value)
>>>         o does *not* create new names in the object's namespace (all
>>>           names are documented w/ descriptors, there's not a lot of
>>>           '_' prefixed names cluttering the namespace)
>>>         o does *not* require a new dictionary/storage-object attribute
>>>           for the object (the descriptor works like any other
>>>           descriptor, a *stand-alone* object that replaces a regular
>>>           attribute)
>>
>>But this is a recipe for name clashes.  If you follow the first bullet,
>>it's a normal attribute, but everything else says you want a property.
>>Properties are themselves objects that are attached to names in an
>>object.  You can't have the same name bound to two different objects.
>
>It's true that:
>
>    * your class has a namespace, and there are objects stored in that
>      namespace
>          o the objects stored in that namespace often are descriptors
>          o they are available to the instances which do not shadow them
>            (as I said, I can deal with this, and it's cleaner anyway).
>                + if they are descriptors, they modify instance access
>                  to attributes

That's technically inaccurate as phrased.  First of all, not all
descriptors get activated through attribute access, only data
descriptors do.  Data descriptors are descriptors that define a ``set``
attribute (which is essentially a method of the descriptor object).
Secondly, it muddies understanding to say that the descriptor modifies
access to attributes, as if the descriptor is a proxy for an attribute.
Data descriptors *replace* attributes, and if you want to store a value,
it's your responsibility to determine where that value is stored (and
how to retrieve it).

>    * the metaclass instance's property *values* would be stored in the
>      metaclass instance's dictionary, just as is normally done (the
>      metaclass' property *descriptors* would be stored in the
>      metaclass' dictionary), there's no new conflicts created here,
>      everything just works like it does now, a lookup would look
>      something like this:
>
> >>> x.y
>x doesn't have a __getattribute__, so see if it has a descriptor for 'y'

Actually, x is the *last* object checked, and __getattribute__() is
never called on instances.

>    get type(x).y
>
>        type(x) doesn't have a __getattribute__, so see if it has a
>        descriptor for 'y'
>
>            get type(type(x)).y -> this is just a simple descriptor, as
>            there's no higher-level descriptor, has a __get__ method,
>            calls it to retrieve type(x).y

That should be type(type(x).y), I think.  (I'm not testing this in
code.)

>        returns the currently stored entry 'y' in type(x)'s dictionary,
>        which happens to be a descriptor
>
>    has type(x).y, a descriptor with a __get__ method, calls it, gets
>    back value stored in instance's dictionary

That's correct if type(x).y is a data descriptor; other types of
descriptors do get overridden by the instance.

>You wind up with some names that are not available for use *as 
>properties* on instances *iff* you set a simple value for the properties 
>of the meta-class instance, but you solve that the regular way, by 
>making the value stored by the meta-class instance's property a 
>descriptor, rather than a simple value.  That's just the way classes 
>work.  Yes, it's a "name clash", but everything in classes/instances is 
>name clashes <shrug>.

Instances don't have properties, only types do.  A metaclass is "just" a
class that creates classes (which are themselves types with new-style
classes).  Problems only show up when you want to access class behavior
*through* a class instance.

>Not a problem I can see in the problem I outlined just yet, there's 
>still no low-level value-setting mechanism exposed,

The point is that there's no low-level value.  You always have to
explicitly specify the name and namespace when you use properties.
-- 
Aahz (aahz at pythoncraft.com)           <*>         http://www.pythoncraft.com/

This is Python.  We don't care much about theory, except where it intersects 
with useful practice.  --Aahz




More information about the Python-list mailing list