__post_init__ for a custom type, a bad idea?

Hi,

In PyGObject, we have a GObject base type that all classes in the framework inherit from. This type has some custom __init__ method which does some (for the purposes of this post) funny magic that makes it annoying to override it.

We are thinking to add a method similar to dataclasses’ __post_init__ to avoid having to override __init__ in most cases.

The question is: Is calling it __post_init__ a bad idea? Thinking about PEP 8’s “Never invent such names; only use them as documented.”

See the merge request with some discussion.

Is anyone likely to write?:

@dataclass
class X(GObject):
    ...

And would that break anything the user expects, or work exactly how both you and they wish? The dataclass machinery will call your __post_init__ on instances (with the InitVars). So perhaps PyGObject should ensure their __post_init__ is idempotent (or could whatever calls it watch out for being in a dataclass)?

Right, I was going to mention that but forgot. GObject dataclasses can’t exist for unrelated reasons. (Not that you’d have much of an incentive to make one, GObject properties have much of the same qualities as dataclass fields.)

OK. Nonetheless, on reflection, my take on it is, as a new contributor to a project, if I saw __post_init__ in the source, I’m likely to wonder if it has that name specifically to be called by a dataclass’s __init__ (or another framework’s hook). That we are even having this discussion, demonstrates the decision to name a non-dataclass method __post_init__ requires an explanatory comment, at the very least.

If the intent is otherwise, that’s a plenty good enough reason to pick a new name. And as a bonus, once whoever first named it accepts this and a new name is used instead, potential bugs due to name clashes between other libraries and this method no longer need to be considered at all, ever again. If there’s one thing LLMs are actually good at, it’s suggesting new names for variables and methods.

Others may think otherwise of course, and perhaps there are good reasons to use the same name that I haven’t thought of.

1 Like

To me __post_init__ clearly conveys “the method that is called after the automatically constructed __init__”. And there is value in that clarity. But this is designing for inheritance, which means it’s not immediately obvious there will never be multiple inheritance. Which would be enough to push me to use __pygob_post_init__ instead.

Don’t spurious dunder-names slightly irritate the type system?