views:

14

answers:

1

Based on a question I previously asked, I tried to come up with a class property that would allow setting as well as getting. So I wrote this and put it in a module util:

class classprop(object):
    def __init__(self, fget, fset=None):
        if isinstance(fget, classmethod):
            self.fget = fget
        else:
            self.fget = classmethod(fget)
        if not fset or isinstance(fset, classmethod):
            self.fset = fset
        else:
            self.fset = classmethod(fset)
    def __get__(self, *a):
        return self.fget.__get__(*a)()
    def __set__(self, cls, value):
        print 'In __set__'
        if not self.fset:
            raise AttributeError, "can't set attribute"
        fset = self.fset.__get__(cls)
        fset(value)

class X(object):
    @classmethod
    def _get_x(cls):
        return 1
    @classmethod
    def _set_x(cls, value):
        print 'You set x to {0}'.format(value)
    x = classprop(fget=_get_x, fset=_set_x)

While getting is working, setting doesn't seem to be getting called:

>>> util.X.x
1
>>> util.X.x = 1
>>> 

What am I doing wrong?

(And I have seen implementations of this that work a bit differently. I'm specifically wanting to know why this implementation isn't working.)

A: 

The doc's say:

object.__set__(self, instance, value) Called to set the attribute on an instance instance of the owner class to a new value, value.

Unlike for __get__, it does not mention class attributes. So Python won't call any __set__ on a class attribute.

THC4k
Why would `X` not be the instance and `type` be the class?
Jason Baker
Instances and types are different and so is writing to them. Python just does not implement descriptors the way you want them to be.
THC4k