Найти - Пользователи
Полная версия: Дескриптор с self.value (Descriptor with self.value)
Начало » Python для экспертов » Дескриптор с self.value (Descriptor with self.value)
1 2 3
4kpt_V
 #
if __name__ == '__main__':
    a = SomeClass()
    b = SomeClass()
    print(id(a.myName))
    print(id(b.myName))
    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

Это раз…

И как Вы думаете? В какой момент выполняется эта строка?
 #
class SomeClass:
    myName = Name()  # вот эта вот...
alexgreg
PEHDOM
вопрос, вам это надо для чего?
для понимания тонкостей работы протокола дескриптора в рамках изучения расширенных методов управления атрибутов класса/экземпляра класса

для продакшн-варианта я бы использовал простой атрибут класса, т.к. это самый простой способ реализации поставленной задачи
alexgreg
4kpt_V
И как Вы думаете? В какой момент выполняется эта строка?

Я согласен, если бы класс Name был обычным классом без протокола дескриптора. Дело в том, что аналогичное объявление свойств класса, но с наличием атрибутов в этом же классе (в примере - класс D), отрабатывает:

  
class Nn: # дескриптор свойств nn
    """ счётчик обращений к name """
    def __get__(self, instance, owner):
        return owner._nn
    
    def __set__(self, instance, value):
        raise AttributeError('Нельзя изменить счётчик')
    
    def __delete__(self, instance):
        raise AttributeError('Нельзя удалить счётчик')
class Name: # дескриптор свойств name
    """ имя экземпляра """
    def __get__(self, instance, owner):
        owner._nn += 1
        return '[%d] %s' % (owner._nn, instance._name)
    
    def __set__(self, instance, value):
        instance._name = value
    def __delete__(self, instance):
        raise AttributeError('Нельзя удалить имя экземпляра')
class D: # класс-клиент
    def __init__(self):
        D._nn = 0
        self._name = 'по-умолчанию'
    nn = Nn()
    name = Name()
#---------------------------------------------------------------------------------
if __name__ == '__main__':
    a, b, c = D(), D(), D()
    a.name = 'my name is A'
    b.name = 'my name is B'
    c.name = 'my name is C'
    print(a.name)
    print(b.name)
    print(c.name)
    print(a.nn)
    print(b.nn)
    print(c.nn)

Результаты:

 ================= RESTART: D:\web.py\attrs\mydescriptors.py =================
[1] my name is A
[2] my name is B
[3] my name is C
3
3
3
>>>


В этом примере свойство nn - общий для всех экземпляров счётчик обращений к свойству name, а name - имя экземпляра (для каждого своё)
4kpt_V
Я задал простой вопрос. Жду на него ответа.

P.S. Хватит выделять черным. У форумчан со зрением пока все ОК
alexgreg
4kpt_V
Я задал простой вопрос. Жду на него ответа.
Думаю, что при импорте/запуске модуля


Аналогичная строка из второго примера:
 class D: # класс-клиент
    def __init__(self):
        D._nn = 0
        self._name = 'по-умолчанию'
    nn = Nn()
    name = Name()  #  вот эта ... 


В чём принципиальное отличие?
4kpt_V
Верно. Т.е. при импорте или запуске модуля создается класс и с атрибутом класса (внимание! класса), связывается объект (внимание! объект) дескриптора. Потом вы на основе этого класса наделали объектов, но при этом атрибут остался атрибутом класса. Не объекта! Изменяя этот атрибут через объект (который Вы наштамповали с использованием класса как формы) Вы все равно меняете атрибут класса, который наследуют через него все объекты. Соответственно в них он тоже меняется.

P.S. Не знаю как еще проще объяснить Надеюсь понятно.
alexgreg
4kpt_V
P.S. Не знаю как еще проще объяснить Надеюсь понятно.
к предыдущему моему посту: объявление аналогичное, но работает как надо
4kpt_V
alexgreg
Вы читаете вообще что я пишу?
alexgreg
4kpt_V
Вы читаете вообще что я пишу?
Онлайн
конечно
4kpt_V
Что из того, что я написал Вам не понятно?
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB