มีวิธีลบตัวแปรฟังก์ชันและอื่น ๆ ที่สร้างขึ้นจากหน่วยความจำของล่ามหรือไม่?


115

ฉันค้นหาคำตอบที่ถูกต้องสำหรับคำถามนี้มาสองสามวันแล้ว แต่ก็ยังไม่มีอะไรดี ฉันไม่ใช่มือใหม่ที่สมบูรณ์ในการเขียนโปรแกรม แต่ยังไม่ถึงระดับกลาง

เมื่อฉันอยู่ในเชลล์ของ Python ฉันพิมพ์: dir()และฉันสามารถดูชื่อทั้งหมดของวัตถุทั้งหมดในขอบเขตปัจจุบัน (บล็อกหลัก) มีทั้งหมด 6 ชื่อ:

['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__']

จากนั้นเมื่อฉันประกาศตัวแปรx = 10มันจะเพิ่มลงในรายการวัตถุนั้นโดยอัตโนมัติภายใต้โมดูลในตัวdir()และเมื่อฉันพิมพ์dir()อีกครั้งมันจะแสดงในตอนนี้:

['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'x']

เช่นเดียวกับฟังก์ชันคลาสและอื่น ๆ

ฉันจะลบอ็อบเจ็กต์ใหม่ทั้งหมดโดยไม่ลบมาตรฐาน 6 ที่มีอยู่ในตอนต้นได้อย่างไร

ฉันได้อ่านที่นี่เกี่ยวกับ "การล้างหน่วยความจำ" "การล้างคอนโซล" ซึ่งจะลบข้อความทั้งหมดจากหน้าต่างพรอมต์คำสั่ง:

>>> import sys
>>> clear = lambda: os.system('cls')
>>> clear()

แต่ทั้งหมดนี้ไม่เกี่ยวข้องกับสิ่งที่ฉันพยายามจะบรรลุมันไม่ได้ทำความสะอาดวัตถุที่ใช้แล้วทั้งหมด


2
ทำไมคุณถึงรู้สึกว่าคุณต้องทำสิ่งนี้หรือคุณแค่ถามด้วยความอยากรู้อยากเห็น?
PM 2Ring

ฉันไม่รู้ว่ามีdelฟังก์ชั่นอยู่ที่นั่น ฉันเริ่มเรียนรู้ Python และมักจะต้องทดลองในเชลล์ดังนั้นชื่อตัวแปรมาตรฐานเช่นxหรือyมักจะถูกใช้งานอยู่แล้วและการรีสตาร์ทเชลล์จะใช้เวลาอีก 15 วินาทีในการทำ (ตอนนี้ฉันมีแล็ปท็อปเก่ามาก) ดังนั้นฉันจึงต้องการหาวิธีล้างหน่วยความจำ Python ให้เร็วขึ้น
funghorn

1
อา. FWIW delไม่ใช่ฟังก์ชันดังนั้นจึงไม่ใช่(และ). เป็นคำหลักที่แนะนำคำสั่ง del แน่นอนว่าการลบออบเจ็กต์อาจเกี่ยวข้องกับฟังก์ชัน แต่นั่นเป็นอีกเรื่องหนึ่ง ...
น. 2Ring

เมื่อทำการทดลองในชื่อเชลล์เช่นxหรือyไม่ควรใช้เว้นแต่คุณจะใช้ชื่อนั้น หรือถ้าคุณไม่ทำอะไรโง่ ๆ เช่นfrom _somemodule_ import *นั้นคุณจะได้รับขยะทุกประเภทที่รกรุงรัง :)
PM 2Ring

1
ฉันเข้าสู่คำถามนี้และตอนนี้ฉันสงสัย - ทำไมฉันไม่สามารถรีสตาร์ทเคอร์เนลและเรียกใช้สคริปต์จากด้านบนอีกครั้งได้หากฉันต้องการลบตัวแปรและฟังก์ชันทั้งหมดต่อไป
พเนจร

คำตอบ:


160

คุณสามารถลบชื่อแต่ละชื่อด้วยdel:

del x

หรือคุณสามารถลบออกจากglobals()วัตถุ:

for name in dir():
    if not name.startswith('_'):
        del globals()[name]

