2012-09-14 17 views
17

trong nhiều trường hợp, bạn có chắc bạn chắc chắn sẽ không sử dụng danh sách một lần nữa, tôi hy vọng bộ nhớ nên được phát hành ngay bây giờcách phát hành bộ nhớ đã sử dụng ngay trong danh sách python?

a = [11,22,34,567,9999] 
del a 

tôi không chắc chắn nếu nó thực sự giải phóng bộ nhớ, bạn có thể sử dụng

del a[:] 

thực sự xóa tất cả các phần tử trong danh sách a.

vì vậy cách tốt nhất để phát hành là điều này?

def realse_list(a): 
    del a[:] 
    del a 

không chắc chắn.

btw, khoảng tuple và được đặt như thế nào?

+9

trừ khi bạn đang xử lý tấn dữ liệu và thực sự nhận được ngoại lệ MemoryError, đừng lo lắng về quản lý bộ nhớ. – monkut

Trả lời

19
def release_list(a): 
    del a[:] 
    del a 

Không bao giờ làm điều này. Python tự động giải phóng tất cả các đối tượng không được tham chiếu nữa, do đó, del a đơn giản đảm bảo rằng bộ nhớ của danh sách sẽ được giải phóng nếu danh sách không được tham chiếu ở bất kỳ nơi nào khác. Nếu trường hợp đó xảy ra, thì các mục danh sách riêng lẻ cũng sẽ được phát hành (và bất kỳ đối tượng nào được tham chiếu chỉ từ chúng, vv), trừ khi một số mục riêng lẻ cũng vẫn được tham chiếu.

Điều đó có nghĩa là chỉ chỉ thời gian khi del a[:]; del a tự động phát hành nhiều hơn del a khi danh sách được tham chiếu ở một nơi khác. Đây là chính xác khi bạn không nên bị xóa khỏi danh sách: người khác vẫn đang sử dụng nó !!!

Về cơ bản, bạn không nên nghĩ đến việc quản lý các phần bộ nhớ. Thay vào đó, hãy nghĩ đến việc quản lý các tham chiếu đến các đối tượng.Trong 99% của tất cả các mã Python, Python dọn dẹp mọi thứ bạn không cần ngay sau lần cuối cùng bạn cần nó, và không có vấn đề gì. Mỗi khi hàm kết thúc tất cả các biến cục bộ trong hàm "die", và nếu chúng trỏ tới các đối tượng không được tham chiếu ở bất cứ nơi nào khác, chúng sẽ bị xóa và sẽ xếp thứ tự vào mọi thứ chứa trong các đối tượng đó. Thời gian duy nhất bạn cần phải suy nghĩ về nó là khi bạn có một đối tượng lớn (nói một danh sách lớn), bạn làm điều gì đó với nó, và sau đó bạn bắt đầu một tính toán phụ dài hạn (hoặc bộ nhớ chuyên sâu), trong đó đối tượng lớn không phải là cần thiết cho tính toán phụ. Bởi vì bạn có một tham chiếu đến nó, đối tượng lớn sẽ không được phát hành cho đến khi tính toán phụ kết thúc và sau đó bạn quay trở lại. Trong trường hợp đó (và chỉ trường hợp đó), bạn có thể rõ ràng là del tham chiếu đến đối tượng lớn trước khi bạn bắt đầu tính toán phụ, để đối tượng lớn có thể được giải phóng trước đó (nếu không có ai khác sử dụng nó, nếu người gọi đã chuyển đối tượng cho bạn và người gọi thì vẫn cần sau khi bạn quay trở lại, bạn sẽ là rất vui mừng vì nó không được phát hành).

+0

Điều gì xảy ra nếu ** a ** là biến thành viên (một biến lớn) và tôi biết tôi sẽ không sử dụng nó nữa, số này có phải là "biến được tham chiếu" không? Kịch bản rất đơn giản: Tôi có một đối tượng xử lý danh sách lớn _when_needed_. Sau khi một số phương thức được gọi, danh sách ** a ** được xử lý và tôi lưu lại kết quả. Trong trường hợp này tôi biết tôi sẽ không bao giờ cần ** a ** nữa. – hsgubert

+1

@hsgubert Nếu 'a' là thuộc tính của một số đối tượng (biến thành viên), thì có nó được tham chiếu bằng cách là một phần của đối tượng đó (giả sử chính đối tượng được tham chiếu ở đâu đó). Nhưng nếu bạn biết bạn không cần nó nữa và bạn đang ở trong một phương thức của cùng một lớp, bạn chỉ có thể 'del self.a' để loại bỏ nó. Nếu bạn không ở trong một phương pháp của lớp đó, đừng làm phiền nó. Thiết kế tốt hầu như luôn giữ cho mỗi lớp chịu trách nhiệm quản lý các thuộc tính riêng của nó; rất khó để hiểu một lớp nếu các phần * khác * của chương trình có thể ngẫu nhiên quyết định rằng đối tượng không cần một trong các thuộc tính của nó nữa. – Ben

