Як очистити всі змінні в середині сценарію Python?


86

Я шукаю щось подібне до "clear" у Matlab: команда / функція, яка видаляє всі змінні з робочої області, звільняючи їх із системної пам'яті. Чи існує така річ у Python?

EDIT: Я хочу написати сценарій, який у певний момент очистить всі змінні.


2
Буде корисно, якщо ви змінили заголовок на щось на кшталт "Як очистити всі змінні в середині сценарію Python?" для майбутніх пошуків за темою, оскільки "Як перезапустити вікно команд у Python?" не має нічого спільного з тим, про що ви насправді просите.
Сем Долан

Чи можете ви надати будь-який можливий контекст, у якому це має сенс?
S.Lott

2
Це схоже на черговий випадок спроби перенести звички кодування з рідного середовища в те, де вони не мають жодного сенсу.
Гленн Мейнард,

Якщо вас просто турбують якісь масивні об’єкти (зображення чи інші величезні масиви), ви можете delїх отримати, коли закінчите. Якщо ви просто стурбовані тим, що простір імен захаращений, вам, мабуть, слід переглянути свій дизайн, використовуючи стільки імен. Наприклад, для серії перетворень зображення дотримання кожного проміжного кроку, мабуть, непотрібне.
Nick T

3
@ S.Lott: дослідницький науковий аналіз у консолі. Часто трапляється багато небажаних змінних (після того, як випробувати щось, а потім вирішити, що це не є відповідним шляхом). Але в цьому випадку відповідь Джона Ла Роя є найбільш підходящою.
naught101

Відповіді:


69

Наступна послідовність команд видаляє кожне ім'я з поточного модуля:

>>> import sys
>>> sys.modules[__name__].__dict__.clear()

Я сумніваюся, що ви насправді хочете це зробити, оскільки "кожне ім'я" включає всі вбудовані файли, тому після такого повного знищення ви не можете багато чого зробити. Пам'ятайте, у Python насправді не існує поняття "змінна" - є об'єкти різного роду (включаючи модулі, функції, клас, числа, рядки, ...), і є імена , прив'язані до об'єктів; послідовність - це видалення кожного імені з модуля (відповідні об’єкти зникають тоді і тільки тоді, коли кожне посилання на них щойно було видалено).

Можливо, ви хочете бути більш виборчим, але важко вгадати, що саме ви маєте на увазі, якщо не хочете бути більш конкретними. Але, лише для прикладу:

>>> import sys
>>> this = sys.modules[__name__]
>>> for n in dir():
...   if n[0]!='_': delattr(this, n)
... 
>>>

Ця послідовність залишає лише імена, які є приватними чи магічними, включаючи __builtins__ спеціальну назву, що містить усі вбудовані імена. Отже, вбудовані файли все ще працюють - наприклад:

>>> dir()
['__builtins__', '__doc__', '__name__', '__package__', 'n']
>>> 

Як бачите, ім'я n(керуюча змінна в цьому for) також трапляється (оскільки воно forкожного разу перезаписується в реченні), тому, можливо, буде краще назвати цю змінну управління _, наприклад, щоб чітко показати "це спеціальний "(плюс, в інтерактивному інтерпретаторі ім'я _все одно перев'язується після кожного повного виразу, введеного в підказці, до значення цього виразу, тому воно не буде триматися довго ;-)

У всякому разі, як тільки ви визначили , що саме це є ви хочете зробити, це не важко визначити функцію для цієї мети і покласти його в файл для запуску (якщо ви хочете його тільки в інтерактивних сесіях) або файл сайт-підганяє ( якщо це потрібно у кожному сценарії).


2
Ну, ви завжди можете залишити копію оригінального словника під час запуску, а потім видалити додані імена;) Однак я думаю, що це явне зловживання динамічною системою, і я не можу подумати про безглузду ситуацію, щоб зробити це в.
моноцери

5
Ха - ха, це блискуче ... Це дивно , як багато функціональності ви втрачаєте, роблячи це, і все ж , скільки функціональності ви можете отримати назад, роблячи такі речі , як int = (2).__class__, str = ''.__class__, і True = (1 == 1)т.д ...
Chinmay Kanchi

@monoceres, як би ти назвав цю копію і куди її сховав, щоб вона теж не зникла? -)
Алекс Мартеллі

2
Чим більше я використовую Python, тим більше я його люблю. Це не тільки чудова мова, ви також можете годинами просто возитись з нею і
змушувати

1
Можливо, я зрозумів це неправильно, але зіткнувся з однією проблемою: коли for n in dir(): ... if n[0]!='_': delattr(this, n)в якийсь момент використовуєш n=thisі видаляєш у циклі! Отже, на наступній ітерації з’являється помилка під час спроби, delattr(this,n)оскільки ви щойно видалили її! :) Отже, це не працює коректно
Mikhail_Sam

