2012-01-28 25 views
5

Điều này về cơ bản là một câu hỏi về tuổi thọ của thời gian. Nếu một hàm trả về một đối tượng, nhưng tham chiếu không được gán cho một biến và chỉ được sử dụng để gọi một phương thức trên đối tượng được trả về, thì tham chiếu tạm thời có bị xóa tự động không?Các tham chiếu tạm thời có được tự động xóa trong Python không?

Để cung cấp cho một ví dụ cụ thể, giả sử có chuỗi này các cuộc gọi phương pháp:

o.method_a().method_b() 

là tài liệu tham khảo tạm thời được trả về bởi o.method_a() tự động xóa khi cuộc gọi đến method_b() kết thúc, như thể dòng được viết như sau:

tmp = o.method_a() 
try: 
    tmp.method_b() 
finally: 
    tmp = None 

EDIT: Tôi quan tâm đến câu trả lời chung. CPython hoàn thành các đối tượng ngay sau khi số lượng tham chiếu giảm xuống 0. Các triển khai Python khác có thể không hoàn thành các đối tượng ngay lập tức. Tôi tự hỏi nếu ngôn ngữ Python là như C + +, đảm bảo rằng các đối tượng tạm thời bị phá hủy ở cuối của tuyên bố mà họ đã được tạo ra. (Ngoại trừ rằng trong Python, câu hỏi là liệu tham khảo tạm thời bị xóa vào cuối của bản tuyên bố mà họ đã tạo ra.)

Trong C++, mã tương tự có thể được thực hiện với:

class B { 
public: 
    void method_b(); 
}; 

class A { 
public: 
    std::shared_ptr<B> method_a(); 
}; 



A o; 
o.method_a()->method_b(); 

C++ trạng thái chuẩn "Các đối tượng tạm thời bị hủy bỏ như là bước cuối cùng trong việc đánh giá biểu thức đầy đủ ... mà (từ từ) chứa điểm mà chúng được tạo ra. Điều này đúng ngay cả khi việc đánh giá đó kết thúc bằng việc ném một ngoại lệ." Trong ví dụ này, có nghĩa là đối tượng std::shared_ptr<B> tạm thời được tạo bởi lệnh gọi đến A::method_a() sẽ bị hủy ngay lập tức khi kết thúc đánh giá biểu thức đầy đủ o.method_a()->method_b();. Phá hủy một std::shared_ptr có nghĩa là xóa một tham chiếu đến đối tượng được chia sẻ.

+1

hai đoạn của bạn có ngữ nghĩa giống hệt nhau, nhưng nó không phải là một cho rằng bất kỳ trong số đó sẽ gọi finalizers hoặc phá hủy các đối tượng ngay lập tức. Trong thực tế ngay cả trong CPython sự hủy diệt có thể bị trì hoãn nếu đối tượng là trong một chu kỳ (mặc dù bạn không thể có một finalizer sau đó). – fijal

Trả lời

3

Có, người thu gom rác chịu trách nhiệm theo dõi số lượng tham chiếu. Khi số tham chiếu giảm xuống 0, bộ thu gom rác sẽ xóa đối tượng. Đây là một ví dụ nhanh.

>>> class C(object): 
...  def foo(self): 
...   return B() 
... 
>>> class B(object): 
...  def __del__(self): 
...   print 'deleting %r' %self 
...  def bar(self): 
...   print 'I am method bar of %r' %self 
... 
>>> c = C() 
>>> c.foo().bar() 
I am method bar of <__main__.B object at 0xa187d2c> 
deleting <__main__.B object at 0xa187d2c> 

Như một lưu ý phụ, nếu có tham chiếu đến đối tượng tạm thời từ bất kỳ đối tượng nào khác thì không bị xóa. Đối tượng là rác chỉ được thu thập khi số tham chiếu bằng không.

Đồng thời ghi chú về del. del chỉ giảm số lượng tham chiếu của một đối tượng. Nó không xóa một đối tượng. Ví dụ: nếu a = b = C(), del a chỉ xóa tên a và giảm số lượng tham chiếu cho đối tượng C(), nhưng không thực sự xóa nó, vì b vẫn đề cập đến nó.

Bạn nói đúng, tính tham chiếu là triển khai CPython. Theo các triển khai khác, đặc tả Python không cung cấp bất kỳ sự đảm bảo nào về thời điểm các đối tượng bị phá hủy.

Đây là những gì Python Language Reference đã nói về vấn đề này:

Đối tượng không bao giờ bị phá hủy một cách rõ ràng; tuy nhiên, khi chúng trở nên không thể tiếp cận, chúng có thể bị thu gom rác. Việc thực hiện được phép trì hoãn thu gom rác hoặc bỏ qua nó hoàn toàn - đó là vấn đề chất lượng thực hiện cách thu thập rác thải được thực hiện, miễn là không có đối tượng nào được thu thập mà vẫn có thể truy cập được.

+0

+1 Tôi đoán nó không được chỉ định rõ ràng. Cảm ơn vi đương link. –

0

Câu hỏi hay.

Tôi cho rằng đối tượng được thêm vào garbage collector od python của python vì đối tượng không có tham chiếu. Sau đó, điều này sẽ bị xóa ngay lập tức.

2

Bạn có ý nghĩa gì khi "xóa"? Bạn có thể có nghĩa là xóa như trong "destructor __del__ được gọi là", hoặc xóa như trong "bộ nhớ liên quan được giải phóng". Không được đảm bảo. Ví dụ, bạn có thể so sánh CPython 2.7.2 với PyPy 1.7.0 [sử dụng các ví dụ về @Praveen Gollakota]:

class C(object): 
    def foo(self): 
     return B() 

class B(object): 
    def __del__(self): 
     print 'deleting %r' %self 
    def bar(self): 
     print 'I am method bar of %r' %self 

c = C() 
c.foo().bar() 

print 'END OF LINE' 

sản xuất

localhost-2:coding $ python tempref.py 
I am method bar of <__main__.B object at 0x1004b7d90> 
deleting <__main__.B object at 0x1004b7d90> 
END OF LINE 
localhost-2:coding $ pypy tempref.py 
I am method bar of <__main__.B object at 0x0000000102bc4cb0> 
END OF LINE 
+0

Bằng cách "xóa" một tham chiếu, tôi muốn làm cho đối tượng tham chiếu không còn truy cập được thông qua biến giữ tham chiếu, chẳng hạn như bằng cách gán 'None' hoặc áp dụng' del'. GC có thể thu thập một đối tượng ngay sau khi không có tham chiếu "trực tiếp" với nó. GC gọi phương thức '__del __()' của đối tượng trong quá trình hoàn thành. –

+1

"GC gọi phương thức __del __() của đối tượng trong quá trình hoàn thành." Có lẽ tôi nên rõ ràng hơn: điểm của đoạn mã trên là nó * không * đảm bảo rằng '__del__' sẽ được gọi. [Hoặc, tùy thuộc vào cách bạn xác định mọi thứ, mà không phải tất cả các đối tượng được hoàn thành, tôi đoán.] – DSM

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