Уведомления

Группа в Telegram: @pythonsu

#1 Май 15, 2017 07:14:11

alexgreg
Зарегистрирован: 2017-05-15
Сообщения: 26
Репутация: +  0  -
Профиль   Отправить e-mail  

Дескриптор с self.value (Descriptor with self.value)

Задача: в некотором клиентском классе SomeClass описать свойство myName (имя экземпляра), разместив атрибут value в классе-дескрипторе Name. Предполагается, что каждый экземпляр класса SomeClass имеет своё собственное имя.

Пишу код (Python 3.6.0):

 class Name: # name descriptor
    def __init__(self):
        self.value = 'default name'
    def __get__(self, instance, owner):
        return self.value
    
    def __set__(self, instance, value):
        self.value = value
        
    def __delete__(self, instance):
        raise AttributeError('from Name.__delete__')
class SomeClass:
    myName = Name()
#---------------------------------------------------------------------------------
if __name__ == '__main__':
    a = SomeClass()
    b = SomeClass()
    
    print(a.myName)
    print(b.myName)
    a.myName = 'my name is A'
    print(a.myName)
    print(b.myName)
    b.myName = 'my name is B'
    print(a.myName)
    print(b.myName)
    del a.myName

Получаю результат:

 ==================== RESTART: Dweb.py/attrs/testdesc.py ====================
default name
default name
my name is A
my name is A
my name is B
my name is B
Traceback (most recent call last):
  File "D:/web.py/attrs/testdesc.py", line 36, in <module>
    del a.myName
  File "D:/web.py/attrs/testdesc.py", line 13, in __delete__
    raise AttributeError('from Name.__delete__')
AttributeError: from Name.__delete__
>>>


В чём ошибка?

Отредактировано alexgreg (Май 15, 2017 07:15:45)

Офлайн

#2 Май 15, 2017 08:25:55

krok64
Зарегистрирован: 2017-04-04
Сообщения: 75
Репутация: +  11  -
Профиль   Отправить e-mail  

Дескриптор с self.value (Descriptor with self.value)

 class SomeClass:
    def __init__(self):
        self.myName = Name()

а в класс Name добавь

     def __repr__(self):
        return self.value

Отредактировано krok64 (Май 15, 2017 08:28:30)

Офлайн

#3 Май 15, 2017 09:18:06

alexgreg
Зарегистрирован: 2017-05-15
Сообщения: 26
Репутация: +  0  -
Профиль   Отправить e-mail  

Дескриптор с self.value (Descriptor with self.value)

Разве свойства в __init__ описываются?

Внёс предложенные изменения:

 class Name: # name descriptor
    def __init__(self):
        self.value = 'default name'
    def __get__(self, instance, owner):
        return self.value
    
    def __set__(self, instance, value):
        self.value = value
        
    def __delete__(self, instance):
        raise AttributeError('from Name.__delete__')
class SomeClass:
    def __init__(self):
        self.myName = Name()
#---------------------------------------------------------------------------------
if __name__ == '__main__':
    a = SomeClass()
    b = SomeClass()
    
    print(a.myName)
    print(b.myName)
    a.myName = 'my name is A'
    print(a.myName)
    print(b.myName)
    b.myName = 'my name is B'
    print(a.myName)
    print(b.myName)
    print(a.__dict__)
    print(b.__dict__)
    #del a.myName

Получаю результат:

 ==================== RESTART: D:\web.py\attrs\testdesc.py ====================
<__main__.Name object at 0x02EBD2D0>
<__main__.Name object at 0x03128F70>
my name is A
<__main__.Name object at 0x03128F70>
my name is A
my name is B
{'myName': 'my name is A'}
{'myName': 'my name is B'}
>>>

в этом случая, насколько я понимаю, протокол дескриптора бездействует (проверено print'ами)

Офлайн

#4 Май 15, 2017 09:33:02

krok64
Зарегистрирован: 2017-04-04
Сообщения: 75
Репутация: +  11  -
Профиль   Отправить e-mail  

Дескриптор с self.value (Descriptor with self.value)

alexgreg
Разве свойства в __init__ описываются? Внёс предложенные изменения:
В __init__ свойства инициализируются сразу после создания объекта. Для вывода имени по умолчанию посмотри дополнение ко второму сообщению.

Офлайн

#5 Май 15, 2017 09:39:32

alexgreg
Зарегистрирован: 2017-05-15
Сообщения: 26
Репутация: +  0  -
Профиль   Отправить e-mail  

Дескриптор с self.value (Descriptor with self.value)

1) в __init__ инициализируются атрибуты экземпляра класса, если self используется, разве не так?

