2012-02-17 35 views
7

Tôi đang viết một trò chơi nền tảng đơn giản, và tôi thấy rằng khi loại bỏ các trường hợp 'ma', chúng vẫn tồn tại và không được thu gom rác. Dường như mặc dù tôi đang loại bỏ tất cả các tài liệu tham khảo, các đối tượng ma có một số loại tài liệu tham khảo nội bộ đang ngăn cản chúng được thu thập rác thải. Cụ thể là chúng có các thuộc tính là các công tắc phương thức.tham chiếu nội bộ ngăn chặn việc thu gom rác

Các mã sau minh họa vấn đề của tôi:

import weakref 

weak_ghosts = weakref.WeakKeyDictionary() 

class Ghost(object): 
    def __init__(self): 
     #pass 
     self.switch = {'eat':self.eat, 'sleep':self.sleep} 

    def eat(self): 
     pass 

    def sleep(self): 
     pass 

ghost = Ghost() 
weak_ghosts[ghost] = None 
#ghost.switch = {} # uncomment this line and ghost is successfully removed 
del ghost 
print "number of ghosts =", len(weak_ghosts) 

#output: 
number of ghosts = 1 

Câu hỏi:

  1. thực sự là gì đang xảy ra?
  2. Tôi nên làm gì để tránh tình trạng này?
  3. Tôi có sử dụng phương pháp đúng để tạo từ điển có thể chuyển đổi các phương pháp không?

Trả lời

4

Có tham chiếu vòng tròn được tạo bởi self.switch tham chiếu đối tượng mà nó là một phần của. Check this out:

import weakref 

class Ghost(object): 
    def __init__(self): 
     #pass 
     self.switch = {'eat':self.eat, 'sleep':self.sleep} 

    def eat(self): 
     pass 

    def sleep(self): 
     pass 

ghost = Ghost() 

def callback(o): 
    print 'callback', o 

wref = weakref.ref(ghost, callback) 
print 'del ghost' 
del ghost 
print 'after del ghost' 

Prints:

del ghost 
after del ghost 
callback <weakref at 00B55FC0; dead> 

Vì vậy, các đối tượng thực tế chỉ làm sạch trên tắt máy.

Bạn có thể chạy GC theo cách thủ công để xem hiệu ứng. Thêm phần này vào phần cuối của kịch bản trên:

print 'gc.collect' 
import gc 
gc.collect() 
print 'after gc.collect' 

Bây giờ bạn sẽ thấy:

del ghost 
after del ghost 
gc.collect 
callback <weakref at 00B55FC0; dead> 
after gc.collect 

Lưu ý rằng theo mặc định, GC này được kích hoạt và sẽ chạy bất cứ lúc nào. Nó sẽ làm sạch các đối tượng ghost của bạn vì chúng trở thành các tham chiếu vòng tròn không thể truy cập được.

2

Một lựa chọn là để làm:

class Ghost(object): 
    def __init__(self): 
     self.switch = {'eat':Ghost.eat, 'sleep':Ghost.sleep} 

Vì vậy, các phương pháp được lưu giữ không ràng buộc.

+1

Nhưng sau đó nhớ chuyển đối tượng một cách rõ ràng khi thực sự gọi chúng –

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