У меня есть модуль (module2), который содержит одну функцию:
#module2
def get_items():
return {'thing1': 'string_value',
'thing2': 1,
'thing3': 'self.foo1',
'thing4': 'self.foo2.bar',
'thing5': 'self.foo3.bar['some_key']'}
Как видно, ключи словаря являются строками, значения включают в себя строки и целые числа, но также атрибуты (т. Е. self.foo1
), вложенные атрибуты (т. Е. self.foo2.bar
) и ссылки dict внутри вложенного атрибута (т. Е. * 1006). *) написано в виде строк. Они написаны как строки, потому что в контексте module2 нет self, скорее я бы хотел импортировать этот словарь в другой модуль (module1) и сослаться на некоторое self.
Мне известно, что я могу получить доступ к атрибутам через getattr(self, value.split('self.')[1]
.
Я настроил рекурсивную функцию для получения вложенных атрибутов, которая в приведенном ниже коде называется «rgetattr».
Единственное, что я не могу понять, это как обращаться с вложенным словарем.
Конкретно, мне бы хотелось следующее поведение:
#module2
def get_items():
return {'thing1': 'string_value',
'thing2': 1,
'thing3': 'self.foo1',
'thing4': 'self.foo2.bar',
'thing5': 'self.foo3.bar['some_key']'}
#module1
Class my_class:
def __init__(self, foo):
self.foo = foo # Note that this foo is an object
### The following is how I would like the imported dictionary to look ###
my_desired_dict = {'thing1': 'string_value',
'thing2': 1,
'thing3': self.foo1,
'thing4': self.foo2.bar
'thing5': self.foo3.bar['some_key']}
### The following is how I am attempting to achieve this ###
import module2
item_dict = module2.get_items()
my_desired_dict = {}
for i in item_dict:
if type(item_dict[i])==str and item_dict[i].startswith('self.'):
variable = item_dict[i].split('self.')[1]
this_attr = rgetattr(self, variable)
else:
this_attr = item_dict[i]
my_desired_dict[i] = this_attr
def rgetattr(obj, attr, *args):
def _getattr(obj, attr):
return getattr(obj, attr, *args)
return functools.reduce(_getattr, [obj] + attr.split('.'))
Я был бы открыт к изменению «строк ссылок на атрибуты» в module2 на простой self.foo и т. Д., Если бы был способ сделать это без запуска NameError.