นี่เป็นเพียงตัวอย่างลูป การป้องกันจะลบเฉพาะชื่อที่ไม่ได้ขึ้นต้นด้วยเครื่องหมายขีดล่างโดยสร้างข้อสันนิษฐาน (ไม่ใช่แบบไม่มีเหตุผล) ว่าคุณใช้เฉพาะชื่อโดยไม่มีเครื่องหมายขีดล่างเมื่อเริ่มต้นในล่ามของคุณ คุณสามารถใช้รายชื่อแบบฮาร์ดโค้ดเพื่อเก็บไว้แทนได้ (รายการที่อนุญาตพิเศษ) หากคุณต้องการให้ละเอียด ไม่มีฟังก์ชั่นในตัวที่จะทำการเคลียร์ให้คุณนอกจากออกและรีสตาร์ทล่าม

โมดูลที่คุณนำเข้า ( import os) จะยังคงนำเข้าเนื่องจากมีการอ้างอิงโดยsys.modules; การนำเข้าในภายหลังจะใช้ออบเจ็กต์โมดูลที่นำเข้าแล้วซ้ำ คุณจะไม่มีการอ้างอิงถึงพวกเขาในเนมสเปซส่วนกลางปัจจุบันของคุณ


ฉันต้องบอกว่าstartswith('_')ดูเหมือนไร้เดียงสาทีเดียว หากมีใครฉลาดพอที่จะเขียน_foo=42หรือแม้แต่__foo__=42เราจะลบสิ่งเหล่านี้ได้อย่างไร มีวิธีรับชื่อคุณสมบัติโมดูลมาตรฐานโดยทางโปรแกรมหรือไม่?
georg

2
@georg: ฉันได้เข้ารหัสลูปป้องกันแล้ว คุณจะต้องฮาร์ดโค้ดรายชื่อเริ่มต้นเพื่อเก็บไว้หากคุณต้องการทำให้ดีขึ้น
Martijn Pieters

ไม่มีทาง? ความคิดของฉันเป็นdir(ModuleType())แต่เพียงผลตอบแทนและdoc name
georg

1
@georg: ไม่; namespace โลกของล่ามแตกต่างจากรุ่นถึงรุ่นเป็นอย่างดีและที่มีอยู่ไม่สามารถจะเข้าใจผิดวิธี (ที่ฉันรู้) ให้ระบุสิ่งที่อยู่ในมีเมื่อคุณเปิดล่ามในระยะต่อมา
Martijn Pieters

1
ฟังก์ชันและคลาสของ @nakE เป็นเพียงอ็อบเจกต์อื่น ๆ พวกเขาไม่พิเศษ ใช้รายการที่อนุญาตพิเศษหรือตรวจสอบประเภทวัตถุที่คุณต้องการเพื่อรักษาคลาสและฟังก์ชัน
Martijn Pieters

67

ใช่. มีวิธีง่ายๆในการลบทุกอย่างใน iPython ในคอนโซล iPython เพียงพิมพ์:

%reset

จากนั้นระบบจะขอให้คุณยืนยัน กด y หากคุณไม่ต้องการเห็นข้อความแจ้งนี้ให้พิมพ์:

%reset -f

น่าจะใช้ได้ ..


1
อีกครั้งทำไมถึงไม่เป็นคำตอบอันดับต้น ๆ
myradio

12
@myradio เนื่องจากไม่เกี่ยวข้องกับทุกคนที่ไม่ได้ใช้IPythonและมันก็ไม่ตอบคำถาม คำถามที่ถามวิธีการลบวัตถุอ้างอิงทั่วโลกได้ตั้งค่าเนื้อหาของIPython เปลือก
Andreas

17

คุณสามารถใช้ตัวเก็บขยะ python:

import gc
gc.collect()

6
เฮ้ @Fardin! ขอบคุณ! คำตอบของคุณได้ผลและช่วยวันของฉัน! แต่ก่อน gc.collect () ฉันทำ del (ตัวแปร)
Gmosy Gnaq

9

หากคุณอยู่ในสภาพแวดล้อมแบบโต้ตอบเช่นJupyterหรือipythonคุณอาจสนใจที่จะ ล้าง var ที่ไม่ต้องการหากพวกเขาเริ่มหนัก

คำสั่งเวทย์มนตร์reset และreset_selectiveสามารถใช้ได้ในเซสชัน python แบบโต้ตอบเช่น ipythonและJupyter

1) reset

