如何从字典中分配全局变量?

时间:2017-01-09 20:00:41

标签: python python-3.x dictionary vim global-variables

这是我的字典:

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字典中的键存在。

如果是:

  1. 子列表中的第一个字段(与密钥关联)的值必须是新的全局变量。

  2. 必须执行子列表中第二个字段的值(与密钥关联)。它从我的texteditor vim导入一个变量。

  3. 我创建了这段代码以实现上述目标:

      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',不可用的类型列表

    我错了什么?

4 个答案:

答案 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)

这里有很多问题

  • 字典中的一个循环,desyncing values
  • 仅在执行exec命令调用时使用globalvim.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