60

Ні, вам найкраще перезапустити перекладач

IPython є чудовою заміною вбудованого інтерпретатора і має %resetкоманду, яка зазвичай працює


1
Під "ні" ви маєте на увазі, що я не повинен цього робити або що це неможливо? Якщо ви скажете, що я не повинен цього робити, ви можете пояснити, чому?
snakile

6
+1: Мені потрібно менше чверті секунди, щоб ctrl-dпотім pyt-> tabповернутися до перекладача. Немає жодної причини робити тут щось фантастичне.
Сем Долан

3
% скидання працює для більшості змінних, для деяких - ні. Для мене лише перезапуск перекладача гарантує очищення всього.
artemis_clyde

3
Використовуйте, %reset -fщоб бути неінтерактивним. stackoverflow.com/questions/38798181/…
Йоахім Вагнер

27

Якщо ви пишете функцію, то як тільки ви залишите її, всі імена всередині зникнуть.

Концепція називається простором імен, і вона настільки хороша, що перетворилася на дзен Python :

Простори імен - одна чудова ідея - давайте зробимо ще більше!

Простір імен IPython також можна скинути за допомогою магічної команди %reset -f. ( -fЗначить "сила"; іншими словами, "не питайте мене, чи дійсно я хочу видалити всі змінні, просто зробіть це").


Додам очевидне: якщо ви розміщуєте все усередині головної функції (включаючи імпорт), ви отримуєте на практиці робоче місце, яке ви можете скинути, просто вийшовши з цієї функції. Я вважаю, що це справді те, для чого було призначене питання.
Девід

8
from IPython import get_ipython;   
get_ipython().magic('reset -sf')

3
Будь ласка, подивіться « Як відповісти»
Адоніс

1
або просто%reset -sf
त्वेव जयते

1
насправді, команда% reset -sf не працює і видає помилку, коли ви запускаєте скрипт python із підказкою anaconda (навіть коли ви використовували try-, за винятком; він не працює). Ви можете спробувати те саме, і побачите. Але використання бібліотеки ipython вирішить цю проблему в усіх можливих випадках.
Анураг Гупта

5

Це модифікована версія відповіді Алекса. Ми можемо зберегти стан простору імен модуля та відновити його, використовуючи наступні 2 методи ...

__saved_context__ = {}

def saveContext():
    import sys
    __saved_context__.update(sys.modules[__name__].__dict__)

def restoreContext():
    import sys
    names = sys.modules[__name__].__dict__.keys()
    for n in names:
        if n not in __saved_context__:
            del sys.modules[__name__].__dict__[n]

saveContext()

hello = 'hi there'
print hello             # prints "hi there" on stdout

restoreContext()

print hello             # throws an exception

Ви також можете додати рядок "clear = restoreContext" перед викликом saveContext () і clear () буде працювати як matlab's clear.


1
Чудова відповідь! Я вважаю, що для Python 3 ви захочете налаштувати restoreContext names = list(sys.modules[__name__].__dict__.keys()), інакше Python скаржиться на те, що ви змінили розмір словника під час ітерації через його dict_keysоб’єкт.
Сем Бадер

Крім того, для тих, хто хоче importвідповісти на цю відповідь (тобто я це зберег і імпортую з блокнота Jupyter, щоб очистити простір імен між різними проблемами в домашньому завданні), я думаю, ви захочете використовувати "__main__"замість __name__.
Сем Бадер

3

У Spyder можна налаштувати консоль IPython для кожного файлу Python для очищення всіх змінних перед кожним виконанням у меню Run -> Configuration -> General settings -> Remove all variables before execution.


2

globals()Функція повертає словник, де ключі є іменами об'єктів , які ви можете назвати (і цінність, до речі, є ids цих об'єктів) exec()функція приймає рядок і виконує її , як якщо б ви просто наберіть в консолі пітона. Отже, код є

for i in list(globals().keys()):
    if(i[0] != '_'):
        exec('del {}'.format(i))

Хоча цей фрагмент коду може вирішити питання, включення пояснення допомагає поліпшити якість Вашої відповіді. Пам’ятайте, що ви будете відповідати на запитання для читачів у майбутньому, і ці люди можуть не знати причин вашої пропозиції коду.
Stefan

Дякую. Зараз краще?
Колай.


0

Чи не найпростіший спосіб створити клас, що підтримує всі необхідні змінні? Тоді у вас є один об’єкт з усіма змінними curretn, і якщо вам потрібно, ви можете замінити цю змінну?

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.