# more on destructors

    

index 53084f3..f06878c 100644
@@ -21,6 +21,9 @@ You don't need telegram to read the channel using the link above. If neither of
+ union
+ lookup-error
+ is
++ del
++ del2
++ gc_is_finalized

## To write

@@ -60,3 +63,4 @@ These are ideas for future posts. Let me know if you want to write a guest post
+ generator.close
+ re.scanner
+ pickle and security
++ list.clear
diff --git a/pythonetc/del2.md b/pythonetc/del2.md
new file mode 100644
index 0000000..8207560
--- /dev/null
+++ b/pythonetc/del2.md
@@ -0,0 +1,40 @@
+# __del__
+
+The method __del__ is called on the object by the grabage collector when the last reference to the object is removed:
+
+python
+class A:
+  def __del__(self):
+    print('destroying')
+
+a = b = A()
+del a
+del b
+# destroying
+
+def f():
+  a = A()
+
+f()
+# destroying
+
+
+The method is used by python file object to close the descriptor when you don't need it anymore:
+
+python
+def f():
+    a_file = open('a_file.txt')
+    ...
+
+
+However, you cannot safely rely on that the destructor (this is how it's called in other languages, like C) will be ever called. For instance, it can be not true in PyPy, MicroPython, or just if tthe garbage collector is disabled using gc.disable().
+
+The thumb up rule is to use the destructor for unimportant things. For example, aiohttp.ClientSession uses __del__ to warn about an unclosed session:
+
+python
+def __del__(self) -> None:
+  if not self.closed:
+    warnings.warn(
+      f"Unclosed client session {self!r}", ResourceWarning
+    )
+
diff --git a/pythonetc/gc_is_finalized.md b/pythonetc/gc_is_finalized.md
new file mode 100644
index 0000000..2e18ee5
--- /dev/null
+++ b/pythonetc/gc_is_finalized.md
@@ -0,0 +1,40 @@
+# gc.is_finalized
+
+By using __del__ and global variables it is possible to leave a reference to the object after it was "destroyed":
+
+python
+runner = None
+class Lazarus:
+  def __del__(self):
+    print('destroying')
+    global runner
+    runner = self
+
+lazarus = Lazarus()
+print(lazarus)
+# <__main__.Lazarus object at 0x7f853df0a790>
+del lazarus
+# destroying
+print(runner)
+# <__main__.Lazarus object at 0x7f853df0a790>
+
+
+In the example above, runner points to exactly the same object as lazarus did and it's not destroyed. If you remove this reference, the object will stay in the memory forever because it's not tracked by the garbage collector anymore:
+
+python
+del runner  # it will NOT produce "destroying" message
+
+
+This can lead to a strange situation when you have an object that escapes the tracking and will be never collected.
+
+In python 3.9, the function gc.is_finalized was introduced that tells you if the given object is a such runner:
+
+python
+import gc
+lazarus = Lazarus()
+gc.is_finalized(lazarus) # False
+del lazarus
+gc.is_finalized(runner)  # True
+
+
+It's hard to imagine situation when you'll actually need it, though. The main conclusion you can make out of it is that you can break things with a destructor, so don't overuse it.