[Python-Dev] PEP 442 clarification for type hierarchies
stefan_ml at behnel.de
Tue Aug 6 17:18:59 CEST 2013
Antoine Pitrou, 06.08.2013 14:12:
> Le Mon, 05 Aug 2013 22:30:29 +0200,
> Stefan Behnel a écrit :
>> Hmm, it's a bit unfortunate that tp_finalize() maps so directly to
>> __del__(), but I think this can be fixed. In any case, each
>> tp_finalize() function must only ever be called once, so if a subtype
>> inherited the tp_finalize() slot from its parent, it mustn't be
>> called again.
> This is already dealt with by a custom bit in the GC header (cf.
> _PyGC_IS_FINALIZED, IIRC).
But that's only at an instance level. If a type in the hierarchy inherited
the slot function for tp_finalize() from its parent, then the child must
skip its parent in the call chain to prevent calling the same slot function
twice. No instance flag can help you here.
>>>> An obvious open question is how to deal with exceptions during
>>>> finalisation. Any break in the execution chain would mean that a
>>>> part of the type wouldn't be finalised.
>>> Let's come back to pure Python:
>>> class A:
>>> def __del__(self):
>>> class B(A):
>>> def __del__(self):
>> What makes you think it's a good idea to call the parent type's
>> finaliser before doing the local finalisation, and not the other way
>> round? What if the subtype needs access to parts of the super type
>> for its cleanup?
> I'm not saying it's a good idea. I'm just saying that to reason about
> the C API, it is a good idea to reason about equivalent pure Python
> code. Since exceptions aren't implicitly silenced in pure Python code,
> they probably shouldn't in C code.
>> In other words, which makes more sense (at the C level):
>> Should that order be part of the protocol or not? (well, not for
>> __del__() I guess, but maybe for tp_finalize()?)
> No, it is left to the user's preference. Since tp_finalize() is meant
> to be equivalent to __del__(), I think it's better if the protocols
> aren't subtly different (to the extent to which it is possible, of
Ok, fine with me. If the calls are done recursively anyway, then the child
can decide when to calls into its parent.
>> Coming back to the __del__() vs. tp_finalize() story, if tp_finalize()
>> first recursed into the super types, the top-most one of which then
>> calls __del__() and returns, we'd get an execution order that runs
>> Python-level __del__() methods before C-level tp_finalize()
>> functions, but loose the subtype-before-supertype execution order for
>> tp_finalize() functions.
> Well... to get that, you'd have to subclass a pure Python class with a
> C extension type.
Maybe I'm wrong here. It's the default implementation of tp_finalize() that
calls __del__, right? If a Python class with a __del__ inherits from an
extension type that implements tp_finalize(), then whose tp_finalize() will
be executed first? The one of the Python class or the one of the extension
More information about the Python-Dev