Рассмотрим функцию
def path_to_obj(root_obj, attr_path):
obj = root_obj
for attr in attr_path:
obj = getattr(obj, attr)
return obj
, которая дает мне объект из спецификации root объекта и «путь к атрибуту», которая ведет себя следующим образом:
>>> class A:
... def foo(self, x): ...
... foo.x = 3
... class B:
... def bar(self, x): ...
...
>>> path_to_obj(A, ('foo',))
<function A.foo at 0x10f8f3ee0>
>>> path_to_obj(A, ('foo', 'x'))
3
>>> path_to_obj(A, ('B', 'bar'))
<function A.B.bar at 0x10f93f040>
быть обратным obj_to_path
этой функции?
Действительно, он сможет работать только с некоторыми типами (только с типами по ссылке?), Так что давайте просто придерживаться их. Вот пример того, как я бы это сделал:
def obj_to_path(obj):
if hasattr(obj, '__qualname__') and hasattr(obj, '__globals__'):
root_name, *attr_path = obj.__qualname__.split('.')
return obj.__globals__[root_name], tuple(attr_path)
else:
return obj
Что работает в некоторых случаях
for t in [(A, ('foo',)), (A, ('B', 'bar'))]:
assert obj_to_path(path_to_obj(*t)) == t
Но когда я использую глобальные переменные, я думаю про себя (словами Хеттингера) ... «Должен быть способ получше!».