4

Khi ghi chú @monkut, có thể bạn không nên lo lắng quá nhiều về quản lý bộ nhớ trong hầu hết các trường hợp. Nếu bạn có một danh sách khổng lồ mà bạn chắc chắn rằng bạn đang thực hiện với tại và nó sẽ không đi ra khỏi phạm vi chức năng hiện tại của một thời gian, mặc dù:

del a chỉ đơn giản là loại bỏ tên của bạn a cho rằng đoạn bộ nhớ. Nếu một số chức năng hoặc cấu trúc khác hoặc bất kỳ điều gì có một tham chiếu đến nó vẫn còn, nó sẽ không bị xóa; nếu mã này có tham chiếu duy nhất đến danh sách đó dưới tên a và bạn đang sử dụng CPython, bộ đếm tham chiếu sẽ ngay lập tức giải phóng bộ nhớ đó. Các triển khai khác (PyPy, Jython, IronPython) có thể không giết nó ngay lập tức vì chúng có các bộ thu gom rác khác nhau.

Do đó, câu lệnh del a trong chức năng realse_list của bạn không thực sự làm bất kỳ điều gì, bởi vì người gọi vẫn có tham chiếu!

del a[:] sẽ, như bạn lưu ý, xóa các phần tử khỏi danh sách và do đó có thể phần lớn việc sử dụng bộ nhớ của nó.

Bạn có thể làm the_set.clear() để có hành vi tương tự với các bộ.

Tất cả những gì bạn có thể làm với một bộ, vì chúng không thay đổi, là del the_tuple và hy vọng không ai khác có tham chiếu đến nó - nhưng bạn có lẽ không nên có bộ dữ liệu khổng lồ!

+1

Câu trả lời này sẽ hoàn chỉnh hơn với một cuộc thảo luận về các tham chiếu yếu. – Marcin

1

Nếu bạn lo lắng về quản lý bộ nhớ và hiệu suất cho các loại dữ liệu tại sao không sử dụng một cái gì đó giống như một hàng đợi đôi liên kết.

Dấu chân bộ nhớ đầu tiên của nó được phân tán ra ngoài bộ nhớ, do đó bạn sẽ không phải phân bổ một đoạn lớn bộ nhớ liên tục ngay trên con dơi. Thứ hai, bạn sẽ thấy thời gian truy cập nhanh hơn để enqueueing và dequeueing bởi vì không giống như trong một danh sách tiêu chuẩn khi bạn loại bỏ cho phép nói một yếu tố trung không cần trượt phần còn lại của danh sách trong chỉ số đó mất thời gian trong danh sách lớn .

Tôi cũng nên lưu ý nếu bạn đang sử dụng chỉ số nguyên tôi sẽ đề nghị xem xét một đống nhị phân như bạn sẽ thấy O (log^2n) lần truy cập so với chủ yếu là O (N) với danh sách.

2

Sử dụng Python Reference Count để quản lý tài nguyên của nó.

import sys 
class foo: 
    pass 

b = foo() 
a = [b, 1] 

sys.getrefcount(b) # gives 3 
sys.getrefcount(a) # gives 2 

a = None # delete the list 
sys.getrefcount(b) # gives 2 

Trong ví dụ trên, b của số tài liệu tham khảo sẽ được tăng lên khi bạn đặt nó vào một danh sách, và như bạn có thể thấy, khi bạn xóa danh sách, số lượng tài liệu tham khảo của b được giảm đi quá. Vì vậy, trong mã của bạn

def release_list(a): 
    del a[:] 
    del a 

là thừa.

Tóm lại, tất cả những gì bạn cần làm là gán danh sách vào đối tượng Không có hoặc sử dụng từ khóa xóa để xóa danh sách khỏi từ điển thuộc tính. (a.k.a, để hủy liên kết tên khỏi đối tượng thực tế). Ví dụ:

a = None # or 
del a 

Khi số tham chiếu của đối tượng chuyển về 0, python sẽ giải phóng bộ nhớ cho bạn. Để đảm bảo đối tượng bị xóa, bạn phải đảm bảo không có địa điểm nào khác tham chiếu đối tượng theo tên hoặc theo vùng chứa.

sys.getrefcount(b) # gives 2 

Nếu sys.getrefcount cung cấp cho bạn 2, có nghĩa là bạn là người duy nhất có tham chiếu của đối tượng và khi bạn làm

b = None 

nó sẽ được giải phóng khỏi bộ nhớ.

Các vấn đề liên quan