2017-01-09 61 views
0

這是我的詞典:如何從字典中分配全局變量?

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中導入一個變量。

我創造了這個代碼來實現上述:

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]') 

但無論我做什麼它提供了錯誤

undefined variable 'sa'

undefined variable 'gCASE', unhashable type list

我是怎麼了?

+0

您是否有錯誤消息中指定的錯誤行? – nbro

+2

你做錯了什麼是用'exec'分配全局值。你有這樣一個很好的理由嗎? – TigerhawkT3

+1

一個大問題:問題在於你的循環中有太多循環。 您檢查是否'N'在字典中,然後使用_current_字典迭代,從而導致變形點焊 在importlist N: 如果n在vimvar: EXEC( '全球' + vimvar [N] [0]) exec('='。join(vimvar [n])) –

回答

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 
+0

非常感謝Will。是的,我需要全局變量,因爲我需要它們在另一個(非python)腳本中。它似乎不能在我的腳本中工作)是,你把'key'作爲子列表中的第一個值,'val'作爲子列表中的第二個值。全局必須是第一個值在子列表中,並且子列表中的第二個值必須像這樣被執行...'global gCASE'和'gCASE = vim.eval(「g:CASE」)' – Reman

+0

你得到了什麼錯誤?假設'vim.eval()'語句正常,代碼應該可以按你的需要工作。 –

+0

(我爲了清晰起見編輯過,'key'這個詞可能令人困惑)。你可以在python控制檯上設置全局變量來實現這個動作:'globals()['gCASE'] = 1234' –

1

的問題是線

exec(vimvar[val][0] + '=vimvar[val][1]') 

我想你混淆索引的字典:您嘗試使用VAL作爲索引,而只是沒有意義。例如,您引用的一個擴展爲:

vimvar[['akeyw', 'vim.eval("a:keyw")']] 

首先,你不能用一個列表作爲字典鍵 - 這就是「unhashable」問題是什麼。其次,字典鍵中沒有這樣的元素。

也許你只想val [0]在那一點?既然你在做一些有趣的事情,我不確定你想要完成什麼。由於TigerHawk已經指出,這種方式分配一個全球通常是一個壞習慣。

+0

Tnx Prune:我想要的是在上面的例子'global gCASE'中執行並且'gCASE = vim.eval(「g:CASE」)'' – Reman

2

有很多問題在這裏

  • 一個循環的字典太多,使用execglobal時,你只執行調用vim.eval命令desyncing值

我會放棄一切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。不知道它會覆蓋你的所有命令,但肯定會提供一些想法。

然後,數據不是存儲在變量,但在變量的字典:例如:

{'akeyw': 'something', 'gCASE': 'other', 'startline': 10} 

你可以很方便地訪問它,它不涉及壞的編碼實踐。

+0

讓 - 弗朗索瓦,爲了避免全局性我創建了一個像你這樣的字典,但我該如何返回字典?返回'字典名稱'不起作用:錯誤:'字典名稱'未定義。 – Reman

+0

只是返回'results'。這是字典。 –

+0

你的意思是沒有'迴歸'? – Reman

1

這裏是你如何做到這一點,沒有global'global'exec。首先,如果你絕對需要一個全局變量,並且你不能保存一個返回值(一個函數爲其調用者提供一個值的普通方式),可以使用一個可變對象,如字典(參見How do I create a variable number of variables?) 。其次,要分配給這些全局變量(現在是可以簡單變異的字典)的值可以是普通表達式而不是字符串,以便添加到=並使用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