[Python-Dev] RFC: readproperty

Žiga Seilnacht ziga.seilnacht at gmail.com
Wed Sep 28 19:28:45 CEST 2005


Michael Hudson <mwh <at> python.net> writes:

> 
> "Phillip J. Eby" <pje <at> telecommunity.com> writes:
> 
> > Unfortunately, finding out a descriptor's name is non-trivial; it'd be nice 
> > if there were a descriptor hook __bind__(cls,name) that was called by 
> > classes during cls.__new__ or assignment to a class attribute, and which 
> > you could define to return a replacement descriptor.  It seems like one of 
> > the first metaclasses I end up writing in any new project is something to 
> > do this, and I believe Ian Bicking has encountered the same thing in e.g. 
> > SQLObject.
> 
> I've done this many times too, but I've never really felt the need to
> propose a change to Python for it.  I guess one could modify the
> descriptor protocol slightly, but is it worth it?  Hmm, dunno.
> 
> Cheers,
> mwh
> 

You can use something like this to find a descriptor's name:

class Private(property):

    def __init__(self, permission, fget=None, fset=None, fdel=None, doc=None):
        fget = fget or 'r' in permission and self.default_fget or None
        fset = fset or 'w' in permission and self.default_fset or None
        fdel = fdel or 'd' in permission and self.default_fget or None
        super(private, self).__init__(fget, fset, fdel, doc)

    def get_attribute_name(self, instance):
        my_name = None
        for cls in instance.__class__.mro():
            for attribute_name, attribute_object in cls.__dict__.iteritems():
                if attribute_object is self:
                    my_name = attribute_name
                    break
            if my_name is not None:
                class_name = cls.__name__
                break
        attribute_name = '_%s__%s' % (class_name, my_name)
        self.attribute_name = attribute_name
        return attribute_name

    def default_fget(self, instance):
        try:
            attribute_name = self.attribute_name
        except AttributeError:
            attribute_name = self.get_attribute_name(instance)
        return getattr(instance, attribute_name)

    def default_fset(self, instance, value):
        try:
            attribute_name = self.attribute_name
        except AttributeError:
            attribute_name = self.get_attribute_name(instance)
        setattr(instance, attribute_name, value)

    def default_fdel(self, instance):
        try:
            attribute_name = self.attribute_name
        except AttributeError:
            attribute_name = self.get_attribute_name(instance)
        delattr(instance, attribute_name)



More information about the Python-Dev mailing list