На самом деле, этот dict не хранится в локальном пространстве имен функции, это свободная переменная, поэтому он сохраняется в замыкании функции. В Python 2 рассмотрим:
In [1]: def cached(funcy):
...: cache = dict()
...: def cache_funcy(x):
...: if x in cache:
...: return cache[x]
...: else:
...: print cache
...: result = funcy(x)
...: cache[x] = result
...: return result
...: return cache_funcy
...:
...: @cached
...: def triple(x):
...: return 3*x
...:
In [2]: triple(1)
{}
Out[2]: 3
In [3]: triple(2)
{1: 3}
Out[3]: 6
А теперь:
In [5]: triple.func_closure
Out[5]:
(<cell at 0x10e4e7be8: dict object at 0x10e7ec910>,
<cell at 0x10e7b2590: function object at 0x10e81ede8>)
Первая ячейка содержит dict
, вторая ячейка содержит функцию, котораябыть украшенным (что также является свободной переменной).Итак, вы можете использовать:
In [6]: triple.func_closure[0].cell_contents
Out[6]: {1: 3, 2: 6}
In [7]: triple.func_closure[0].cell_contents[2] = 'foo'
In [8]: triple(2)
Out[8]: 'foo'
Обратите внимание, атрибуты функций в Python 3 немного отличаются, здесь есть прямой атрибут __closure__
, поэтому:
In [4]: triple.__closure__
Out[4]:
(<cell at 0x1026dbc78: dict object at 0x1028d1bd0>,
<cell at 0x1026dbf48: function object at 0x1028e59d8>)
И фактически, в Python 2, начиная с Python 2.6, эти атрибуты подчеркивания были добавлены для прямой совместимости, поэтому этот атрибут также существует, если вы не используете версию ниже Python 2.6.
Так что из соображений совместимости, вы, вероятно, должны использовать __closure__