Làm cách nào để xóa tất cả các biến ở giữa tập lệnh Python?


84

Tôi đang tìm kiếm một cái gì đó tương tự như 'clear' trong Matlab: Một lệnh / hàm xóa tất cả các biến khỏi vùng làm việc, giải phóng chúng khỏi bộ nhớ hệ thống. Có một thứ như vậy trong Python không?

CHỈNH SỬA: Tôi muốn viết một tập lệnh mà tại một thời điểm nào đó sẽ xóa tất cả các biến.


2
Sẽ rất hữu ích nếu bạn thay đổi tiêu đề của mình thành một cái gì đó như "Làm cách nào để xóa tất cả các biến ở giữa tập lệnh Python?" cho các tìm kiếm trong tương lai về chủ đề này, bởi vì "Làm thế nào để khởi động lại cửa sổ lệnh trong Python?" không liên quan gì đến những gì bạn đang thực sự hỏi.
Sam Dolan

Bạn có thể cung cấp bất kỳ bối cảnh khả thi nào mà điều này có ý nghĩa không?
S.Lott

2
Nghe có vẻ giống như một trường hợp khác cố gắng chuyển thói quen viết mã từ môi trường bản địa của họ sang một nơi mà chúng không có ý nghĩa gì.
Glenn Maynard

Nếu bạn chỉ quan tâm đến một số đối tượng lớn (hình ảnh hoặc các mảng lớn khác), bạn có thể delthực hiện chúng khi hoàn thành. Nếu bạn chỉ lo lắng về việc không gian tên bị lộn xộn, bạn có thể nên xem xét lại thiết kế của mình khi sử dụng quá nhiều tên. Ví dụ, đối với một loạt các chuyển đổi hình ảnh, việc giữ lại mọi bước tạm thời có thể là không cần thiết.
Nick T

3
@ S.Lott: phân tích khoa học khám phá trong bảng điều khiển. Thông thường sẽ có nhiều biến số không mong muốn (sau khi thử mọi thứ và sau đó quyết định đó không phải là một con đường phù hợp). Nhưng trong trường hợp này, câu trả lời của John La Rooy là thích hợp nhất.
naught101

Câu trả lời:


69

Chuỗi lệnh sau sẽ xóa mọi tên khỏi mô-đun hiện tại:

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

Tôi nghi ngờ rằng bạn thực sự KHÔNG muốn làm điều này, bởi vì "mọi tên" bao gồm tất cả các cài đặt sẵn, vì vậy bạn không thể làm gì nhiều sau khi xóa sạch hoàn toàn như vậy. Hãy nhớ rằng, trong Python thực sự không có cái gọi là "biến" - có các đối tượng , thuộc nhiều loại (bao gồm mô-đun, hàm, lớp, số, chuỗi, ...), và có tên , liên kết với các đối tượng; những gì trình tự làm là xóa mọi tên khỏi một mô-đun (các đối tượng tương ứng sẽ biến mất nếu và chỉ khi mọi tham chiếu đến chúng vừa bị xóa).

Có thể bạn muốn chọn lọc hơn, nhưng thật khó để đoán chính xác ý của bạn trừ khi bạn muốn cụ thể hơn. Tuy nhiên, chỉ để đưa ra một ví dụ:

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

Chuỗi này chỉ để lại những cái tên riêng tư hoặc ma thuật, bao gồm cả __builtins__tên đặc biệt chứa tất cả các tên được tạo sẵn. Vì vậy, tích hợp sẵn vẫn hoạt động - ví dụ:

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

Như bạn thấy, tên n(biến điều khiển trong đó for) cũng xảy ra xung quanh (vì nó được liên kết lại trong formệnh đề mọi lúc mọi nơi), vì vậy, có thể tốt hơn nếu đặt tên cho biến điều khiển đó _, chẳng hạn, để hiển thị rõ ràng "nó đặc biệt "(ngoài ra, trong trình thông dịch tương tác, tên _vẫn được liên kết lại sau mỗi biểu thức hoàn chỉnh được nhập tại dấu nhắc, với giá trị của biểu thức đó, vì vậy nó sẽ không tồn tại lâu ;-).

Dù sao, một khi bạn đã xác định chính xác những gì nó bạn muốn làm, nó không phải là khó để định nghĩa một hàm cho mục đích này và đặt nó trong tập tin khởi động của bạn (nếu bạn muốn nó chỉ trong phiên tương tác) hoặc tập tin trang web tùy chỉnh ( nếu bạn muốn nó trong mọi tập lệnh).


2
Vâng, bạn luôn có thể giữ một bản sao của từ điển gốc khi khởi động và sau đó xóa các tên đã được thêm vào;) Tuy nhiên, tôi nghĩ rằng đây là một sự lạm dụng rõ ràng đối với hệ thống động và tôi không thể nghĩ ra tình huống vô nghĩa để làm điều này trong.
monoceres

5
Haha, đây là rực rỡ ... Đó là ngạc nhiên bao nhiêu chức năng bạn bị mất bằng cách làm này, nhưng có bao nhiêu chức năng mà bạn có thể lấy lại bằng cách làm những thứ như thế int = (2).__class__, str = ''.__class__, True = (1 == 1)vv ...
Chinmay Kanchi

@monoceres, làm thế nào bạn sẽ đặt tên cho bản sao đó và nơi bạn sẽ giấu nó vì vậy nó không được lau đi quá -?)
Alex Martelli

2
Tôi càng sử dụng Python, tôi càng yêu thích nó. Đây không chỉ là một ngôn ngữ tuyệt vời, bạn cũng có thể bỏ ra hàng giờ chỉ đơn giản là không quan trọng với nó và làm cho nó làm những điều bạn thực sự không nên ;-)
Chinmay Kanchi