reset รีเซ็ตเนมสเปซโดยลบชื่อทั้งหมดที่กำหนดโดยผู้ใช้หากเรียกโดยไม่มีอาร์กิวเมนต์

inและoutพารามิเตอร์ระบุว่าคุณต้องการล้างแคชเข้า / ออกหรือไม่ ประวัติไดเร็กทอรีถูกล้างด้วยdhistพารามิเตอร์

reset in out

อีกสิ่งหนึ่งที่น่าสนใจคือarrayลบอาร์เรย์ numpy เท่านั้น:

reset array

2) reset_selective

รีเซ็ตเนมสเปซโดยลบชื่อที่กำหนดโดยผู้ใช้ ประวัติอินพุต / เอาต์พุตจะเหลืออยู่ในกรณีที่คุณต้องการ

Clean Array ตัวอย่าง:

In [1]: import numpy as np
In [2]: littleArray = np.array([1,2,3,4,5])
In [3]: who_ls
Out[3]: ['littleArray', 'np']
In [4]: reset_selective -f littleArray
In [5]: who_ls
Out[5]: ['np']

ที่มา: http://ipython.readthedocs.io/en/stable/interactive/magics.html


6

สิ่งนี้ได้ผลสำหรับฉัน

คุณต้องเรียกใช้สองครั้งหนึ่งครั้งสำหรับคนทั่วโลกตามด้วยคนในพื้นที่

for name in dir():
    if not name.startswith('_'):
        del globals()[name]

for name in dir():
    if not name.startswith('_'):
        del locals()[name]

4

จริงๆแล้ว python จะเรียกคืนหน่วยความจำที่ไม่ได้ใช้งานอีกต่อไปสิ่งนี้เรียกว่าการรวบรวมขยะซึ่งเป็นกระบวนการอัตโนมัติใน python del variable_nameแต่ก็ยังคงถ้าคุณต้องการที่จะทำมันแล้วคุณสามารถลบได้โดย คุณสามารถทำได้โดยกำหนดตัวแปรให้None

a = 10
print a 

del a       
print a      ## throws an error here because it's been deleted already.

วิธีเดียวที่จะเรียกคืนหน่วยความจำจากออบเจ็กต์ Python ที่ไม่ได้อ้างถึงอย่างแท้จริงคือผ่านตัวรวบรวมขยะ คีย์เวิร์ด del เพียงแค่เลิกผูกชื่อจากอ็อบเจ็กต์ แต่อ็อบเจ็กต์ยังคงต้องถูกรวบรวมขยะ คุณสามารถบังคับให้ตัวรวบรวมขยะทำงานโดยใช้โมดูล gc แต่นี่เป็นการเพิ่มประสิทธิภาพก่อนกำหนด แต่ก็มีความเสี่ยงในตัวเอง การใช้delไม่มีผลจริงเนื่องจากชื่อเหล่านั้นจะถูกลบไปเมื่ออยู่นอกขอบเขต


แน่นอน. แน่นอนว่าเมื่อทำงานในชื่อเนมสเปซทั่วโลกของล่ามจะไม่อยู่นอกขอบเขต แต่อย่างใด :) ฉันเดาว่ามันคุ้มค่าที่จะกล่าวถึงสิ่งที่เกิดขึ้นกับหน่วยความจำที่ใช้โดยวัตถุที่เก็บรวบรวมขยะนั้นขึ้นอยู่กับการนำไปใช้งาน แต่ในการใช้งาน Python ส่วนใหญ่หน่วยความจำ gc'ed จะกลับไปที่พูล Python เท่านั้นมันจะไม่กลับไปที่ OS จนกว่าโปรแกรมจะออก
PM 2Ring

@ PM2Ring LOL :) ฉันคิดอย่างนั้น คุณอ้างถึง python จากที่ใด
d-coder

2
โปรดทราบว่าใน CPython จำเป็นต้องใช้ GC เพื่อทำลายวงจรการอ้างอิงเท่านั้น หากไม่มีการอ้างอิงใด ๆ วัตถุจะถูกลบออกจากหน่วยความจำ ดังนั้นdel ไม่มีผลจริงที่นี่
Martijn Pieters

@MartijnPieters ลบ insta? เป็นศัพท์เทคนิคหรือไม่? :)
ริกอา

2
@eryksun: ใช่ตามที่กำหนดโดย RFC 4042-bis2 แน่นอน! :-P
Martijn Pieters
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.