Превратите ключи словаря в имена переменных с одинаковыми значениями в Python из файлов Matlab.mat с помощью scipy.io.loadmat

Я пытаюсь взять базовый словарь temp = {'key':array([1,2])}, загруженный из файла.mat с scipy.io.loadmat. Превратите ключи в файле словаря Python, возвращаемые loadmat(), в имена переменных со значениями, совпадающими с соответствующими ключами.

Так, например:

temp = {'key':array([1,2])}

превратился в

key = array([1,2])

Я знаю, как получить ключи с помощью temp.keys(). Затем захватить элементы легко, но как заставить список строк в temp.keys () быть именами переменных вместо строк.

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

ура

7 ответов

Решение

В python параметры метода могут передаваться как словари с ** магия:

def my_func(key=None):
   print key
   #do the real stuff

temp = {'key':array([1,2])}

my_func(**temp)

>>> array([1,2])

Лучше всего использовать temp['key'], Однако, чтобы ответить на вопрос, вы можете использовать exec функция. Преимущества такого подхода состоят в том, что вы можете делать это не нужно жестко кодировать имена переменных или ограничивать себя работой внутри функции.

from numpy import array,matrix

temp = {'key':array([1,2]),'b': 4.3,'c': 'foo','d':matrix([2,2])}

for k in temp:
    exec('{KEY} = {VALUE}'.format(KEY = k, VALUE = repr(temp[k])))

>>> key
array([1, 2])
>>> b
4.3
>>> c
'foo'
>>> d
matrix([[2, 2]])

ПРИМЕЧАНИЕ. Это будет работать только в том случае, если вы импортировали определенную функцию из модулей. Если вы не хотите этого делать из-за практики кода или огромного объема функций, которые вам необходимо импортировать, вы можете написать функцию для объединения имени модуля перед записью. Вывод такой же, как и в предыдущем примере.

import numpy as np,numpy

temp = {'key':np.array([1,2]),'b': 4.3,'c': 'foo','d':np.matrix([2,2])}

def exec_str(key,mydict):
    s = str(type(mydict[key]))
    if '.' in s:
        start = s.index("'") + 1
        end = s.index(".") + 1
        v = s[start:end:] + repr(mydict[key])
    else:
        v = repr(mydict[key])     
    return v

for k in temp:
    exec('{KEY} = {VALUE}'.format(KEY = k, VALUE = exec_str(k,temp)))

Хотя это не лучшая практика кода, она работает хорошо для всех примеров, которые я тестировал.

Лучшим способом может быть помещение данных в отдельный объект:

class attrdict(dict):
    def __getattr__(self, k): return self[k]
    def __setattr__(self, k, v): self[k] = v

somedict = {'key': 123, 'stuff': 456}

data = attrdict(somedict)
print data.key
print data.stuff

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

РЕДАКТИРОВАТЬ: оказывается, что материал ниже на самом деле не работает большую часть времени. Жаль, так много для магии.

Если вы хотите вмешаться в магию, вы можете сделать что-то вроде

locals().update(somedict)

Это будет нормально работать в интерактивном режиме, и вы даже можете скрыть доступ к locals() внутри функции загрузчика, возиться с sys._getframe().f_back.f_locals,

Однако это не будет работать в функциях:

def foo():
    locals().update({'a': 4})
    print a 

Дело в том, что a выше привязан к глобальной переменной во время компиляции, и поэтому Python не пытается искать его среди локальных переменных.

Ни один из приведенных выше ответов не помог мне с массивами numpy и другими не встроенными типами. Однако сделали следующее:

      import numpy as np
temp = {'a':np.array([1,2]), 'b': 4.3, 'c': 'foo', 'd':np.matrix([2,2])}
for var in temp.keys():
    exec("{} = temp['{}']".format(var, var))

Обратите внимание на порядок цитат. Это позволяет var обрабатываться как переменная в первом экземпляре, а затем как ключ во втором экземпляре, индексируясь в temp Словарь.

Конечно, обычные заявления об опасности exec() а также eval() все еще применяется, и вы должны запускать это только при вводе, которому вы абсолютно доверяете.

Как ответил hdhagman, использовать exec () проще. Я пишу более простой код.

temp = {'ключ':[1,2]}

for k, v in temp.items():
    exec("%s = %s" % (k, v))

печать (ключ) => [1,2]

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

Чтобы сохранить данные

      x1=[2,4,6,8,10]
x2=[1,3,5,7,9]
x3='hello world'
vars={'x1':'x1','x2':'x2','x3':'x3'}

file='test.pickle'
f = open(file,'wb')
for key in vars.keys():
    pickle.dump(eval(vars[key]),f)

del x1,x2,x3

прочитать из файла

      s = open(file,'rb')
for k in vars:
    exec('{KEY} = {VALUE}'.format(KEY = k, VALUE = repr(pickle.load(s))))

print(x1,x2,x3)

Хотя я бы просто рекомендовал использовать словарь напрямую и обращаться к таким массивам, как temp['key'], если вы знали все имена переменных заранее, вы могли бы написать функцию для извлечения их в отдельные переменные:

def func(**kwargs):
    return kwargs['a'],kwargs['b']


temp = {'a':np.array([1,2]),'b':np.array([3,4])}
a,b = func(**temp)
del temp # get rid of temporary dict
Другие вопросы по тегам