1

У меня есть класс питона, который наследует очередь приоритета, и я также использовать дескриптор, чтобы добавить атрибут к классу, например:Добавление дескриптора к подклассу Python

from Queue import PriorityQueue 
class My_Class(PriorityQueue): 
    my_attr = NonNegativeInt(0) 

    def __init__(self): 
     PriorityQueue.__init__(self) 

Дескриптор реализуются как это :

class NonNegativeInt(object): 
    def __init__(self, default): 
     self.default = default 
     self.data = WeakKeyDictionary() 

    def __get__(self, instance, owner): 
     return self.data.get(instance, self.default) 

    def __set__(self, instance, value): 

     if type(value) is not int: 
      raise TypeError('Value must be an int') 

     if value < 0: 
      raise ValueError("Value must be above 0") 

     self.data[instance] = value 

Когда я называю My_Class.my_attr = -1 я не получаю никаких исключений. Однако, если я изменю My_Class на это я получаю исключение в порядке:

class My_Class(object): 
    my_attr = NonNegativeInt(0) 

    def __init__(self): 
     pass 

Интересно, что первая реализация My_Class начинается с атрибутом my_attr, он просто не выполняет функцию __set__ в NonNegativeInt.

Почему изменяется изменение суперкласса, как работает мой дескриптор? Это имеет отношение к этой строке: PriorityQueue.__init__(self)? Как я могу дать подклассу поведение, которое я хочу?

+0

Вы имеете в виду, что вы наследуете от 'object' (нижний регистр), и вы устанавливаете атрибут на * экземпляр *' My_Class', правильно? –

+0

И откуда берется 'PriorityQueue'? –

+0

Да, я наследую от 'object', это была просто опечатка. – devin

ответ

2

Дескрипторы работают только с классы нового стиля (те, которые прямо или косвенно наследуются от object). Существует некоторая поддержка дескрипторов __get__ методов в классах старого стиля, но эта поддержка ограничена.

Класс, который вы используете, вероятно, не наследуется от object. Если это Queue.PriorityQueue class, то это, безусловно, так, классы в этом модуле являются старыми.

То, что вы звоните: PriorityQueue.__init__ не имеет ничего общего.

+1

Если я изменю 'My_Class' на это, это сработает:' class My_Class (PriorityQueue, object): '. Есть ли какая-то причина, по которой я должен этого избежать? – devin

+0

@devin: Если бы вы использовали 'super()' для перехода к переопределенным методам или для использования множественного наследования (последнее смешивание в 'object'), могут возникнуть проблемы, но для вашего usecase я ** думаю **, что все должно быть в порядке. –

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

  • Нет связанных вопросов^_^