5

我在一个类上有一个描述符,它的__set__方法没有被调用。几个小时以来,我一直在努力寻找这个问题,但对此没有任何答案。但是我在下面注意到的是,当我将 12 分配给 MyTest.X 时,它会删除 X 的属性描述符,并将其替换为值 12。因此调用了 Get 函数的打印语句。那挺好的。

但是__set__函数的打印语句根本不会被调用。我错过了什么吗?

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__
4

3 回答 3

6

其他两个答案暗示使用元类来完成您想做的事情。为了帮助了解它们,这里有一个示例,将一个应用于您的问题中的代码,使其执行您想要的操作:

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 type。但是,您可以将其用作基类并派生您自己的专用元子类——在这种情况下,它具有作为数据描述符(又名属性)的类属性。请注意,self元或元子类方法中的参数是元类实例,它是一个类。在上面的代码中,它被命名为MyTest.

于 2013-08-12T16:59:53.393 回答
4

描述符作用于类的实例,而不是类本身。如果您有 , 的实例MyTestX将按预期工作,但将其作为类属性访问实际上会设置类对象本身的属性。您可以尝试定义一个自定义元类来添加描述符,然后MyTest使用该元类创建。

于 2013-08-08T18:55:54.267 回答
3

__set__您分配给X一个实例时,唯一会被调用

如果您希望这适用于类属性,则必须在的元类上设置描述符MyTest

于 2013-08-08T18:54:40.700 回答