#python #python-3.x
#python #python-3.x
Вопрос:
Проблема в том, что запуск exec() для переменной с именем именованного аргумента не работает при нормальной работе программы, но установка точки останова и выполнение рассматриваемой строки кода в том же месте, похоже, работают.
Воспроизведение проблемы следует:
"""
LEGACY CODE, CANNOT CHANGE
vvvvvvvvvvv
"""
from collections import namedtuple
class A_Object(namedtuple('A_object', 'parameter_a' ' parameter_b')):
def __new__(cls, *args, **kwargs):
init = super(A_Object, cls).__new__(cls, parameter_a=[], parameter_b=[])
return init
"""
^^^^^^^^^^^
LEGACY CODE, CANNOT CHANGE
"""
def _remove_all_data(self):
for field in self._fields:
print("removing field:", field)
# This does not work in the normal execution of the program,
# but if you set a break point and execute the same command in the python console ( in Pycharm ) it works.
exec('self = self._replace({0}=[])'.format(field))
return self
def driver():
a = A_Object()
a.parameter_a.append('a')
a.parameter_a.append('b')
a.parameter_a.append('c')
a.parameter_b.append(1)
a.parameter_b.append(2)
a.parameter_b.append(3)
# Try to remove all data from properties.
a = a._remove_all_data()
tmp = a._asdict()
for k in tmp.keys():
for i in range(0, len(tmp[k])):
print('{}[{}]='.format(k,i), tmp[k][i])
if __name__ == '__main__':
driver()
Этот минимально воспроизводимый пример покажет, что запуск программы приведет к выводу содержимого parameter_a и parameter_b (в этом проблема). Желаемым результатом будет parameter_a, а parameter_b будет пустым списком. Если вы поставили точку останова в exec('self = self._replace({0}=[])'.format(field))
строке и во время отладки откройте консоль python в pycharm и запустите эту строку кода « exec('self = self._replace({0}=[])'.format(field))
» в консоли. она очистит параметры_a и paramter_b (давая желаемый результат).
Комментарии:
1. вы не можете изменять локальные переменные с
exec
помощью /eval
. Вы не должны использоватьexec
здесь в первую очередь2. Но очевидно, что это не совсем тот случай, если я могу использовать exec для изменения локальных переменных в консоли python. И я согласен, что в этом случае лучше не использовать exec / eval.
3. Нет, вы не можете, в Python 3. Консоль отладчика отличается от обычной среды (на самом деле она уже используется
exec
…)4. Спасибо, я этого не знал.
Ответ №1:
Вам это не нужно exec
: если вам нужен аргумент ключевого слова с динамическим именем, используйте **kwargs
синтаксис. Вы также можете заменить все поля одновременно, вместо того, чтобы вызывать _replace
несколько раз в цикле:
def _remove_all_data(self):
return self._replace(**{ f: [] for f in self._fields })
Комментарии:
1. Я забыл
**
, когда я впервые усталkwargs
проходить. Это решается для желаемого результата / результата. Спасибо. Прежде чем я отмечу это как ответ, знаете ли вы, почему exec ведет себя так странно, что не работает в этой программе?2. @Theisen вы читали документацию для exec ? она предупреждает вас, что изменения локальных переменных не будут работать.
3. Это не странное поведение — это ожидаемое поведение.
exec
не изменяет значения локальных переменных, таких какself
. Как советуют документы дляexec
функции: «Передайте явный словарь locals, если вам нужно увидеть влияние кода на locals после возврата функции exec()».