如何在python中修改本地名称空间 [英] How to modify the local namespace in python

查看:250
本文介绍了如何在python中修改本地名称空间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在python中修改函数的本地名称空间?我知道在函数内部调用locals()时会返回该函数的本地名称空间,但是我想这样做(我有一个理由想在无法访问g的情况下执行此操作,但是给它更快一个简单,愚蠢的例子来说明问题):

def g():
   pass

def f():
    g()

f.add_to_locals({'g':g})

解决方案

您有两个选择.首先,请注意,示例中的g实际上不是函数的局部变量(即未在函数内部分配),而是全局变量(即未分配给局部变量).这意味着将在定义函数的模块中查找它.这很幸运,因为无法在外部更改本地语言(缺少修补字节码),因为它们是在函数运行时分配的,而不是在运行之前分配的. /p>

一个选择就是简单地将您的函数注入到函数模块的命名空间中.这将起作用,但会影响该模块中访问变量的每个函数,而不仅仅是一个函数.

要只影响一个功能,您需要将func_globals指向其他位置.不幸的是,这是一个只读属性,但是您可以通过重新创建具有相同主体但具有不同全局名称空间的函数来完成您想要的事情:

import new
f = new.function(f.func_code, {'g': my_g_function}, f.func_name, f.func_defaults, f.func_closure)

f现在将是相同的,除了它将在提供的字典中查找全局变量.请注意,这将重新绑定整个全局名称空间-如果那里有可以查找 的变量,请确保也提供它们.不过,这也相当hacky,可能不适用于cpython以外的其他python版本.

How can I modify the local namespace of a function in python? I know that locals() returns the local namespace of the function when called inside it, but I want to do something like this (I have a reason why I want to do this where g is not accessible to f, but it's quicker to give a trivial, stupid example to illustrate the problem):

def g():
   pass

def f():
    g()

f.add_to_locals({'g':g})

解决方案

You've a couple of options. First, note that g in your example isn't actually a local to the function (ie. not assigned within it), it's a global (ie hasn't been assigned to a local variable). This means that it will be looked up in the module the function is defined in. This is fortunate, as there's no way of altering locals externally (short of patching the bytecode), as they get assigned when the function runs, not before.

One option is simply to inject your function into the function's module's namespace. This will work, but will affect every function in that module that accesses the variable, rather than just the one function.

To affect just the one function, you need to instead point that func_globals somewhere else. Unfortunately, this is a read-only property, but you can do what you want by recreating the function with the same body, but a different global namespace:

import new
f = new.function(f.func_code, {'g': my_g_function}, f.func_name, f.func_defaults, f.func_closure)

f will now be indentical, except that it will look for globals in the provided dict. Note that this rebinds the whole global namespace - if there are variables there that f does look up, make sure you provide them too. This is also fairly hacky though, and may not work on versions of python other than cpython.

这篇关于如何在python中修改本地名称空间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