I do think there is a meta going on around LISP repl and it's internal introspection which other REPL don't quite provide. You can come to almost the same place in output, but not at interaction with the run state of the 'machine' itself. (somebody else in the thread made the point its mostly there except handling exceptions in the stack)
The importlib.reload function only applies to one copy of a module. A comprehensive solution would be incredibly complicated and would still have limitations.
In contrast, a Lisp package exists in exactly one place. No matter where you get it from, two references to the same package are always eq (having "is" equality in Python terms). Therefore, if you redefine something in a package, you redefine it for everything that uses the package. It also helps that imports in Lisp apply to the symbols, not the things they refer to. So importing something doesn't hide a copy of it anywhere. The most naive redefinition technique will always work, with no edge cases.
The inability for class redefinition to affect already existing objects in Python is another severe limitation. Even if you could redefine anything reliably in Python, you'd still have this problem.
I still wish there was an environment more like Smalltalk for Python.
Some years ago I was playing around with Franz Lisp, and noticed an interesting debugging feature in it. A few days later, I was using a then-new version of Visual Studio for writing either C (not C++) or VB, and noticed the same cool feature in it, which MS was calling Edit and Continue.
IIRC, it was introduced in that VS version, but not sure, since I was not a regular Visual Studio user.
You can also use `from importlib import reload` and then have an expression like reload(foo).bar() to constantly reload your foo library.
That's useful not only for breakpoints but also for errors. We can fix an error without re-running everything from zero. https://www.youtube.com/watch?v=jBBS4FeY7XM
import code; code.interact(local=vars(foo))
where `foo` is the module object you want to set as current. This launches a subREPL in that module's namespace. (EOF kills the subREPL and returns to main.)Python has a debugger in the standard library that can also do post-mortem inspections.