Why does the Python descriptor __set__ not get called
python
Solution
The other two answers allude to using metaclasses to accomplish what you want to do. To help learn about them, here's an example of applying one to the code in your question that makes it do what you want:
class _static_property(object):
"""Descriptor class used for declaring computed properties that
don't require a class instance.
"""
def __init__(self, getter, setter):
self.getter = getter
self.setter = setter
def __get__(self, obj, objtype=None):
print("In the getter function")
return self.getter(obj)
def __set__(self, obj, value):
print("In setter function")
self.setter(obj, value)
class _MyMetaClass(type):
def getX(self):
return self._x
def setX(self, v):
self._x = v
X = _static_property(getX, setX)
class MyTest(object):
__metaclass__ = _MyMetaClass # Python 2 syntax
_x = 42
#class MyTest(object, metaclass=_MyMetaClass): # Python 3 (only) syntax
# _x = 42
print(MyTest.__dict__)
print(MyTest.X)
MyTest.X = 12
print(MyTest.X)
print(MyTest.__dict__)
Classes are instances of their metaclass which is normally type `type`. However you can use that as a base class and derive your own specialized meta-subclass -- that in this case is one that has class attributes which are data descriptors (aka properties). Note that the `self` argument in a meta or meta-subclass method is a metaclass instance, which is a class. In code above, it's named `MyTest`.
Problem
I have a descriptor on a class, and its `__set__` method does not get called. I have been looking long and hard on this for a few hours and have no answer for this. But what I noticed below is that when I assign 12 to MyTest.X, it erases the property descriptor for X, and replaces it with the value of 12. So the print statement for the Get function gets called. That's good. But the print statement for the `__set__` function does NOT get called at all. Am I missing something? ``` class _static_property(object): ''' Descriptor class used for declaring computed properties that don't require a class instance. ''' def __init__(self, getter, setter): self.getter = getter self.setter = setter def __get__(self, instance, owner): print "In the Get function" return self.getter.__get__(owner)() def __set__(self, instance, value): print "In setter function" self.setter.__get__()(value) class MyTest(object): _x = 42 @staticmethod def getX(): return MyTest._x @staticmethod def setX(v): MyTest._x = v X = _static_property(getX, setX) print MyTest.__dict__ print MyTest.X MyTest.X = 12 print MyTest.X print MyTest.__dict__ ```