Я не знаю, есть ли «правильный» ответ на это - причина в том, что для большинства из этих объектов можно жить счастливо, не прикрепляя дополнительные атрибуты к их экземплярам, - и стоимость наличия __dict__
это просто не стоит.
Можете ли вы представить, что у int
s у Python __dict__
с? Для каждого числа, кроме 80-байтовых байтов, будет создан еще один 200-байтовый объект, чтобы можно было иметь атрибуты, привязанные к их «42»?
Кроме того, для неизменяемых классов, таких как кортежи, строки и т. Д., Один и тот же экземпляр может быть повторно использован в разных контекстах - __dict__
в одном случае может создать, казалось бы, не связанный экземпляр одного и того же объекта для внезапного появления атрибутов .
Кроме того, указанный вами класс os.stat_result
является именованным кортежем - он должен быть неизменным и компактным.
Таким образом, помимо размера и стоимости ресурсов для создания __dict__
для большинства объектов, существует также проблема кодирования: они обычно изначально кодируются (т.е. записываются на C) - и атрибут e __dict__
должен быть явно созданные - так что в отличие от классов, написанных на Python - нужно стараться изо всех сил, чтобы разрешить __dict__
в этих классах, в то время как для кода Python обход заключается в том, чтобы избежать __dict__
.
И, наконец, когда сообщество, разрабатывающее язык, приходит к выводу, что в объекте, имеющем __dict__
, будет какое-то явное преимущество, он может быть включен. Это произошло с самим типом объекта Function некоторое время назад - и теперь функции могут иметь атрибуты, прикрепленные к ним декораторами, и это может найти хорошее применение.
Хотя если вам нужен код, прикрепляющий дополнительные атрибуты к одному классу, вы можете сделать это по старинке, просто наследовать этот класс и преобразовать в него свой объект. (Я только что обнаружил, что os.stat_result
- это , а не named_tuple, и его нельзя использовать в качестве базового класса - извините за это - так что завернуть его в простой класс может быть самой простой вещью, которую нужно сделать :
class MyStatResult:
def __init__(self, stat_result):
self.stat = stat_result
def __repr__(self):
return "Wrapper for" + repr(self.stat)
Теперь, если ваша цель - извлечь заголовки / значения полей как диктовку, а не добавлять к ней дополнительные атрибуты - самоанализируемая часть этих объектов задается dir
- в случае os.stat_result
fieds у этого вопроса есть хороший префикс:
stat = os.stat(path)
stat_dict = lambda path: {name: getattr(stat, field) for field in dir(stat) if field.startswith("st_")}
В Python 3.8, благодаря PEP 572, можно написать это как хороший вкладчик:
stat_dict = lambda path: {name: getattr(stat, field) for field in dir(stat:=os.stat(path)) if field.startswith("st_")}