我在类上有一个描述符,并且不会调用它的__set__
方法。我一直在寻找这个问题几个小时并且没有答案。但是我在下面注意到的是,当我将12分配给MyTest.X时,它会擦除X的属性描述符,并将其替换为值12.因此调用Get函数的print语句。那很好。
但__set__
函数的print语句根本不会被调用。我错过了什么吗?
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__
答案 0 :(得分:5)
另外两个答案提到使用元类来完成你想要做的事情。为了帮助我们了解它们,这里有一个例子,它将一个应用到您问题中的代码中,使其按照您的意愿执行:
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__)
类是其元类的实例,通常是类型type
。但是,您可以将其用作基类并派生自己的专用元子类 - 在这种情况下,它具有类属性,即数据描述符(也称为属性)。请注意,元或元子类方法中的self
参数是元类实例,它是一个类。在上面的代码中,它的名称为MyTest
。
答案 1 :(得分:4)
描述符可以处理类的实例,而不是类本身。如果您有MyTest
的实例,X
将按预期工作,但作为类属性访问它实际上设置了类对象本身的属性。您可以尝试定义自定义元类以添加描述符,然后使用该元类创建MyTest
。
答案 2 :(得分:3)
__set__
仅在您分配给实例的X
时被调用
如果您希望这适用于类属性,则必须在MyTest