Я хотел реализовать наивные пространства имен, чтобы я мог выполнять такие запросы:
create_namespace(namespace, parent)
- добавить новое пространство имен в родительское пространство имен add_var(namespace, var)
- добавить новую переменную в namespace get_var(namespace, var)
- вернуть ближайшее пространство имен, в котором содержится переменная
В конце концов мне удалось реализовать первые два из них, и теперь я могу создать древовидную структуру, например:
d = {'global':{'vars': {'a'},'local':{'foo': {'vars': set(), 'local': {'foo1': {'vars': {'a'}, 'local': {}}}}, 'bar': {'vars': set(), 'local': {'foo2': {'vars': set(), 'local': {}}}}, 'baz': {'vars': set(), 'local': {'foo3': {'vars': {'a'}, 'local': {'foobar': {'vars': set(), 'local': {}}}}}}}}}
Чтобы уточнить:
get_var("foobar", "a")
должен вернуться "foo3"
get_var("foo2", "a")
должен вернуться "global"
Но я застрял полностью пытаясь понять, как работает рекурсия и почему иногда мы возвращаем рекурсивный вызов , а иногда просто вызываем функцию внутри себя (inte rnet не помогает, потому что я уже сыт по горло fibonacci и factorial ).
Эта реализация не работает, потому что, как я сказал, я просто не могу понять, почему мои возвращаемые значения теряются, когда callstack не набран:
def get_var(namespace, var):
def go_deeper(dic, location=None):
if dic == {} or location == namespace:
return location
for (name, ns) in dic.items(): #iterate over namespaces within parent namespace
if var in ns["vars"]:
go_deeper(ns["local"], name) #if we found variable *var* we remember its location by passing it as an argument
else:
go_deeper(ns["local"], location) #otherwise we keep using previous found *location*
return go_deeper(d)