Python (3) свойство класса странность - PullRequest
0 голосов
/ 21 февраля 2020

Примечание Обновлено в соответствии с запросом сокращенного кода и вопроса. Надеюсь, это поможет.

Я пытаюсь понять различные способы, которыми можно создавать свойства класса (например, как @property для атрибутов экземпляра, но для атрибутов / переменных класса). Я опробовал некоторые предложения здесь (например, Использование свойства () для методов класса и Как создать свойство класса? ).

Короче , похоже, что использование методологии метакласса, рекомендованного для Python 3.x в " Использование свойства () для методов класса ", приводит к тому, что атрибут фактически не сохраняется (см. результаты теста). Мне интересно, допустил ли я ошибку или кто-то мог объяснить, почему я вижу ожидаемое и правильное поведение.

Обратите внимание, что код из " Как сделать свойство класса?", кажется, ведет себя так, как я и ожидал, но я проверил" лучший "ответ в" Как создать свойство класса?", и он не ведет себя так, как я ожидал.

Код

Пытаясь разобраться, я написал тестовый код для метода мета-класса, указанного для Python 3.x:

Выход

Some_Inst is a SomeClass
 - Some_Inst.class_prop = 'Set with Some_Inst.class_prop', Some_Inst.__class__.class_prop = 'Set with Some_Inst.class_prop'
 - SomeClass.class_prop = 'Set with Some_Inst.class_prop', SomeClass.__class__.class_prop = 'No Such Attribute'
 - Some_Inst.class_attr = 'Set with Some_Inst.class_prop', Some_Inst.__class__.class_attr = 'Set with Some_Inst.class_prop'
 - SomeClass.class_attr = 'Set with Some_Inst.class_prop', SomeClass.__class__.class_attr = 'No Such Attribute'
 - Some_Inst.inst_attr = 'Set with Some_Inst.inst_prop', Some_Inst.__class__.inst_attr = 'SomeClass Default inst_attr'
 - SomeClass.inst_attr = 'SomeClass Default inst_attr', SomeClass.__class__.inst_attr = 'No Such Attribute'
 - Some_Inst.inst_prop = 'Set with Some_Inst.inst_prop', Some_Inst.__class__.inst_prop = '<property object at 0x7fdc48c594a8>'
 - SomeClass.inst_prop = '<property object at 0x7fdc48c594a8>', SomeClass.__class__.inst_prop = 'No Such Attribute'
 - SomeClass.inst_prop.__get__() = 'SomeClass Default inst_attr'
 - Some_Inst.meta_attr = 'SomeClassMeta.__init__() set meta_attr', Some_Inst.__class__.meta_attr = 'SomeClassMeta.__init__() set meta_attr'
 - SomeClass.meta_attr = 'SomeClassMeta.__init__() set meta_attr', SomeClass.__class__.meta_attr = 'SomeClassMeta Default meta_attr'
 - Some_Inst.meta_prop = 'Set with Some_Inst.meta_prop', Some_Inst.__class__.meta_prop = 'SomeClassMeta.__init__() set meta_attr'
 - SomeClass.meta_prop = 'SomeClassMeta.__init__() set meta_attr', SomeClass.__class__.meta_prop = '<property object at 0x7fdc48c59908>'
 - Some_Inst.norm_attr = 'Set with Some_Inst.norm_prop', Some_Inst.__class__.norm_attr = 'SomeClass Default norm_attr'
 - SomeClass.norm_attr = 'SomeClass Default norm_attr', SomeClass.__class__.norm_attr = 'No Such Attribute'
 - Some_Inst.norm_prop = 'Set with Some_Inst.norm_prop', Some_Inst.__class__.norm_prop = '<property object at 0x7fdc48c596d8>'
 - SomeClass.norm_prop = '<property object at 0x7fdc48c596d8>', SomeClass.__class__.norm_prop = 'No Such Attribute'
 - SomeClass.norm_prop.__get__() = 'SomeClass Default norm_attr'

Вопросы

  • Почему SomeClass.inst_prop и SomeClass.norm_prop возвращают property(), тогда как все другие property() в классе или экземпляре ведут себя как ожидалось (даже после первого создания) ?
  • Я думал, что целью метакласса было создание свойства Class. Почему тогда установка Some_Inst.meta_prop = "Set with Some_Inst.meta_prop" меняет значение экземпляра, но не значение класса? Обратите внимание, что Some_Inst.class_prop ведет себя так, как я думал.

1 Ответ

1 голос
/ 21 февраля 2020

Поскольку вы существенно изменили вопрос, вот новый ответ.

- Some_Inst.inst_prop = 'Set with Some_Inst.inst_prop', Some_Inst.__class__.inst_prop = '<property object at 0x000002062A3C9B38>'

Как свойство экземпляра Some_Inst, оценка Some_Inst.inst_prop возвращает вам значение свойства, а оценка Some_Inst.__class__.inst_prop get Вы, что inst_prop для класса: собственность. Это свойство определено в классе, поэтому оно разрешается в его значение для экземпляра и в свойство для класса.

То же самое верно для norm_prop в контексте вашего первого вопроса.

Что касается второго вопроса: «Я думал, что целью метакласса было создание свойства Class. Почему тогда установка Some_Inst.meta_prop = "Set with Some_Inst.meta_prop" изменяет значение экземпляра, но не значение класса?»

Потому что Some_class не имеет атрибута meta_prop, пока вы не назначите его с помощью Some_Inst.meta_prop = "Set with Some_Inst.meta_prop". meta_prop - это свойство, которое вы определили в мета-классе, но поскольку SomeClass не наследуется от SomeClassMeta (оно просто имеет мета-класс), оно не включено в SomeClass.

Почему вы хотите использовать мета-классы для определения свойств класса, а не просто определить их в классе? По словам Тима Питерса:

"Метаклассы - это более глубокие маги c, чем могут волноваться 99% пользователей. Если вам интересно, нужны ли они вам, это не так (люди, которые действительно нуждаются в них") знаю с уверенностью, что они им нужны, и не нужно объяснять, почему). "

Эта статья имеет отличное дальнейшее объяснение: https://realpython.com/python-metaclasses/

...