为什么不调用Python描述符__set__

C J*_*son 5 python

我有一个类的描述符,它的__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__
Run Code Online (Sandbox Code Playgroud)

Sil*_*Ray 5

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


mar*_*eau 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__)
Run Code Online (Sandbox Code Playgroud)

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