I have the following Python code:
#!/usr/bin/python3
import time
class Greeter:
def __init__(self, person):
self.person = person
print("Hello", person);
def __del__(self):
print("Goodbye", self.person);
def inspect(self):
print("I greet", self.person);
if __name__ == '__main__':
to_greet = []
try:
to_greet.append(Greeter("world"));
to_greet.append(Greeter("john"));
to_greet.append(Greeter("joe"));
while 1:
for f in to_greet:
f.inspect()
time.sleep(2)
except KeyboardInterrupt:
while (len(to_greet) > 0):
del to_greet[0]
del to_greet
print("I hope we said goodbye to everybody. This should be the last message.");
When I run it and Ctrl+C
during the sleep, I get:
Hello world
Hello john
Hello joe
I greet world
I greet john
I greet joe
^CGoodbye world
Goodbye john
I hope we said goodbye to everybody. This should be the last message.
Goodbye joe
I don't understand why Goodbye joe
is only printed after This should be the last message
. Who is holding a reference to it? Is it the print
statement? Even if I put gc.collect()
before the last print
I don't see us saying goodbye to Joe before the last print
. How can I force it?
From what I have been Googling, it seems I should be using the with
statement in such a situation, but I'm not exactly sure how to implement this when the number of people to greet is variable (e.g., read from a names.txt file) or just big.
It seems I won't be able to get C++
-like destructors in Python, so what is the most idiomatic and elegant way to implement destructors like this? I don't necessarily need to delete/destroy the objects, but I do need to guarantee we absolutely say goodbye to everybody (either with exceptions, killed by signal, etc.). Ideally I'd like to do so with the most elegant possible code. But for now, being exception-resistant should be fine.