1
Có thể tôi đã hiểu sai cách, nhưng tôi phải đối mặt với một vấn đề: khi bạn sử dụng for n in dir(): ... if n[0]!='_': delattr(this, n)một lúc nào đó n=thisvà bạn xóa nó trong vòng lặp! Vì vậy, ở lần lặp tiếp theo, bạn gặp Lỗi khi thử delattr(this,n)vì bạn vừa xóa nó! :) Vì vậy, nó không hoạt động một cách chính xác
Mikhail_Sam

60

Không, tốt nhất bạn nên khởi động lại trình thông dịch

IPython là một sự thay thế tuyệt vời cho trình thông dịch đi kèm và có %resetlệnh thường hoạt động


1
Ý bạn là tôi không nên làm điều đó hay là không thể? Nếu bạn nói tôi không nên làm điều đó, bạn có thể giải thích tại sao không?
snakile

6
1: Phải mất ít hơn một phần tư thứ hai cho tôi để ctrl-dsau đó pyt-> tabđể trở về người phiên dịch. Không có lý do gì để làm bất cứ điều gì ưa thích ở đây.
Sam Dolan

3
% reset hoạt động với hầu hết các biến, đối với một số biến thì không. Đối với tôi, chỉ khởi động lại trình thông dịch mới đảm bảo làm sạch mọi thứ.
artemis_clyde

3
Sử dụng %reset -fđể không tương tác. stackoverflow.com/questions/38798181/…
Joachim Wagner

27

Nếu bạn viết một hàm thì sau khi bạn để nó, tất cả các tên bên trong sẽ biến mất.

Khái niệm này được gọi là không gian tên và nó rất tốt, nó đã biến nó thành Zen của Python :

Không gian tên là một trong những ý tưởng tuyệt vời - hãy làm nhiều hơn nữa!

Không gian tên của IPython cũng có thể được đặt lại bằng lệnh ma thuật %reset -f. (Nghĩa -flà "lực lượng"; nói cách khác, "đừng hỏi tôi liệu tôi có thực sự muốn xóa tất cả các biến hay không, hãy làm điều đó.")


Tôi sẽ thêm một điều hiển nhiên: nếu bạn đặt mọi thứ bên trong một chức năng chính (bao gồm cả nhập khẩu) thì trên thực tế, bạn sẽ có một nơi làm việc mà bạn có thể đặt lại chỉ bằng cách thoát khỏi chức năng đó. Tôi tin rằng đó thực sự là những gì câu hỏi được dành cho.
David

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

3
Vui lòng xem Cách trả lời
Adonis

1
hoặc đơn giản%reset -sf
सत्यमेव जयते

1
trên thực tế, lệnh% reset -sf không hoạt động và gây ra lỗi, khi bạn chạy tập lệnh python của mình với dấu nhắc anaconda (ngay cả khi bạn đã sử dụng try- Ngoại trừ; nó không hoạt động). Bạn có thể thử tương tự và bạn sẽ thấy. Tuy nhiên, việc sử dụng thư viện ipython sẽ giải quyết vấn đề này, trong mọi trường hợp có thể.
Anurag Gupta

5

Đây là phiên bản sửa đổi của câu trả lời của Alex. Chúng tôi có thể lưu trạng thái của không gian tên của mô-đun và khôi phục nó bằng cách sử dụng 2 phương pháp sau ...

__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

Bạn cũng có thể thêm một dòng "clear = restoreContext" trước khi gọi saveContext () và clear () sẽ hoạt động giống như clear của matlab.


1
Câu trả lời chính xác! Tôi tin rằng đối với Python 3, bạn sẽ muốn tinh chỉnh restoreContext bằng names = list(sys.modules[__name__].__dict__.keys()), nếu không Python sẽ phàn nàn rằng bạn đã thay đổi kích thước từ điển trong khi lặp qua dict_keysđối tượng của nó .
Sam Bader

Ngoài ra, đối với những người muốn importcâu trả lời này (tức là tôi đã lưu câu trả lời này và tôi nhập câu trả lời này từ sổ ghi chép Jupyter để xóa không gian tên giữa các vấn đề khác nhau trong bài tập về nhà), tôi nghĩ bạn sẽ muốn sử dụng "__main__"thay thế __name__.
Sam Bader

3

Trong Spyder, người ta có thể cấu hình bảng điều khiển IPython cho mỗi tệp Python để xóa tất cả các biến trước mỗi lần thực thi trong Menu Run -> Configuration -> General settings -> Remove all variables before execution.


2

Các globals()hàm trả về một cuốn từ điển, nơi mà các phím là tên của đối tượng mà bạn có thể đặt tên (và giá trị, bằng cách này, là idcủa các đối tượng) Các exec()chức năng phải mất một chuỗi và thực thi nó như thể bạn chỉ cần gõ nó trong một con trăn console. Vì vậy, mã là

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

Mặc dù đoạn mã này có thể giải quyết câu hỏi, nhưng việc bao gồm giải thích sẽ giúp cải thiện chất lượng câu trả lời của bạn. Hãy nhớ rằng bạn đang trả lời câu hỏi cho người đọc trong tương lai và những người đó có thể không biết lý do cho đề xuất mã của bạn.
Stefan Crain

Cảm ơn bạn. Bây giờ có tốt hơn không?
Kolay.Ne

0

Trong IDE nhàn rỗi có Shell / Restart Shell. Cntrl-F6 sẽ làm điều đó.


0

Không phải là cách dễ nhất để tạo một lớp bao gồm tất cả các biến cần thiết? Sau đó, bạn có một đối tượng với tất cả các biến curretn và nếu cần, bạn có thể ghi đè biến này không?

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.