Однострочник для указания множества переменных для «del» и игнорирования тех, которые не существуют

Я использую Spyder для исследовательского анализа данных, а не для производственного кода. Мне нравится думать о своем сценарии как о последовательности основных разделов. В конце каждого раздела я хочу удалить временные объекты, чтобы обозреватель переменных в Spyder не был слишком перегружен. Однако существующие объекты зависят от потока управления через код. Если у меня есть только один оператор «del» в конце каждого раздела для удаления всех объектов, которые могут появиться независимо от потока управления через код, я получаю NameError для тех объектов, которые не были созданы.

Есть ли простой однострочник, который я могу использовать, похожий на del a,b,c,d, но не выдающий ошибку, если некоторые переменные не существуют? Мне нужна короткая строка, потому что я не хочу отвлекать внимание от основных функций кода.

На мой взгляд, блок try/Exception — это многострочная управляющая структура, которая вносит в код слишком много когнитивного шума. Что-то вроде следующего кажется незаконным, и похоже, что однострочный текст не может состоять из оператора if внутри цикла for:

# Syntax error at the "if"
for vName in ['gbCluster']: if vName in locals(): del locals()[vName]

# Works without "if"
for vName in ['gbCluster']: del locals()[vName]

Я не знаком со Spyder – важно ли, чтобы это была одна строка, чтобы ее можно было получить из поиска по истории, или…? В любом случае, globals().pop(vName, None) в вашем цикле — это типичный способ удалить ключ, только если он существует.

Ry- 09.07.2024 21:32

Не по делу, но вы не должны изменять locals(). Вместо этого используйте globals().

wjandrea 09.07.2024 21:33

@wjandrea: Спасибо! Ваш комментарий побудил меня узнать, что пространство имен REPL является глобальным, как описано здесь

user2153235 09.07.2024 21:39

@Ry: Спасибо! Я не полагаю, что можно избежать цикла for для извлечения нескольких переменных/объектов? Послесловие: Кажется невозможным. Я думаю, переменная цикла сохранится без дополнительного del. Ничего страшного. Вы хотели опубликовать свой комментарий в качестве ответа?

user2153235 09.07.2024 21:49
{globals().pop(k, None) for k in 'abcd'} не оставит переменную цикла в пространстве имен.
wim 10.07.2024 03:12

«В конце каждого раздела я хочу удалить временные объекты, чтобы проводник переменных в Spyder не был слишком перегружен». Рассматривали ли вы возможность просто использовать ряд функций? Передавайте переменные, которые вы хотите сохранить, из одного блока в другой в качестве параметров (или глобальных переменных), а остальные определите в области действия функции.

tobias_k 10.07.2024 14:39

@tobias_k: Я обнаружил, что для исследовательского анализа данных я часто переделываю код, поэтому мне бы хотелось избежать дополнительной постоянной перенастройки сигнатур функций и вызовов функций.

user2153235 10.07.2024 16:54

@wim: Спасибо! Отлично! (Не так хорошо, как команда без ошибок del, но такой команды не существует). Стоит ли публиковать в качестве ответа?

user2153235 10.07.2024 17:06

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

wim 10.07.2024 17:39

@wim: ОК. Что ж, вот шаблон кода, который я использовал на основе вашего примера: _ = {globals().pop(vNm,None) for vNm in ('cat','horse') }. Присвоение _ скрывает вывод Spyder Explorer.

user2153235 11.07.2024 16:41
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
10
149
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Что-то вроде

for name in [n for n in somelist if n in someplace]: del someplace[name]

должно сработать

Это работает, если someplace является существующей dict, но не для переменных с произвольными именами (globals() можно использовать в некоторых случаях, но locals() будет работать только в глобальной области видимости, где это эквивалентно globals()).

ShadowRanger 09.07.2024 23:42

Я знаю, я оставляю эту часть открытой для заполнения ОП. Вопрос был больше о том, как написать однострочный текст, чем о том, как удалять переменные.

Walter Tross 10.07.2024 14:27

Спасибо, вот шаблон кода, который я нашел работающим: for vNm in [ ifNm for ifNm in ['dog','cat','ifKeep1innerSpc'] if ifNm in globals() ]: del globals()[vNm]. Это действительно укрепило мое шаткое понимание понимания списков.

user2153235 10.07.2024 17:14

да, это точно такой же шаблон кода, как тот, который я предложил

Walter Tross 12.07.2024 11:46
Ответ принят как подходящий

Используйте функцию! Вы можете передать пространство имен (dict), из которого вы хотите удалить имена (ключи), и функция сможет выполнить тяжелую работу по удалению и игнорированию ошибок. Затем вы можете поместить функцию в модуль для повторного использования.

Кстати, имена, которые вы хотите удалить, являются глобальными, а не локальными как таковыми (и в любом случае вам не следует изменять locals()).

def del_keys_noerror(d, *keys):
    for key in keys:
        try:
            del d[key]
        except KeyError:
            pass  # Ignore keys that are already absent

Например:

a = False
if a:
    b = 0

del_keys_noerror(globals(), 'a', 'b')

Результат: a удаляется.

P.S. Я мог бы добавить регистрацию в журнал, когда имя уже неопределенно или успешно удалено, на всякий случай, если вам нужно отладить функцию.

wjandrea 10.07.2024 05:53

@wjandrea: Спасибо. Я думаю, что это может быть наиболее практичным на данный момент. Другие ответы и комментарии демонстрируют умные и гибкие акробатические трюки, которые помогли мне с Python, но вызов функции для удаления из глобальных переменных требует наименьшего количества накладных расходов в основной части кода.

user2153235 10.07.2024 17:20

Он не удаляет глобальные переменные (имена по-прежнему будут существовать), но если ваша цель — просто освободить память объектов, на которые они ссылаются, существует умная однострочная программа, позволяющая установить для всех таких имен значение None (поэтому ссылка на name по-прежнему будет работать, но будет содержать None, а не какой-то огромный объект, который там раньше был):

globals().update(dict.fromkeys(("names", "to", "clear")))

dict.fromkeys принимает итерацию ключей и быстро создает простой dict с этими ключами, сопоставляя их все с None (если вы передадите второй аргумент, он будет использовать его вместо этого). globals().update(...) затем массово обновляет словарь глобальных переменных. На самом деле это создаст переменные, если они еще не существовали (со значением None), но если вас беспокоит освобождение памяти, а не очистка глобального пространства имен от лишних имен (обычно это не важно), это работает так же хорошо (и, вероятно, быстрее). для загрузки, поскольку он выполняет обе операции массово на уровне C).

Спасибо, но я вообще-то пытаюсь минимизировать загрязнение в Spyder's Variable Explorer. Я храню много DataFrame, поэтому все промежуточные переменные, используемые для их построения, должны быть del.

user2153235 10.07.2024 22:13

Другие вопросы по теме