2013-08-12 31 views
2

我想为Python制作一个@pure装饰器,其中一部分是可以选择性地禁止访问全局函数的作用域。更改字典作为函数的全局范围

有没有一种方法可以以编程方式更改哪个字典事件作为函数的全局/外部范围?

因此,例如在下面我想能够拦截fh中的访问并抛出错误,但我想允许访问g,因为它是纯函数。

def f(): 
    print("Non-pure function") 

@pure 
def g(i): 
    return i + 1 

@pure 
def h(i): 
    f() 
    return g(i) 

回答

5

你将不得不创建一个从旧的一个函数对象:

newfunc = type(h)(h.__code__, cleaned_globals, h.__name__, h.__defaults__, h.__closure__) 

这里,cleaned_globals是一个字典,将被用作新创建的函数的全局命名空间目的。所有其他参数都回显原来的功能。

cleaned_globals当然可以基于h.__globals__的副本。

演示:

>>> def h(i): 
...  f() 
...  return g(i) 
... 
>>> def g(i): 
...  return i + 1 
... 
>>> def f(): 
...  print("Non-pure function") 
... 
>>> h(1) 
Non-pure function 
2 
>>> cleaned_globals = {'g': g} 
>>> newfunc = type(h)(h.__code__, cleaned_globals, h.__name__, h.__defaults__, h.__closure__) 
>>> newfunc(1) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 2, in h 
NameError: global name 'f' is not defined 
>>> cleaned_globals['f'] = lambda: print('Injected function') 
>>> newfunc(1) 
Injected function 
2 
+0

你也许有一个链接到资源,我可以更多的阅读了这条? – JPvdMerwe

+1

正式记录创建新的函数对象;我用'help(type(f))'作为快速参考。 [datamodel文档](http://docs.python.org/3/reference/datamodel.html)是我对函数属性的指导,一个快速测试告诉我'.__ globals__'是as预期,只读。 –