Почему объявление класса дескриптора в функции __init__ нарушает функциональность дескриптора? - PullRequest
7 голосов
/ 17 июня 2009

В классе B ниже я хотел, чтобы функция __set__ в классе A вызывалась всякий раз, когда вы присваиваете значение B().a. Вместо этого установка значения B().a заменяет значение B().a на значение. Присвоение класса C C().a работает правильно, но я хотел иметь отдельный экземпляр A для каждого пользовательского класса, т. Е. Я не хочу менять «a» в одном экземпляре C (), чтобы изменить «a» во всех остальных экземпляров. Я написал пару тестов, чтобы проиллюстрировать проблему. Можете ли вы помочь мне определить класс, который пройдет как test1, так и test2?

class A(object):
    def __set__(self, instance, value):
        print "__set__ called: ", value

class B(object):
    def __init__(self):
        self.a = A()

class C(object):
    a = A()

def test1( class_in ):
    o = class_in()
    o.a = "test"
    if isinstance(o.a, A):
        print "pass"
    else:
        print "fail"

def test2( class_in ):
    o1, o2 = class_in(), class_in()
    if o1.a is o2.a:
        print "fail"
    else:
        print "pass"

Ответы [ 3 ]

5 голосов
/ 17 июня 2009

В соответствии с документацией :

Следующие методы применяются только , когда экземпляр класса, содержащий метод (так называемый дескриптор класс) появляется в словаре классов другого класса нового стиля , известного как класс владельца. В примерах ниже «атрибут» относится к атрибут, имя которого является ключом недвижимость в классе владельца ’__dict__. Дескрипторы могут быть реализованы только как сами классы нового стиля.

Так что вы не можете иметь дескрипторы в экземплярах.

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

0 голосов
/ 08 марта 2014

Меня укусила похожая проблема: я хотел классифицировать объекты с атрибутами, управляемыми дескриптором. Когда я сделал это, я заметил, что атрибуты переписывались во всех объектах, так что они не были индивидуальными.

Я поднял вопрос SO, и результирующий ответ здесь: Значение атрибута класса меняется без причины

Хорошая ссылка на документ с обсуждением дескрипторов здесь: http://martyalchin.com/2007/nov/24/python-descriptors-part-2-of-2/

Пример дескриптора из вышеупомянутой ссылки приведен ниже:

class Numberise(object):
    def __init__(self, name):
        self.name = name

    def __get__(self, instance, owner):
        if self.name not in instance.__dict__:
            raise (AttributeError, self.name)
        return '%o'%(instance.__dict__[self.name])

    def __set__(self, instance, value):
        print ('setting value to: %d'%value)
        instance.__dict__[self.name] = value
0 голосов
/ 17 июня 2009

Вот класс, который может пройти оригинальные тесты, но не пытайтесь использовать его в большинстве ситуаций. он не проходит тест на подлинность на себе!

class E(object):
    def __new__(cls, state):
        class E(object):
            a = A(state)
            def __init__(self, state):
                self.state = state
        return E(state)

#>>> isinstance(E(1), E)
#False
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...