2) если я опишу метод SomeClient.__repr__, при обращении к a.myName какой метод отработает SomeClient.__repr__ или Name.__get__?

Офлайн

#6 Май 15, 2017 10:22:59

PEHDOM
Зарегистрирован: 2016-11-28
Сообщения: 2196
Репутация: +  294  -
Профиль   Отправить e-mail  

Дескриптор с self.value (Descriptor with self.value)

alexgreg
class SomeClass:
def __init__(self):
self.myName = Name()
Это так не работает. Дескриптор это атрибут класса а не инстанса. Вариант топикстартера был правильный, и работал он правильно(с точки зрения пайтона конечно, а не топикстартера).. так и должно быть.
Когда вы делаете a.myName = ‘my name is A’ вы устанавливете дескриптору myName класса SomeClass значение ‘my name is A’. поскольку b инстанс того же класса что и a то print(b.myName) вернет ‘my name is A’.
Теперь когда вы делаете b.myName = ‘my name is B’ вы вы устанавливете дескриптору myName класса SomeClass значение ‘my name is B’ и сотоветвенно print(a.myName) вернет ‘my name is B’ поскольку а инстанс класса SomeClass



==============================
Помещайте код в теги:
[code python][/code]
Бериегите свое и чужое время.

Отредактировано PEHDOM (Май 15, 2017 10:30:59)

Офлайн

#7 Май 15, 2017 10:31:16

alexgreg
Зарегистрирован: 2017-05-15
Сообщения: 26
Репутация: +  0  -
Профиль   Отправить e-mail  

Дескриптор с self.value (Descriptor with self.value)

где ошибка в первом варианте? предполагается, что каждый экземпляр класса SomeClass должен иметь своё имя, которое хранится в экземпляре соответствующего дескриптора (поле self.value класса Name)

Отредактировано alexgreg (Май 15, 2017 10:31:55)

Офлайн

#8 Май 15, 2017 10:54:55

4kpt_V
От: Харьков
Зарегистрирован: 2017-02-19
Сообщения: 299
Репутация: +  12  -
Профиль   Отправить e-mail  

Дескриптор с self.value (Descriptor with self.value)

alexgreg
Для Вашего случая лучше использовать property.

Ошибка в том, что Вы делаете атрибут класса и изменив его через один из экземпляров удивляетесь почему он поменялся у других

Простой пример для понимания

 #
class A:
    n = {}
#
a = A()
b = A()
a.n["a"] = 12
print(b.n)  # {'a': 12}

Отредактировано 4kpt_V (Май 15, 2017 11:00:06)

Офлайн

#9 Май 15, 2017 11:04:56

PEHDOM
Зарегистрирован: 2016-11-28
Сообщения: 2196
Репутация: +  294  -
Профиль   Отправить e-mail  

Дескриптор с self.value (Descriptor with self.value)

alexgreg
где ошибка в первом варианте?
вопрос, вам это надо для чего? если для продакшена, то советую использовать чтонить другое(выше советуют property например ), а не дескрипторы, если это задания от преподавателя и нужно использовать именно дексриптеры то есть один нетрадиционный способ(тоесть через жопу) чтобы дескриптор храних значения каждого инстанса.



==============================
Помещайте код в теги:
[code python][/code]
Бериегите свое и чужое время.

Офлайн

#10 Май 15, 2017 11:04:58

alexgreg
Зарегистрирован: 2017-05-15
Сообщения: 26
Репутация: +  0  -
Профиль   Отправить e-mail  

Дескриптор с self.value (Descriptor with self.value)

4kpt_V
alexgreg
Для Вашего случая лучше использовать property.

все остальные варианты работают (property, @property, дескриптор с использованием атрибутов класса-клиента). непонятен именно этот вариант, когда значение для класса-клиента хранится в атрибуте класса-дескриптора (self.value в примере)

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version