I was in Montreal, Canada for the PyCon Canada 2017 conference and presented on the ideas and philosophy that are present within the Python programming language. I covered how the Python language influences your coding style and how that coding style is now in the mainstream and has made its way into other programming languages.
In the presentation I used PEP20, the Zen of Python, document as the starting point. PEP are the Python Enhancement Proposals and the Zen of Python was one of the earlier of these proposals.
The ideas within Zen of Python that I further examined are:
- Explicit is better than implicit
- Errors should never pass silently
- If the implementation is hard to explain, it’s a bad idea
- If the implementation is easy to explain, it may be a good idea
Jupyter notebooks embodied parts of the Zen of Python, in particular that “explicit is better than implicit”. Jupyter notebooks (formerly know as IPython) has risen in popularity as it is being used for data science. Data scientists all rely on the notebook style to express their thoughts and to show their work and code. You can use Jupyter notebooks at Google Colab and Microsoft Azure, and see rendered versions of them in GitHub code repositories.
Peter Norvig, director of research at Google, uses Python heavily and created some IPython/Jupyter notebooks. You can see a rendered version of one of his notebooks on Github. What’s cool here is the space for explanation, including charts and graphs and mathematical formulas. The notebook is close to an interactive textbook. Also, Jupyter notebooks supports many languages today including Python, Haskell, Ruby, R and Scala so you aren’t restricted to just Python. This is an example of the Python philosophy reaching beyond that one programming language and into other languages and domains.
Sphinx Documentation and Docstrings in Python
Within Python, you have the ability to create documentation using docstrings which aides in readability. Docstrings give developers a space to be more explicit about the intent of the code and to explain it.
The next project that I examined which embodies parts of the Zen of Python was the Sphinx documentation project. Sphinx is how most Python-based projects generate their documentation and it generates it by using the docstrings that are part of the code. The default configuration of Sphinx produces good looking documentation with an index and a basic search engine.
Sphinx embodies and enables the idea that beautiful is better than
ugly, that explicit is better than implicit. The markup language itself is complex, but not complicated, and is simple if you stick to the basics. So there are many points at which Sphinx embodies the Python philosophy.
The Design of Python APIs
Next there are the way Python APIs for libraries are designed. Python libraries have great API designs. I feel that the Python philosophy and the Zen of Python can take some credit for this. The APIs of many Python libraries are sensible, they are explicit, they are explained well, they are readable. The Python philosophy strongly influence how Python libraries are written.
And this is just in Python, let’s see where else the Python philosophy has made an appearance.
One example that I want to point out is Express.js. Express is a Node.js-based web framework. In their code they have a router which dispatches from a url pattern to a controller. You may know this as the urlconf file in Django or as a url resolver.
very un-Pythonic. However, it still can express some of the Python
Ruby and the Zen of Python
However, Ruby is a different story. Through my career I have encountered Ruby code that bears a strong resemblance to Python.
For example, pulling function parameters into their own local variables:
def before hello 'world', 123 end def after name = 'world' repetitions = 123 hello(name, repetitions) end
This greatly improves readability and makes it simple to debug whether you’re using a proper debugger or print statements. Since the variable parameters are separate from the function call, you can print their values out before the function is called.
Another example of explicitness and readability in Ruby code that I
recently worked on was for testing method calls. Originally we had
many tests relying on our test library to ensure that the method calls
were accurate and had particular arguments passed to them. It was
tedious work because we had to find a specific method call in the list
of method calls and then test the arguments.
To match a list of method calls, it looked something like this:
describe 'method call test' do it 'calls the method with 1, "abc", :hello' do expect(MyClass.method_calls).to eq  MyClass.do_things expect(MyClass.method_calls).to eq([ [:abc, [1, 2, 3, '127.0.0.1', 'b1d4a2', '45be3f']], [:def, [3, 2, 3, '127.0.0.1', 'b1d4a2', '45be3f']], [:efg, [3, 2, 4, '127.0.0.1', 'b1d4a2', '45be3f']], [:hij, [3, 2, 4, '127.0.0.1', 'b1d4a2', '45be3f']], ]) end end
The new code now looks like this:
describe 'method call test' do it 'calls the method with 1, "abc", :hello' do expect_do_things_call(:abc, :id => 1, :other_id => 2, :thing_id => 3, :ip_address => '127.0.0.1', :role_id => 'b1d4a2', :category_id => '45be3f' ) expect_do_things_call(:def, :id => 3, :other_id => 2, :thing_id => 3, :ip_address => '127.0.0.1', :role_id => 'b1d4a2', :category_id => '45be3f' ) # ...more of the above... end end
The upside is that the test is explicit in the arguments and parameters that will be passed to the method. The expectation is far more clear and it increases readability. Tests are used to double-check our work but if the code in those tests is dense, nested and hard to understand, then we can’t double-check our work effectively. The Python philosophy of readability and explicitness is at play here. I would also say that the “flat is better than nested” and the “sparse is better than dense” concepts in the Zen of Python are also at work.
While some of the ideas here are essential to good software development and software engineering, they are uniquely embedded within Python. These ideas are embodied within the Zen of Python which sets the standard and affects Python and its community. With Sphinx and Jupyter, the Python philosophy becomes more widespread.