2017-01-09 4 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. Значение 1-го поля в подсписка (связанный с ключом) должна быть новой глобальной переменной.

  2. Значение второго поля в подсписке (связанное с ключом) должно быть выполнено. Он импортирует переменную из моего текстового редактора 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_ словарь итерацию, что приводит к DEF для п в importlist: если п в vimvar: Exec («глобальный»+ vimvar [п] [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() Dict (если вы действительно нужен был глобальной переменной):

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

Большое спасибо. Да Мне нужны глобальные переменные, потому что они мне нужны в другом скрипте (не python). Что я не понимаю в вашем решении (btw это, похоже, не работает в моем скрипте) заключается в том, что вы берете как «ключ» первое значение в подсписке и как «val» второе значение в подсписке. Глобалы должны быть 1-м значением в подсписке и 2-ом значении в подсписке должно быть выполнено так: 'global gCASE' и' gCASE = vim.eval ("g: CASE") ' – Reman

+0

Какая ошибка вы получаете? Предполагая, что инструкции 'vim.eval()' в порядке, код должен работать так, как вы хотите. –

+0

(Я отредактировал для ясности, слово «ключ», возможно, запуталось). Вы можете установить глобальные переменные на консоли python, чтобы увидеть это в действии: 'globals() ['gCASE'] = 1234' –

1

Проблема заключается в строке

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

Я думаю, что вы запутались индексации словаря: вы пытались использовать Вэл в качестве индекса, и что просто не имеет смысла. Например, один из ваших ссылок расширяется:

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

Во-первых, вы не можете использовать список в качестве словаря ключ - это то, что «unhashable» проблема. Во-вторых, в словарных ключах нет такого элемента.

Возможно, вам просто нужно val [0] в этой точке? Поскольку вы делаете некоторые забавные вещи, я не уверен, чего вы хотите достичь. Поскольку TigerHawk уже указал, присвоение глобального такого способа, как правило, является плохой практикой.

+0

Tnx Prune: я хочу выполнить в вышеприведенном случае 'global gCASE' и 'gCASE = vim.eval (" g: CASE ")' и т. д. – Reman

2

Есть много проблем

  • одна петля слишком много в словаре, desyncing значения
  • с помощью exec и global, когда вы только выполнять вызовы vim.eval команды.

Я бы бросить все, что exec материал и повторно сделать двигатель оценки ВИМ:

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 вычитается. Не уверен, что он будет охватывать все ваши команды, но, конечно, дает некоторые идеи.

Затем данные не хранятся в переменных, но в словаре переменных: пример:

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

вы можете получить доступ к нему очень легко, и это не связано с плохой практикой кодирования.

+0

Jean-François, чтобы избежать глобалов, я создал словарь как ваш, но как мне вернуть словарь? return 'dictionary name' не работает: Ошибка: «имя словаря» не определен. – Reman

+0

просто верните 'результаты'. Это словарь. –

+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 
Смежные вопросы