__del__
adalah finalisator . Ini dipanggil ketika sebuah objek dikumpulkan sampah yang terjadi di beberapa titik setelah semua referensi ke objek telah dihapus.
Dalam kasus sederhana ini bisa terjadi tepat setelah Anda mengatakan del x
atau, jika x
adalah variabel lokal, setelah fungsi berakhir. Secara khusus, kecuali ada referensi melingkar, CPython (implementasi Python standar) akan segera mengumpulkan sampah.
Namun, ini adalah detail implementasi CPython. Satu-satunya properti yang diperlukan dari pengumpulan sampah Python adalah bahwa ini terjadi setelah semua referensi dihapus, jadi ini mungkin tidak perlu terjadi segera setelah itu dan mungkin tidak terjadi sama sekali .
Terlebih lagi, variabel dapat hidup untuk waktu yang lama karena berbagai alasan , misalnya pengecualian yang menyebar atau introspeksi modul dapat membuat jumlah referensi variabel lebih besar dari 0. Selain itu, variabel dapat menjadi bagian dari siklus referensi - CPython dengan pengumpulan sampah dihidupkan paling banyak , tapi tidak semua, siklus seperti itu, itupun hanya secara berkala.
Karena Anda tidak memiliki jaminan bahwa itu dijalankan, seseorang tidak boleh memasukkan kode yang Anda perlukan __del__()
- sebaliknya, kode ini milik finally
klausul try
blok atau manajer konteks dalam sebuah with
pernyataan. Namun, ada kasus penggunaan yang valid untuk __del__
: mis. Jika sebuah objek X
mereferensikan Y
dan juga menyimpan salinan Y
referensi dalam global cache
( cache['X -> Y'] = Y
) maka akan lebih sopan jika X.__del__
juga menghapus entri cache.
Jika Anda tahu bahwa destructor menyediakan (melanggar pedoman di atas) pembersihan diperlukan, Anda mungkin ingin menyebutnya langsung , karena tidak ada yang khusus tentang hal itu sebagai metode: x.__del__()
. Jelas, Anda harus melakukannya hanya jika Anda tahu bahwa tidak keberatan untuk dipanggil dua kali. Atau, sebagai upaya terakhir, Anda dapat mendefinisikan kembali metode ini menggunakan
type(x).__del__ = my_safe_cleanup_method
__exit__
dalam konteks ini? Apakah itu berjalan setelah atau sebelum__del__
atau bersama?__del__
metode mungkin tidak berjalan bahkan pada penghentian program, dan bahkan ketika mereka berjalan saat penghentian, menulis__del__
metode yang bekerja dengan baik bahkan saat penerjemah sibuk merusak diri sendiri di sekitar Anda membutuhkan pengkodean yang lebih hati-hati daripada yang diterapkan banyak pemrogram. (Pembersihan CPython biasanya mendapatkan__del__
metode untuk dijalankan saat penafsiran shutdown, tetapi masih ada kasus di mana itu tidak cukup. Daemon threads, C-level global, dan objek yang__del__
dibuat dengan yang lain__del__
semua dapat menyebabkan__del__
metode tidak berjalan.)Saya menulis jawaban untuk pertanyaan lain, meskipun ini adalah pertanyaan yang lebih akurat untuk itu.
Bagaimana cara kerja konstruktor dan destruktor?
Ini adalah jawaban yang sedikit beropini.
Jangan gunakan
__del__
. Ini bukan C ++ atau bahasa yang dibuat untuk destruktor. The__del__
Metode benar-benar harus pergi dengan Python 3.x, meskipun aku yakin seseorang akan menemukan kasus penggunaan yang masuk akal. Jika Anda perlu menggunakan__del__
, perhatikan batasan dasar per http://docs.python.org/reference/datamodel.html :__del__
dipanggil saat pengumpul sampah kebetulan sedang mengumpulkan objek, bukan saat Anda kehilangan referensi terakhir ke suatu objek dan bukan saat Anda mengeksekusinyadel object
.__del__
bertanggung jawab untuk memanggil salah__del__
satu superclass, meskipun tidak jelas apakah ini dalam urutan resolusi metode (MRO) atau hanya memanggil setiap superclass.__del__
sarana agar pengumpul sampah menyerah untuk mendeteksi dan membersihkan tautan siklik, seperti kehilangan referensi terakhir ke daftar tertaut. Anda bisa mendapatkan daftar objek yang diabaikan dari gc.garbage. Terkadang Anda dapat menggunakan referensi yang lemah untuk menghindari siklus sama sekali. Hal ini kadang-kadang diperdebatkan: lihat http://mail.python.org/pipermail/python-ideas/2009-October/006194.html .__del__
Fungsi bisa menipu, menyimpan referensi ke sebuah obyek, dan menghentikan pengumpulan sampah.__del__
akan diabaikan.__del__
melengkapi__new__
lebih dari__init__
. Ini membingungkan. Lihat http://www.algorithm.co.il/blogs/programming/python-gotchas-1- del -is-not-the-berlawanan-of- init / untuk penjelasan dan penjelasan.__del__
bukanlah anak yang "dicintai" dengan Python. Anda akan melihat bahwa dokumentasi sys.exit () tidak menentukan apakah sampah dikumpulkan sebelum keluar, dan ada banyak masalah aneh. Memanggil__del__
on global menyebabkan masalah pengurutan yang aneh, misalnya, http://bugs.python.org/issue5099 . Haruskah__del__
dipanggil bahkan jika__init__
gagal? Lihat http://mail.python.org/pipermail/python-dev/2000-March/thread.html#2423 untuk utas panjang.Tetapi di sisi lain:
__del__
Berarti Anda jangan lupa untuk memanggil pernyataan dekat. Lihat http://eli.thegreenplace.net/2009/06/12/safely-using-destructors-in-python/ untuk__del__
sudut pandang profesional . Ini biasanya tentang membebaskan ctypes atau sumber daya khusus lainnya.Dan alasan pesonal saya untuk tidak menyukai
__del__
fungsinya.__del__
, pesan itu berubah menjadi tiga puluh pesan kebingungan.Jadi, temukan alasan untuk tidak menggunakan
__del__
.sumber
__del__
, tetapi bagaimana memanggil__del__
, jawaban Anda menarik.The
__del__
metode, itu akan dipanggil ketika objek adalah sampah yang dikumpulkan. Perhatikan bahwa itu belum tentu dijamin akan dipanggil. Kode berikut dengan sendirinya belum tentu bisa melakukannya:Alasannya karena
del
hanya mengurangi jumlah referensi satu per satu. Jika sesuatu yang lain memiliki referensi ke objek tersebut,__del__
tidak akan dipanggil.Ada beberapa peringatan untuk digunakan
__del__
. Umumnya, mereka biasanya tidak terlalu berguna. Bagi saya kedengarannya lebih seperti Anda ingin menggunakan metode dekat atau mungkin pernyataan with .Lihat dokumentasi python tentang
__del__
metode .Satu hal lagi yang perlu diperhatikan:
__del__
metode dapat menghambat pengumpulan sampah jika digunakan secara berlebihan. Secara khusus, referensi melingkar yang memiliki lebih dari satu objek dengan__del__
metode tidak akan mengumpulkan sampah. Ini karena pengumpul sampah tidak tahu mana yang harus dipanggil terlebih dahulu. Lihat dokumentasi pada modul gc untuk info lebih lanjut.sumber
The
__del__
Metode (catatan ejaan!) Dipanggil saat objek Anda akhirnya hancur. Secara teknis (dalam cPython) saat itu tidak ada lagi referensi ke objek Anda, yaitu saat objek tersebut berada di luar jangkauan.Jika Anda ingin menghapus objek Anda dan memanggil
__del__
metode useyang akan menghapus objek (asalkan tidak ada referensi lain untuk itu).
Saya sarankan Anda menulis kelas kecil seperti ini
Dan selidiki di penerjemah python, misalnya
Perhatikan bahwa jython dan ironpython memiliki aturan berbeda tentang kapan tepatnya objek dihapus dan
__del__
dipanggil. Ini tidak dianggap sebagai praktik yang baik untuk digunakan__del__
karena ini dan fakta bahwa objek dan lingkungannya mungkin dalam keadaan tidak diketahui saat dipanggil. Itu tidak sepenuhnya dijamin__del__
akan dipanggil - penerjemah dapat keluar dengan berbagai cara tanpa menghapus semua objek.sumber
use del obj1
sepertinya ide yang buruk untuk diandalkan.Seperti yang disebutkan sebelumnya,
__del__
fungsinya agak tidak dapat diandalkan. Dalam kasus di mana mungkin tampak berguna, pertimbangkan untuk menggunakan metode__enter__
dan__exit__
sebagai gantinya. Ini akan memberikan perilaku yang mirip denganwith open() as f: pass
sintaks yang digunakan untuk mengakses file.__enter__
secara otomatis dipanggil saat memasuki cakupanwith
, sementara__exit__
secara otomatis dipanggil saat keluar. Lihat pertanyaan ini untuk lebih jelasnya.sumber