Python闭包和替换周围的scop

2024-05-16 04:58:42 发布

您现在位置:Python中文网/ 问答频道 /正文

我知道在使用Groovy闭包时,我可以更改闭包上的delegate,这样就可以在外部定义闭包中的函数调用。在

我可以用Python做类似的事情吗?在

具体来说,如果您使用以下代码:

def configure():
  build()

def wrap(function):
  def build():
    print 'build'

  function()

wrap(configure)

我希望它打印“build”(只对wrap()进行更改)。在

注意事项:

我不想将函数传递到configure()中,因为configure()可能会调用大量函数。在

我也不想全局地定义它们,因为,再一次,可能有大量的函数可以被configure()调用,而且我不想污染全局命名空间。在


Tags: 函数代码build定义configuredeffunction全局
3条回答

是否是一个好的方法是值得商榷的,但是这里有一个解决方案,它不会修改全局名称空间。在

def configure():
  build()

def wrap(f):
  import new
  def build():
    print 'build'

  new.function(f.func_code, locals(), f.func_name, f.func_defaults, f.func_closure)()

wrap(configure)

我在How to modify the local namespace in python找到的

这在没有元编程的情况下是可行的。让configurebuild函数作为参数:

def default_build():
    print "default build"

def configure(build_func=None):
    build_func = build_func or default_build
    build_func()

def wrap(func):
    def build():
        print "wrap build"

    func(build)

wrap(configure)

这种方式使得configure函数的行为可以改变。在

您也可以摆弄configure所看到的名称空间来做一些更像我所理解的Groovy所做的事情:

^{pr2}$

如果你觉得自己疯了,那么看看this article about dynamic scoping。在

基本上,其思想是修改函数的字节码(使用byteplay模块),并将所有严格意义上不属于局部范围的引用替换为具有局部作用域的引用。要说明基本概念(在Python伪代码中):

code = byteplay.extractcode(function)
newbytecode = []

for opcode, arg in code.code:
    if opcode in (NONLOCAL_CODES):
        opcode = LOCAL_EQUIVALENT

    newbytecode.append((opcode, arg))

code.code = newbytecode

return code.to_code()

比这稍微复杂一些,但是这篇文章提供了一些很好的信息。在

他还建议不要在生产中使用它。:天

相关问题 更多 >