Приоритет атрибута .__dict__ между «типом» и другими классами?

#python #python-3.x

#python #python-3.x

Вопрос:

В следующем простом коде Python:

 >>> class C:
...  class_level_var = 5
...
>>> C.__dict__
mappingproxy({'__module__': '__main__', 'class_level_var': 5, '__dict__': <attribute '__dict__' of
'C' objects>, '__weakref__': <attribute '__weakref__' of 'C' objects>, '__doc__': None})
>>> #trying to reassign C.__dict__:
... C.__dict__ = None
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
AttributeError: attribute '__dict__' of 'type' objects is not writable
>>>
 

Вызов __dict__ on C соединяется с __dict__ of type , хотя C сам имеет прямое __dict__ отношение к нему, как показано в выводе выше: « '__dict__': <attribute '__dict__' of 'C' objects> «. Обратите внимание на сообщение об ошибке при присвоении None , указывающее, что атрибут принадлежит type , а не C ‘s.

Мой вопрос: не должны ли атрибуты объектов (class C ) иметь приоритет над их атрибутами класса (class type )?

Ответ №1:

Вы неправильно интерпретируете сообщение об ошибке.

Вы думаете, что сообщение об ошибке ссылается на атрибут type.__dict__ , но когда оно говорит

 AttributeError: attribute '__dict__' of 'type' objects is not writable
 

это означает, что __dict__ атрибут экземпляров type недоступен для записи. C сам по себе является экземпляром type , и его __dict__ атрибут недоступен для записи.

Возможно, вы также захотите прочитать о протоколе дескриптора. Поиск атрибута для __dict__ атрибута объекта управляется дескриптором для __dict__ в классе объекта или классе-предке. Поскольку C это экземпляр type , поиск C.__dict__ управляется дескриптором, принадлежащим type . Этот дескриптор управляет тем, что происходит, когда вы читаете или (пытаетесь) записать атрибут, и это то, что говорит, что вы не можете назначить C.__dict__ .

'__dict__': <attribute '__dict__' of 'C' objects> Запись, которую вы видели в C.__dict__ , нет C.__dict__ ; это дескриптор, который управляет __dict__ атрибутом экземпляров C .

Комментарии:

1. Я полностью осознаю, что это дескриптор. И дескриптор, который (type.__dict__) является тем, что здесь оценивается, а не тем, что в классе C. Сообщение об ошибке здесь имеет общий смысл. «Сам C является экземпляром типа» — я согласен. «и его атрибут dict недоступен для записи». — Нет, я не думаю, что это тот, он ссылается на атрибут «type», который по-разному переводится для разных объектов, т. Е. Причина, По которой используется дескриптор.

2. атрибут @Searcherer: C __dict__ недоступен для записи, потому что дескриптор для C.__dict__ (который является дескриптором в type.__dict__ , а не дескриптором в C.__dict__ ) говорит, что он недоступен для записи. Вы ожидаете, что дескриптор in C.__dict__ будет использоваться по какой-то причине? Это неправильный дескриптор. '__dict__' Запись в C.__dict__ не C __dict__ является атрибутом.

3. Вы не знаете правил для дескрипторов данных? __dict__ дескрипторы — это дескрипторы данных, и дескриптор данных, найденный при поиске в классе объекта, имеет приоритет над всем, что найдено в собственном dict объекта. В данном случае это означает, что дескриптор, найденный в type.__dict__ , имеет приоритет над '__dict__' записью в C.__dict__ при поиске C.__dict__ атрибута.

4. Вероятно, мне следует углубиться в дескрипторы, прежде чем углубляться в это и тратить ваше время. .. при необходимости отправит ответ. Я ценю ваше руководство (-: