我有一个具有子功能的函数,我想初始化子函数内部的变量。简单地说,
file = "foo"
def outerFunction():
def innerFunction():
var1 = 0
var2 = 1
var3 = 2
print file, var1, var2, var3
file = "bar"
innerFunction()
outerFunction()
输出:bar 0 1 2
但是,我在多个不同的文件中有相当多的变量,我想在调用子函数时将它们简单地导入到子函数中。假设我有一个文件bar.py
,其中包含以下内容:
var1=0
var2=1
var3=2
然后我将我的代码更改为
file = "foo"
def outerFunction():
def innerFunction():
from file import *
print file, var1, var2, var3
file = "bar"
innerFunction()
outerFunction()
这会导致错误,因为当您在子功能中使用import
时,Python 2.7不喜欢它。因此,我们可以直接使用__import__
函数:
file = "foo"
def outerFunction():
def innerFunction():
__import__(file)
print file, var1, var2, var3
file = "bar"
innerFunction()
outerFunction()
这里的导入方法有效,但变量实际上并没有进入子函数的变量列表,导致我打印出来时出错。现在,我知道我可以将代码更改为
file = "foo"
def outerFunction():
def innerFunction():
f = __import__(file)
print file, f.var1, f.var2, f.var3
file = "bar"
innerFunction()
outerFunction()
它将起作用桃子。不过,这不是我想要的解决方案。我希望能够导入这些函数,而无需更改我的其余代码以适应。这个问题有更好的解决方案吗?
答案 0 :(得分:0)
从可维护性的角度来看,导入模块然后引用模块的变量是最佳选择。很容易看出变量的来源。
from module import *
不受欢迎,因为它很难跟踪变量的来源,特别是如果多个模块包含具有相同名称的变量。 from module import *
在函数中是不可能的,因为局部变量在Python中的工作方式。局部变量存储在堆栈中,如果Python不知道将有多少变量,那么它就无法正确地在堆栈上分配空间。
然而,那说,你可以做你所要求的。但你不应该。这背后的想法是将变量引用为全局变量,并在函数启动时相应地更新全局变量。例如
from importlib import import_module
file_ = "foo"
def outer():
def inner():
m = import_module(file_) # import module whose name is the contents of file_
globals().update(m.__dict__) # add module's globals to our own
print(file_, var0, var1, var2)
file_ = "bar"
inner()
outer()
这是一个可怕的想法,因为每个内部函数将共享同一组全局变量,并且可能覆盖具有相同名称的变量。如果同时运行inner
函数,或者它们覆盖定义outer
的模块所需的变量,则会导致问题。可以通过修改每个inner
函数来使用它自己独特的全局变量来克服这一点,但这是一个可怕的黑客攻击,主要包括显示这是如何可能的。
from importlib import import_module
from types import FunctionType
file_ = "foo"
def outer():
def inner():
m = import_module(file_)
globals().update(m.__dict__)
print(file_, var0, var1, var2)
# redefine inner with new globals
inner = FunctionType(inner.__code__,
dict(import_module=import_module, __builtins__=__builtins__), # new globals
inner.__name__, inner.__defaults__, inner.__closure__
)
file_ = "bar"
inner()
outer()