Wow: list of immediate subclasses?

Carl Banks imbosol at aerojockey.com
Fri Aug 1 17:06:33 EDT 2003


Andrew Dalke wrote:
> Carl Banks, responding to Roman Suzi:
>> __subclasses__ is a list of weak references, so the class can be
>> collected even though it's listed in __subclasses__.  For whatever
>> reason, class A isn't deleted by reference counts, but cyclic garbage
>> collection gets it.
> 
> But I want to know that reason.  Why are there any cycles?  After
> all, don't weak-references help break cycles?  

Take a look at "__mro__" method of types.  __mro__ is a tuple
containing real references, and the first item is always the type
object, follwed by all it's bases.  That makes at least one cycle.
There's probably more since gc collects 6 objects.


> And in my code
> before, why do I need to do the gc a few times to force the cycle
> to be broken?

Because, __subclasses__ is a list of weak references internally, it
gets converted to a regular list when called, and this list is stored
in _.  Thus, if you call gc.collect right after evaluating
float.__subclasses__, there remains an active reference.



>>>> float.__subclasses__()
> []
>>>> class Spam(float): pass
> ...
>>>> float.__subclasses__()
> [<class '__main__.Spam'>]
>>>> del Spam
>>>> _ = None  # just in case ...
>>>> float.__subclasses__()
> [<class '__main__.Spam'>]
>>>> gc.collect()
> 0
>>>> float.__subclasses__()
> [<class '__main__.Spam'>]
>>>> gc.collect()
> 0
>>>> float.__subclasses__()
> [<class '__main__.Spam'>]
>>>> gc.collect()
> 0
>>>> gc.collect()
> 6
>>>> gc.collect()
> 0
>>>> float.__subclasses__()
> []
>>>>
> 
> It's a bit too mysterious for my liking.

I think it's a very minor problem.  There doesn't appear to be a
memory leak, and what's the point of making the effort to manually
break cycles when cycle garbage collection exists?



-- 
CARL BANKS




More information about the Python-list mailing list