дескрипторы Python, разделяющие значения между классами - PullRequest
3 голосов
/ 16 декабря 2009

Дескриптор python, с которым я работаю, разделяет его значение во всех экземплярах класса его владельца. Как сделать так, чтобы дескриптор каждого экземпляра содержал свои собственные внутренние значения?

class Desc(object):
    def __init__(self, initval=None,name='val'):
        self.val = initval
        self.name = name

    def __get__(self,obj,objtype):
        return self.val

    def __set__(self,obj,val):
        self.val = val

    def __delete__(self,obj):
        pass


class MyClass(object):
    desc = Desc(10,'varx')

if __name__ == "__main__":
    c = MyClass()
    c.desc = 'max'
    d = MyClass()
    d.desc = 'sally'

    print(c.desc)
    print(d.desc)

Вывод таков: последний вызов устанавливает значение для обоих объектов:

localhost $ python descriptor_testing.py 
sally
sally

1 Ответ

7 голосов
/ 16 декабря 2009

В объекте класса хранится только один объект дескриптора, поэтому self всегда одинаков. Если вы хотите хранить данные для каждого объекта и получать к ним доступ через дескриптор, вы должны либо хранить данные по каждому объекту (возможно, лучшая идея), либо в какой-либо структуре данных, связанной с каждым объектом (идея, которая мне не нравится столько же).

Я бы сохранил данные об объекте экземпляра:

class Desc(object):
    default_value = 10
    def __init__(self, name):
        self.name = name

    def __get__(self,obj,objtype):
        return obj.__dict__.get(self.name, self.default_value)
        # alternatively the following; but won't work with shadowing:
        #return getattr(obj, self.name, self.default_value)

    def __set__(self,obj,val):
        obj.__dict__[self.name] = val
        # alternatively the following; but won't work with shadowing:
        #setattr(obj, self.name, val)

    def __delete__(self,obj):
        pass


class MyClass(object):
    desc = Desc('varx')

В этом случае данные будут сохранены в записи obj '' varx 'в ее __dict__. Из-за того, как работает поиск по дескриптору данных, вы можете «затенить» место хранения с помощью дескриптора:

class MyClass(object):
    varx = Desc('varx')

В этом случае, когда вы выполняете поиск:

MyClass().varx

Объект дескриптора вызывается и может выполнять свой поиск, но когда поиск выглядит так:

MyClass().__dict__['varx']

Значение возвращается напрямую. Таким образом, дескриптор может хранить свои данные в «скрытом», так сказать, месте.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...