In this specific case, it’s not clear to me whether people who subclass threading.Thread
are intended to use its _started
attribute in their own logic, or if it was only called that due to an attitude of defaulting to single-underscore names for implementation details.
If they are intended to use it, then simply put I agree with @guido . Not just if the class “advertises subclassing as an option”, but specifically if _started
should be “available to” subclasses.
If they’re not, then I propose that the standard library should use name mangling in such a case. As it happens, the intuition that thinks of this as representing “private” leads to that conclusion naturally; but I want to show that thinking about it purely in terms of what Python actually does, and without using that theory or dogma about “access levels”, leads to the same conclusion.
I’ve seen a lot of advice that says we should only use the double-underscore name mangling when it’s really necessary. But if clients of threading
aren’t intended to work with _started
in derived classes, and everyone is following this style guide, then collisions of this sort are only to be expected. The standard library authors wouldn’t write __started
because they don’t have a subclass that needs to avoid treading on the base class attribute, and the clients wouldn’t write __started
because they have no reason to anticipate the collision. If they both wrote __started
“defensively” then the name mangling would save them. But since they both write _started
“idiomatically”, the client encounters an error.
An experienced developer might manage to avoid a long debugging session by inferring “oh, that clearly can’t be my code doing that, so it must be the library’s code, so it must be due to a name collision”. But clearly there’s potential for the error to be quite confusing. In the motivating case, for example, the user wanted the derived class _started
to be a simple boolean, whereas the base class apparently uses an instance of some class with an is_set
method (some kind of semaphore perhaps?).
Of course, either party can avoid the name collision by using a double underscore: if it’s only used by one party then the names are actually different to begin with, and if it’s used by both then the name mangling does what it’s designed to do. But if the style expectation is to use a single underscore by default, I argue that it’s the library’s responsibility to break that style guide to preempt the problem. Library code should work smoothly when users do normal things. A convention that says “prefer a single underscore, except when you inherit from a library class” seems needlessly complex to me.