[Python-ideas] A user story concerning things knowing their own names

Robert Kern robert.kern at gmail.com
Wed Mar 16 19:47:45 CET 2011


On 3/16/11 12:13 PM, Ian Bicking wrote:
> I'll note this general problem is also present in any of the declarative ORMs,
> which use silly hacks to tell descriptors their name.  Like you have:
>
> class Table(ORM):
>      name = StringColumn()
>
> Another case where I've noticed a problem is any kind of descriptor that needs
> its own storage; the name of the property gives a possible stable namespace for
> the value, but without the name you either have to pass in a name or the storage
> area becomes volatile.  For instance, a read-only descriptor:
> http://svn.colorstudy.com/home/ianb/recipes/setonce.py
>
> You can solve this in, e.g., the ORM class by doing things when a class is
> created -- but it requires very specific cooperation between the class and the
> descriptor.  Everyone really does it different ways.
>
> One could imagine an extension of the descriptor protocol, where on class
> creation you called something like attr.__addtoclass__(cls, name) (for all
> attributes of the class that define that method) -- which if you just want the
> name you'd simply save that name in your object and return self.

If we were to extend the descriptor protocol, I think it would be better to 
extend it by providing __get_ex__(self, instance, owner, name), __set_ex__(self, 
instance, name, value), etc. methods that would be called in preference over the 
current __get__() and __set__() methods. This allows descriptor objects to be 
reused.

We do this reasonably often with the Traits package (which overrides 
__getattribute__() to essentially implement this __get_ex__()/__set_ex__() 
protocol by different names). For example, we have a complicated trait for 
specifying colors:

   ColorTrait = Trait("black", Tuple, List, Str, color_table)

It would be nice to simply reuse this object everywhere:

   class Figure(HasTraits):
     background = ColorTrait
     foreground = ColorTrait

The alternative is to only provide factories such that you always get a new 
descriptor:

   ColorTrait = lambda: Trait("black", Tuple, List, Str, color_table)

   class Figure(HasTraits):
     background = ColorTrait()
     foreground = ColorTrait()

However, this makes these new descriptors inconsistent with current descriptors, 
which can be shared between classes. It also prevents you from passing around 
descriptor objects as first-class citizens. For example, I might want to ask the 
ColorTrait for its constituents in order to construct a new one that has a 
different default value. I can't ask that of a factory function.

This objection holds for any proposal that requires the descriptor object itself 
to hold onto its name, no matter how it acquires that name. Personally, I don't 
want descriptors that know their own name; I want descriptors that can be told 
what name to use for each operation.

-- 
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
  that is made terrible by our own mad attempt to interpret it as though it had
  an underlying truth."
   -- Umberto Eco




More information about the Python-ideas mailing list