PEP 842: Module Exports

This might feel a bit abstract and wishy-washy, but let me try and capture it (Raymond Hettinger is better at putting this into words than I am, but I’ll do my best). I’ll almost certainly describe things that aren’t some peoples’ experiences, even some people who have been highly involved in this community for a long time[1], but I’ve also spoken to a lot of developers with a lot of language experience and think I’m talking about something that’s at least more common with Python, if not representative of it.

Writing Python should be close to a “zen” experience. At its best, when you get into the flow state, the thoughts you are thinking about the thing you are trying to build are shaped like Python code as you go through the process of writing it down. It’s often said that Python “fits in my head”, sometimes merely referring to the number of rules, but usually it seems to mean that the way a Python program is structured aligns with how the developer’s memory retains the information, and so they can fit a bigger program in because it’s already the right shape.

Bear in mind that Python pre-dates code editors with automatic completions. So nobody coded by pressing a dot and scrolling through a list of every name that the computer can find - to be efficient here, you wrote code that flowed fluently, so you didn’t have to look it up every time.

This flow is the critical thing. Python is popular as a prototyping language. Why? Because it’s great for one person to flow through the design of their program very quickly and fluently, and (here’s where this starts becoming directly relevant) part of that flow comes from the lack of boilerplate decision making.

Try and flow the same way in Java, C#, Rust, C++, or virtually any other significantly structured language and you will find yourself interrupted every other line with a decision to make. Should this be public? Private? Protected? Friend? Static? Global? RAII? GC? Which type? Will it convert? Will it cast? etc. You simply can’t flow.

Python is such a beautiful exception here, because you don’t have to make these decisions at every point. That’s one of the things that many of us love about it, and I’ve come to find it’s the primary reason for me.

I can take the same base concept in a number of different directions as well - exceptions work great for similar reasons, the standard library works great for similar reasons, functions over methods work great for similar reasons. They all lead to a really nice flow that other languages don’t even attempt to replicate.

And so proposals to add things that are explicitly about decisions that really shouldn’t need to be made have a much higher bar to cross before I would consider them beneficial. As others have said, __all__ or del <name> already exist, if you find there is some need to do this. I almost never have needed them.[2] I almost never have seen a scenario that needed them. And I really really want to see cases where other people have needed them before endorsing the need.


  1. I’m not thinking of anyone specific here, just assuming that they’ll exist. ↩︎

  2. Last time I used module-level del was for some really dirty code being injected into arbitrary other modules that you really don’t want to know about :wink: ↩︎

14 Likes