python - 有没有办法访问用装饰器定义的Python函数的 namespace ?

标签 python namespaces python-decorators

假设我使用缓存装饰器来定义一个新函数,如下所示:

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

调用函数 triple 四次会产生以下输出:

>>> triple(1)
{}
3
>>> triple(2)
{1: 3}
6
>>> triple(2)
6
>>> triple(4)
{1: 3, 2: 6}
12

我的理解是,函数triple可以访问本地称为cache的字典,因为该字典存在于triple所在的命名空间中> 已定义。该字典无法在外部全局范围内直接访问。

是否可以通过函数triple的某种属性来访问这个cache字典?

注意:我想知道是否可以在不通过诸如 cache_funcy.cache = cache 之类的方式显式地将 cache 设为 triple 的属性的情况下执行此操作code> 在 cached 的定义中。

最佳答案

实际上,这个字典没有存储在函数的本地命名空间中,它是一个自由变量,因此它存储在函数闭包中。 在 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__

关于python - 有没有办法访问用装饰器定义的Python函数的 namespace ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52960922/

相关文章:

python - 按一列分组并在另一列中唯一

python - 将 Pandas 数据框切片到包含值的所有列的第一个实例

python - 从 pandas 数据框中绘制条形图

php - 命名空间适用于一个类,但不适用于其他类

Django CMS apphook 命名空间

Django - 如何运行表单模板(获取 ' namespace not registered error ' )

python - 更改嵌套函数装饰器中的值

python - 在python中使用装饰器时出现位置参数错误

Python:执行Windows Tracert

python - 为什么我们在这个装饰器中返回 None ?