我正在尝试开发一个模块,它会自动将我的参数转换为python对象,并创建一个包含参数和对象的字典。如果找到@name @。
给出的参数名称,则模块的更多内容必须替换参数值这里是代码和最后的例子。
#FILE convertor.py
import types
is_lambda = lambda value : isinstance(value, types.LambdaType) and value.__name__ == '<lambda>'
def builder(tree, target, item, delimiter):
if delimiter not in item:
return item
result = ''
copir = item.split(delimiter)
for prefix,var in map(None,copir[::2],copir[1::2]):
if prefix is not None: result += prefix
if var is None: continue
lmdcheck = is_lambda(tree[var])
if lmdcheck or delimiter is '@':
result += target+"[\""+var+"\"]"
elif delimiter is '$':
result += str(tree[var])
else:
return None
return result
def resolve_name(tree, target, item):
"""
Resolves links and string in RHS of parameters
"""
# Resolve links First
result = ''
bld = builder(tree, target, item , '@')
if bld is None: return None
result = bld
# And then Resolve strings
bld = builder(tree, target, result, '$')
if bld is None: return None
result = bld
return unicode(result)
def generate(params, target, parent=None):
"""
@function generate generate recods in root initial directory
@param params - list of (name, value) records
@param target - string of variable name which will be generate (need for lambda(s)),
@param parent - methodtree object which will be updated
"""
if parent is None:
try:
exec target+"= {}"
except BaseException as e:
self.error("Cannot create target object self.{}: {}".format(target,e),"generate")
return None
else:
try:
exec target+"= parent"
except BaseException as e:
self.error("Cannot create target object self.{}=parent: {}".format(target,e),"generate")
return None
try:
exec "tree = "+target
except BaseException as e:
error("Cannot create temporal variable tree for return target object:".format(e),"generate")
for name, value in params:
value = resolve_name(tree, target,value)
try:
exec "{}[\'{}\']={}".format(target,name,value)
except BaseException as e:
error("Cannot execute operation self.{}[\'{}\']={}: {}".format(target,name,value,e),"generate")
return None
return tree
if __name__ == "__main__":
params=[
['parameter', '3'],
['Varibale X','5'],
['Pwered X','@Varibale X@**@parameter@'],
['FunctionA','lambda x,p:x**p'],
['FunctionB', 'lambda k:@FunctionA@(k,$parameter$)']
]
dic = generate(params,'dic')
for n in dic:
print n, dic[n], type(dic[n])
if n == 'FunctionA':
print "FunctionA:", dic[n](2,3)
if n == 'FunctionB':
print "FunctionB:", dic[n](2)
所以如果我运行python convertor.py
,一切都会完美运行$ python convertor.py
FunctionA <function <lambda> at 0x7ff116246848> <type 'function'>
FunctionA: 8
Varibale X 5 <type 'int'>
FunctionB <function <lambda> at 0x7ff1162468c0> <type 'function'>
FunctionB: 8
parameter 3 <type 'int'>
Pwered X 125 <type 'int'>
但是当我从convertor.py导入generate时,嵌套的lambda函数不起作用。
#File test.py
from convertor import generate
params=[
['FunctionA','lambda x,p:x**p'],
['parameter', '3'],
['FunctionB', 'lambda k:@FunctionA@(k,$parameter$)']
]
dic = generate(params,'dic')
for n in dic:
print n, dic[n], type(dic[n])
if n == 'FunctionA':
print "FunctionA:", dic[n](2,3)
if n == 'FunctionB':
print "FunctionB:", dic[n](2)
FunctionA <function <lambda> at 0x7fe037994848> <type 'function'>
FunctionA: 8
FunctionB <function <lambda> at 0x7fe0379948c0> <type 'function'>
FunctionB:
Traceback (most recent call last):
File "runner.py", line 14, in <module>
print "FunctionB:", dic[n](2)
File "<string>", line 1, in <lambda>
NameError: global name 'dic' is not defined
我在SO中找不到任何类似的主题,但它可能是重复的。
我可能理解为什么会这样。我只是想知道这有什么解决方案吗?
答案 0 :(得分:2)
Python的全局变量不是真正的全局变量:它们基于每个模块。此外,函数会记住定义它们的模块,并在那里查找任何全局引用,而不是在它们被调用的模块中。
因此,您生成的lambdas在convertor.py的命名空间中被exec
编辑,并将尝试在那里查找dic
。可能的解决方案是向generate()
添加一个参数,指定要用于全局名称的上下文:您的代码生成语句看起来像exec <something> in context
。您通常会为此参数传递globals()
,以使用调用模块的全局变量。