Изменение значения атрибута класса изменяемого и индексируемого типа если имя атрибута доступно через строковую переменную/константу
Коллеги! Дан класс, в котором есть атрибут типа список или словарь. Задача: изменить один из элементов этого списка/словаря, но при том, что название атрибута доступно нам через строковую переменную или строковую константу. Я знаю один способ с применением встроенного объекта __dict__:
class MyClass:
def __init__(self):
self.attr: dict[str, int] = {'key1': 5,
'key2': 7,
'key3': 42}
my_class = MyClass()
attr_name = 'attr'
print(my_class.attr['key2'])
my_class.__dict__[attr_name]['key2'] = 12
print(my_class.attr['key2'])
Вопрос:
Насколько такой способ является допустимым? Есть ли другие, более адекватные способы?
Ответы (1 шт):
Для операций с атрибутами лучше использовать встроенные функции delattr, hasattr, getattr, setattr.
Причина в том, что объекты в Python не обязаны хранить атрибуты в __dict__. Производные типы могут переопределять доступ к атрибутам, перегрузив методы __getattr__, __get_attribute__, __delattr__, __setattr__. Встроенные функции {has,get,set,del}attr умеют обращаться с такими объектами.
Для вашего примера:
class MyClass:
def __init__(self):
self.attr: dict[str, int] = {'key1': 5,
'key2': 7,
'key3': 42}
my_class = MyClass()
attr_name = 'attr'
print(getattr(my_class, attr_name)['key2'])
getattr(my_class, attr_name)['key2'] = 12
print(my_class.attr['key2'])
Результат
7
12
В примере я не использую setattr для обновления значения атрибута, так как словарь хранит данные по ссылке, и можно присваивать значения ключам напрямую getattr(my_class, attr_name)['key2'] = 12.