这是我的字典:
vimvar = {'startline' : [ 'startline' , 'int(vim.eval("s:StartLine"))' ],
'startline-1' : [ 'startline' , 'int(vim.eval("s:StartLine"))-1'],
'endline' : [ 'endline' , 'int(vim.eval("s:EndLine"))' ],
'gcase' : [ 'gCASE' , 'vim.eval("g:CASE")' ],
'akeyw' : [ 'akeyw' , 'vim.eval("a:keyw")' ]
}
这是我的清单:
importlist = ['startline', 'gcase', 'akeyw']
我想要做的是检查importlist
中的值是否作为vimvar
字典中的键存在。
如果是:
子列表中的第一个字段(与密钥关联)的值必须是新的全局变量。
必须执行子列表中第二个字段的值(与密钥关联)。它从我的texteditor vim导入一个变量。
我创建了这段代码以实现上述目标:
for n in importlist:
for key,val in vimvar.items():
if n in vimvar:
exec('global ' + vimvar[key][0])
exec(vimvar[val][0] + '=vimvar[val][1]')
但无论我做什么都会给出错误
未定义的变量' sa'
未定义的变量' gCASE',不可用的类型列表
等
我错了什么?
答案 0 :(得分:2)
两个问题:
首先,当你只需要循环一次时,你需要循环两次:
for n in importlist:
if n in vimvar:
name, val = vimvar[n]
...
其次,您不需要使用exec()
进行分配。分配给容器对象(推荐):
data = {}
for n in importlist:
if n in vimvar:
name, val = vimvar[n]
data[name] = exec(val)
或者更改globals()
字典(如果你真的需要它作为全局变量):
for n in importlist:
if n in vimvar:
name, val = vimvar[n]
globals()[name] = exec(val)
如果可以,请尽量避免将其存储在全局变量中。并且只对您可以信任的字符串使用exec()
,是否有任何理由说明此代码可能不在您的来源中?例如
vimvar = {
'startline': ['startline', int(vim.eval("s:StartLine"))],
'startline-1': ['startline', int(vim.eval("s:StartLine"))-1],
'endline': ['endline', int(vim.eval("s:EndLine"))],
'gcase': ['gCASE', vim.eval("g:CASE")],
'akeyw': ['akeyw', vim.eval("a:keyw")]
}
for n in importlist:
if n in vimvar:
name, val = vimvar[n]
globals()[name] = val
答案 1 :(得分:2)
这里有很多问题
exec
命令调用时使用global
和vim.eval
。我会删除所有exec
内容并重新启动vim评估引擎:
vimvar = {'startline' : [ 'startline' , "s:StartLine" , 0],
'startline-1' : [ 'startline' , 's:StartLine' , -1 ],
'endline' : [ 'endline' , "s:EndLine" , 0 ],
'gcase' : [ 'gCASE' , "g:CASE" ],
'akeyw' : [ 'akeyw' , "a:keyw" ]
}
importlist = ['startline', 'gcase', 'akeyw']
results = dict()
for n in importlist:
if n in vimvar: # key found in dict (no need for inner loop)
data = vimvar[n] # get value list
varname = data[0] # dict key name
command = data[1] # vim command to call
# call vim command
result = vim.eval(command)
if len(data)>2:
# perform optional conversion / offset, could work for string too
to_add = data[2]
result = type(to_add)(result) + to_add
# create dictionary entry
results[varname] = result
print(results)
请注意,字典现在只包含vim命令的参数。当需要转换/添加时,值列表中有一个额外的参数。如果它为0,则结果仅转换为整数,如果为-1,则转换为1,然后减去1。不确定它会覆盖你的所有命令,但肯定会提出一些想法。
然后,数据不存储在变量中,而是存储在变量字典中:example:
{'akeyw': 'something', 'gCASE': 'other', 'startline': 10}
您可以非常轻松地访问它,而且不会涉及糟糕的编码习惯。
答案 2 :(得分:1)
问题在于
exec(vimvar[val][0] + '=vimvar[val][1]')
我认为您对字典编制索引感到困惑:您尝试使用 val 作为索引,这没有任何意义。例如,您的一个参考扩展为:
vimvar[['akeyw', 'vim.eval("a:keyw")']]
首先,您不能使用列表作为字典键 - 这是"不可用的"问题是。其次,字典键中没有这样的元素。
也许你只想要 val [0] ?既然你做了一些有趣的事情,我不确定你想要完成什么。正如 TigerHawk 已经指出的那样,以这种方式分配全球通常是一种不良做法。
答案 3 :(得分:1)
以下是在没有global
或'global'
或exec
的情况下执行此操作的方式。
首先,如果您绝对需要一个全局变量并且无法保存返回值(函数为其调用者提供值的普通方式),请使用可变对象,如字典(请参阅{{3 }})。
其次,您要分配给那些全局变量的值(现在是您可以简单地改变的字典)可以是普通表达式而不是要添加到=
并使用exec
执行的字符串。 vimvar
字典中的值将是所需的“变量名称”(现在是一个键),您要使用的函数以及最终的偏移量。
my_global_dict = {}
def f():
vimvar = {'startline' : ["s:StartLine", (vim.eval, int), 0],
'startline-1' : ["s:StartLine", (vim.eval, int), -1],
'endline' : ["s:EndLine", (vim.eval, int), 0],
'gcase' : ["g:CASE", (vim.eval,), 0],
'akeyw' : ["a:keyw", (vim.eval,), 0]
}
importlist = ['startline', 'gcase', 'akeyw']
for k in importlist:
if k in vimvar:
s,funcs,offset = vimvar[k]
for func in funcs:
s = func(s)
if offset:
s += offset
my_global_dict[k] = s