Python: использование vars() для назначения строки переменной
Мне очень полезно иметь возможность создавать новые переменные во время выполнения и создавать словарь результатов для последующей обработки, т.е. записывать в файл:
myDict = {}
for i in range (1,10):
temp = "variable"+str(i)
vars()[temp] = myFunctionThatReturnsData() # variable1= data1, variable2 = data2,etc.
myDict[temp] = vars(temp)
который создает запись словаря [result1: data1], которую я могу вызвать с myDict [result1]. Я использую vars(), не понимая, что я делаю. Я принимаю его vars()
возвращает словарь с локальными переменными (?) И
vars() [x] = y
создает новую запись словаря [x: y]?
У меня есть script, где я передаю словарь, подготовленный с помощью {input1: data1, input2: data2}, и я использую этот метод для итерации по всем значениям, сохранения всех результатов и вывода их в файл, Этот бит кода находится внутри функции внутри класса и работает.
Мой источник недоразумений заключается в том, что я читал разные сообщения о том, как нельзя смириться с locals() и как vars() эквивалентен (?) locals() или globals()..
Итак, мой вопрос (по крайней мере) в два раза:
1.Что именно делает vars(), или, в частности, vars() [x] = y do,
2.Какой объем этого словаря (что мне нужно иметь в виду, когда пишу большие программы
3. Хорошая практика программирования.
Спасибо заранее!
Ответы
Ответ 1
Питонический способ создания последовательности переменных
Если вам нужна последовательность переменных, создайте последовательность. Вместо того, чтобы создавать независимые переменные типа:
variable0
variable1
variable2
variable3
Вы должны посмотреть на создание list
. Это похоже на то, что предлагает S.Lott(у S.Lott обычно есть хорошие советы), но более аккуратно отображает ваш цикл for
:
sequence = []
for _ in xrange(10):
sequence.append(function_that_returns_data())
(Обратите внимание, что мы отбрасываем переменную цикла (_
). Мы просто пытаемся получить 10 проходов.)
Затем ваши данные будут доступны как:
sequence[0]
sequence[1]
sequence[2]
sequence[3]
[...]
sequence[9]
В качестве дополнительного бонуса вы можете:
for datum in sequence:
process_data(datum)
Сначала вы можете подергивать, когда ваша последовательность начинается с 0. Вы можете пройти через различные искажения, чтобы ваши фактические данные начинались с 1, но это больнее, чем это стоит. Я рекомендую просто привыкнуть к спискам на основе нуля. Все вокруг них построено, и они начинают чувствовать себя довольно быстро.
vars() и locals()
Теперь, чтобы ответить на другую часть вашего вопроса. vars()
(или locals()
) обеспечивает низкий уровень доступа к переменным, созданным python. Таким образом, следующие две строки эквивалентны.
locals()['x'] = 4
x = 4
Объем vars()['x']
в точности совпадает с областью x
. Одна из проблем с locals()
(или vars()
) заключается в том, что она позволит вам помещать материал в пространство имен, которое вы не можете получить из пространства имен обычными способами. Таким образом, вы можете сделать что-то вроде этого: locals()[4] = 'An integer'
, но вы не можете получить это обратно, не используя locals снова, потому что локальное пространство имен (как и все пространства имен python) предназначено только для хранения строк.
>>> x = 5
>>> dir()
['__builtins__', '__doc__', '__name__', 'x']
>>> locals()[4] = 'An integer'
>>> dir()
[4, '__builtins__', '__doc__', '__name__', 'x']
>>> x
5
>>> 4
4
>>> locals()[4]
'An integer'
Обратите внимание, что 4 не возвращает то же самое, что и locals() [4]. Это может привести к неожиданным, трудным для отладки проблемам. Это одна из причин избежать использования locals()
. Другим является то, что в целом сложность заключается в том, чтобы делать вещи, которые python обеспечивает более простые, менее подверженные ошибкам способы выполнения (например, создание последовательности переменных).
Ответ 2
Сделайте это вместо этого. Это проще.
myDict = {}
for i in range (1,10):
temp = "variable"+str(i)
myDict[temp] = myFunctionThatReturnsData() # variable1= data1, variable2 = data2,etc.
Это все, что вам нужно делать.
Результаты будут myDict['variable1']
через myDict['variable9']
Вам редко нужно vars()
или locals()
. Просто прекратите использовать их и используйте обычные переменные и обычные словари. Старайтесь избегать вещей, которые вы не понимаете, и придерживайтесь простых, очевидных вещей.
Ответ 3
Из справки для vars,
вары (...) vars ([object]) → словарь
Without arguments, equivalent to locals().
With an argument, equivalent to object.__dict__.
Вы используете его без vars, поэтому давайте посмотрим на помощь для locals()
локальные (...) locals() → словарь
Update and return a dictionary containing the current scope local
переменные.
Итак, это отвечает на два первых вопроса. vars() возвращает словарь для локальных переменных, которые индексируются по имени переменной в виде строки. Область действия локальная.
Я не уверен в третьем вопросе, но это похоже на хак, который не является хорошим знаком. Я думаю, если вы будете осторожны в использовании этого только в правильной области, вы можете пройти с ним.
Ответ 4
jcdyer очень хорошо объясняет концепции, и Джастин Пил четко указывает, что делают vars()
и locals()
. Но небольшой пример всегда ускоряет понимание.
class Bull(object):
def __init__(self):
self.x = 1
self.y = "this"
def __repr__(self):
return "Bull()"
def test1(self):
z = 5
return vars()
def test2(self):
y = "that"
return vars(self)
def test3(self):
return locals()
def test4(self):
y = 1
return locals()
if __name__ == "__main__":
b = Bull()
print b.test1()
print b.test2()
print b.test3()
print b.test4()
print vars(b).get("y")
Результат:
{'self': Bull(), 'z': 5}
{'y': 'this', 'x': 1}
{'self': Bull()}
{'y': 1, 'self': Bull()}
this
Ответ 5
Я могу ответить на номер 3: это не хорошая практика программирования. Я не совсем понимаю, что вы пытаетесь выполнить, но я уверен, что есть более элегантный способ сделать это, не используя locals()
(что совпадает с vars()
в соответствии с help(vars)
в интерактивной оболочке Python).
Ответ 6
Использование vars/locals или globals таким образом (а) плохая практика и (б) не работает во всех случаях. Подробнее см. Динамически установить локальную переменную. Итог: просто используйте dicts - для чего они предназначены.