I may be misunderstanding something here. But, I think replacing class MyClass(MyBaseClass): ...
with print(Bar)
and then having that work isn’t magic, it’s an expected behavior of garbage collection in Python. On creation of the function nested2
, the Python interpreter sees that there is is a reference to Bar
, so it increases the reference counter for Bar
. Then when the call for nested1
closes out and garbage collection happens, the object isn’t GC’d because the nested2
object is keeping it alive.
It doesn’t work with strings and future annotations because those aren’t real references to the Bar
object.
Here is your code example, but slimmed down. If you comment out the line print("Bar in nested2:", Bar)
, the calls Refs to Bar
and Total scopes ...
change. That is because commenting out that line removes the reference to Bar
in the scope of nested2
’s function definition.
import sys
import gc
def nested1():
Bar = 'this is Bar'
def nested2():
print("Bar in nested2:", Bar)
return
print('Refs to Bar:', gc.get_referrers(Bar))
print('Total scopes referencing Bar:', len(gc.get_referrers(Bar)))
return nested2
def calling_it():
Baz = 'this is baz'
return nested1()()
calling_it()