2013-08-08 4 views
5

У меня есть дескриптор класса, и его метод __set__ не вызывается. Я долго смотрел на это несколько часов и не отвечал за это. Но ниже я заметил, что когда я назначаю 12 MyTest.X, он стирает дескриптор свойства для X и заменяет его значением 12. Таким образом вызывается запрос печати для функции Get. Это хорошо.Почему дескриптор Python __set__ не вызван

Но инструкция печати для функции __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__ 
+0

Вы действительно хотите использовать атрибуты класса, а не создавать экземпляр экземпляра? – user2357112

+0

В моем случае, который очень сложный, это обертывание статических методов, которые в конечном итоге передаются статическим методам C++. –

+0

По крайней мере, у SWIG возникли проблемы с протоколами дескриптора, поэтому решение может быть и на вашем оберточном слое C++, если вы делаете более сложные вещи, чем показано здесь. – schlenk

ответ

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. Однако вы можете использовать это как базовый класс и получить свой собственный специализированный мета-подкласс - в этом случае это тот, который имеет атрибуты класса, которые являются дескрипторами данных (aka properties). Обратите внимание, что аргумент self в методе мета или подкласса представляет собой экземпляр метакласса, который является классом. В приведенном выше коде он называется MyTest.

+0

Большое вам спасибо за показ примера того, как это работает. –

3

__set__ только вызывается, когда вы назначаете X экземпляра

Если вы хотите, чтобы работать для класса атрибута объявления, вы должны настроить дескриптор на метаклассе MyTest

+0

Есть ли способ сделать так, что я хочу? –

+0

@CJohnson, конечно, просто сделайте метакласс, который делает это. –

+0

metaclass? Извините, я новичок в python. –

4

Дескрипторы работают над экземплярами классов, а не самими классами. Если у вас есть экземпляр MyTest, X будет работать так, как вы ожидаете, но доступ к нему как атрибуту класса фактически устанавливает атрибут самого объекта класса. Вы можете попытаться определить пользовательский метакласс для добавления дескриптора в, а затем создать MyTest с этим метаклассом.

+0

Итак, посмотри на метакласс сейчас –

Смежные вопросы