As an ML-focused python dev I have never been able to break the habit of REPL-driven development, but I find it works really well for "building code that works" rather than coming up with a tower of abstractions immediately. A typical python development workflow for me is:

* Start with a blank `main` file and proceed linearly down the page, executing as I go.

* Gradually pull out visually awkward chunks of code and put them into functions with no arguments at the top of the file.

* If I need to parameterize them, add those parameters as needed - don't guess at what I might want to change later.

* Embrace duplication - don't unnecessary add loops or abstractions.

* Once the file is ~500 LOC or becomes too dense, start to refactor a bit. Perhaps introduce some loops or some global variables.

* At all times, ensure the script is idempotent - just highlighting the entire page and spamming run should "do what I want" without causing trouble.

* Once the script is started to take shape, it can be time to bring some OO into it - perhaps there is an object or set of objects I want to pass around, I can make a class for that. Perhaps I can start to think about how to make the functionality more "generalized" and accessible to others via a package.

This is literally the only way I've ever found to be productive with green field development. If my first LOC has the word "class" or "def" in it - I am absolutely going to ripping my hair out 12 hours later, guaranteed.

I too agree with pretty much everything you say. Just want to add that I pretty much solely use ptpython[0]. It can handle line breaks in pasted code, vim (or emacs) bindings and syntax highlighting, and much more.

[0] https://github.com/prompt-toolkit/ptpython