Seeing is huge. Anything that you can do that lets you see what's happening in a system with more detail or more quickly will help you master that system. Do you want to understand how your lawn mower works? Remove the hood.
Python programming can be a pleasure, partly because it's simple to see what you're doing. If you want to understand a little snippet, you just take it to the interpreter, run it, and get an output. Edit it and get a new output.
Some effects are trickier to see because they are contextual. That is, your snippet won't do the same thing if you paste it into the interpreter as it will in the environment where it's meant to live. This is particularly true for me when I'm working with Django code, which often depends on a Django environment.
The Django shell (./manage.py shell) solves part of this problem. The Django Extensions shell (./manage.py shell_plus if you've installed the Django Extensions app) can take you further. But even then if you have code that depends on the actual location of a file, for example, you can't test it in the shell directly.
To get around that issue, I've typically done two different things in the past: 1) run the code in a test and use print statements or ipdb to get the information that I want, or 2) figure out how to reload the interpreter every time I update a module.
This post celebrates the fact that I just learned how to do 2 much more efficiently than before. So here it is --
effortless ipython reload: