I completely concur and can act as another data point of someone who has used tuples for __all__ for many years and would happily switch to lists to make these decorators work
What’s wrong with using _foo? The _prefix is widely accepted to mean private, and it’s very elegant to both write and read. A key advantage is that it is even obvious in calling code without the need to lookup the declaration.
Adding @privateand @publicseems to me at odds with Python’s “we’re all adults” philosophy, and it is adding additional verbosity that does not seem to me to add any substantial benefit.
Well, the main problem is imports. Do you always write
import argparse as _argparse
import asyncio as _asyncio
? If not, then these modules are star-importable from your module, and to prevent that, you have to define __all__:
import argparse
import asyncio
__all__ = ["my_public_function"]
which is somewhat annoying and error-prone to do, so this PEP proposes an easier way to define __all__.
Thanks for the examples. However my question remains essentially the same: what’s wrong with __all__? It works, it’s at module scope (where it should be imho), it’s accepted practice and well understood. Perhaps I’m missing something, but I have not seen this to be error prone in practice, and if it is in some codebase, I propose this should be fixed by more tests, not more syntactical sugar.
The 842-844 proposals and ancillary discussions are about adding a way to make the management easier and less error prone than what __all__, wildcard import semantics, and prefix convention currently provides. I don’t personally find maintaining _all__ particularly burdensome, but would be very welcome to a mechanism that makes it easier. There are many aspects to this such as making it local to function definitions, not requiring duplicating the function name, avoiding accidental pollution of the public API definition and unintentional use non-public module members, and not (practically) requiring simple one-module libraries adopt an “API hub” module. A whole lot more considerations have been raised, but I think this covers the core motivations for these proposals.
I think a big part of the challenge in improving upon the current state of affairs is there isn’t a clear bug…things pretty much can be made to work. There are quite a few ways to reasonably declare what is public and what is private, so it is complex to introduce another mechanism that doesn’t conflict, duplicate (there should be one clear way), or appear to deprecate or discourage the current ways while still being a worthwhile addition.
Good hint. Imho that’s good enough. Im there is no need for either of these PEPs.
What is possibly lacking is good and consistent documentation of the status quo in a single place. The current mechanisms and conventions are scattered and partly vague (maybe even up to inconsistent).
There’s at least:
- 7. Simple statements — Python 3.14.7 documentation
- 9. Classes — Python 3.14.7 documentation
- Distributing type information — typing documentation
- PEP 8 – Style Guide for Python Code | peps.python.org
I believe it would be valuable to pull them together into a single consistent description. This may also make it more obvious whether the current state is good enough.
Why don’t you give that a try here. (And please make clear what is implemented in the runtime, what’s a type checker rule, and what’s merely a recommendation (like PEP 8).
Ok, I’ve given it a shot. Turns out to be substantially more effort than I thought. I’ve created a dedicated thread, because it would side-track too much from PEP 844. Please find the summary of the status quo here: Python API exposure mechanisms (public/internal) - determining status quo