Wednesday, October 13, 2021

The Python Coding Blog: Python Readability, the PEP 8 Style Guide, and Learning Latin

Over the past couple of years, I’ve decided to start ticking things off my lifetime to-do list. We all have things “we’d like to do at some point when we have time.” I finally started carving time out of my days to do these things. In the past two years, I’ve learned touch-typing (that’s right, I had never learned this), started learning and playing chess, and now I’ve started learning Latin. Yes, Latin! “What’s Latin got to do with Python readability and the PEP 8 style guide?” I can hear you ask.

Latin is a fascinating language. As someone who loves languages—the human ones and the computer ones—I’ve always wished I had learned Latin when I was at school. One of the many things I found intriguing is that there were no punctuation marks or spaces in the original form of the language. thereaderhadtoinferthewordsandpauseswhenreading. The language was mostly spoken in those days, and only scholars tended to read and write.

Over time, the need to make the text more readable became important. Punctuation was one of the tools that made its way into languages to help with this. This made the text easier to read. But it also ensured that the author’s thoughts and ideas were conveyed more precisely.

You can read more about the mysterious origin of punctuation, but in this article, I’m more interested in the similar path that coding took in the past decades as programs become more complex, more widespread, and the need to make them more readable by human beings become more important.

Coding In The Past

In the earlier days of computer programming, there were only a few programmers. The complexity of computer code was limited primarily by the hardware restrictions on memory and speed of execution. Code was rarely shared and read by others, and teams working on software were small and often consisted of just one person.

Certain habits made sense in those early days and a bit later too. Making sure the code was short had some benefits in early computer programs. So did using short variable names, preferably one or two letters long. In the very early days, code had to be converted into punch cards that were then fed into the computer!

Even as punch cards were no longer needed, the desire to be efficient often led to using short variable names and keeping the code as short as possible. Who wants to type in more when you can get away with less?

The Shift Towards More Readable Code

However, as computers became faster and included more memory, programs decame more complex. Programming languages also evolved to better suit these new, longer, more complex programs. Teams become larger and collaboration more common. And the need to maintain code become just as important, if not more important, than writing the code in the first place.

This evolution naturally led to computer code becoming more readable by humans, too. Python is one of those “newer” languages and it has readability built into its DNA. Python’s syntax makes Python code more similar to plain English than code in most other languages. But Python goes further than this. It also encourages Python programmers to write neat, readable code. It does this mainly through its style guide, PEP 8, which I’ll talk about shortly.

Not every programmer is entirely on board. Old habits die hard. Some programmers still don’t place a high level of importance on how readable computer code is. And that’s fine. Defining what’s best when writing code is subjective. However, the trend seems to be going away from the old style of writing code towards writing code that’s more readable.

Indeed, you can see this trend within the Python codebase itself. Consider some “old” functions in Python, such as randint() from the random module. Perhaps, if this function were written today it would have been called random_integer. And the worst offenders in the standard library when it comes to readability, or lack of it, are the pair of functions in the datetime module called strptime and strftime. You can also find similarly named functions in the time module, which predate the ones in datetime, but most people will be familiar with those in the datetime module.

These “badly-named” functions are rare in Python. More modern libraries and newer additions to the language are unlikely to have such unreadable names.

Why Is Python Readability Important?

Have a look at the following Python program, read through it, and try to understand what it does:

p = [3.5, 2.1, 9.8, 7]
q = [2, 3, 1, 2]
i = [x * y for x, y in zip(p, q)]
t = sum(i)
print(t)

This program outputs 37.1. As long as you’re familiar with python list comprehensions and the zip() built-in function, you probably didn’t have too many issues understanding this program. However, look at the code below:

prices = [3.5, 2.1, 9.8, 7]
quantities = [2, 3, 1, 2]

income = [price * quantity for price, quantity in zip(prices, quantities)]

total_income = sum(income)
print(total_income)

There are no additional comments in this version of the code compared to the previous one. In fact, the two programs are identical except for the choices of variable names (and the use of blank lines to separate sections of code). The second version is easier to understand because it provides the context of what the code is doing. The author of the first program knew that p stands for prices and q for quantities, and so on. But this is not obvious for a reader of the program. The author may also struggle to remember what the one-letter variables stand for six months later!

The example above is a simple one, perhaps even trivial. However, this concept becomes so much more important as programs become longer and more complex.

Another Example

Let’s have a look at another example. Can you figure out what’s the purpose of the code in this function? This is the same example used in the Snippets section of The Python Coding Book chapter on functions:

def ins(n):
    return n.split()[0][0].upper() + ". " + n.split()[1][0].upper() + "."

Take your time to work through this one-liner and understand what it does.

Once you’re done, you can try it out with:

print(ins("william shakespeare"))

# Output: W. S.

The function returns the initials from a name. Even the person who writes this code will need a bit of time to digest it again a few months later. And if you want to make changes to this function, you’ll need to spend a bit of time making sure you understand each part of this one-line function very well.

Now, consider the following function:

def get_initials(full_name):
    """
    Get initials from a full name with two parts, such as 'John Smith'
    :param full_name: str, full name containing one first name and one last name,
    separated by a space
    :return: str with initials in the form 'J. S.'
    """
    full_name = full_name.upper()
    first_name, last_name = full_name.split()  # Assumes full_name has two words
    return f"{first_name[0]}. {last_name[0]}."

print(get_initials("william shakespeare"))

# Output: W. S.

This function is ten lines long, rather than just two. It performs the same task as the ins() function above. However, note that it’s easier to understand what this function does. The main reasons are:

  • The function name clearly describes what the function does. This wasn’t the case in the first function
  • The parameter name n in the function signature was replaced by full_name in the second version. Again, the use of a descriptive name makes all the difference when reading and understanding the code
  • The get_initials() function has a docstring explaining what the function does and what input parameter is needed. The docstring also clarifies what data the function returns
  • The logic of the algorithm is separated into steps:
  • First, full_name is replaced with the uppercase version of the string
  • Then the two separate parts of the full name are split using the split() string method
  • Finally, the function returns the initials using an f-string and the variables defined in the previous line

Different programmers will make different decisions on how to write the code to make it more readable. However, Python offers some help with this. This help comes in the form of PEP 8.

The PEP 8 Style Guide and Python Readability

PEPs are Python Enhancement Proposals which, when accepted, become a part of the language. Often PEPs deal with new aspects of the language or its syntax. However, PEP 8 deals with the recommended coding style when coding in Python.

The PEP 8 style guide is a pragmatic document that makes opinionated suggestions without being too dogmatic. It ensures consistency among Python programmers and is one of the tools that help to make Python code more readable. It’s not the only tool, though. You can still write code that scores poorly on readability while adhering to PEP 8 perfectly. So, learning PEP 8 is a necessary but not a sufficient requirement to writing readable code.

For those who are new to programming or Python, it’s well worth a quick browse through the PEP 8 document, and then you can return to it later for a more thorough read.

Some of the points in it may initially look bizarre, but they all have a purpose! Yes, even the blank line at the end of a script is there for a reason! If you’re using an IDE such as PyCharm, you’re likely to be warned by your editor when you break PEP 8 guidelines.

I’ll finish this section with a couple of quotes directly from PEP 8:

One of Guido [van Rossum, Python’s creator]’s key insights is that code is read much more often than it is written. The guidelines provided here are intended to improve the readability of code and make it consistent across the wide spectrum of Python code. As PEP 20 says, “Readability counts”.

PEP 8 — Style Guide for Python Code

But also:

However, know when to be inconsistent — sometimes style guide recommendations just aren’t applicable. When in doubt, use your best judgment.

PEP 8 — Style Guide for Python Code

If you want to dive a bit more into the ethos of Python, you can read The Zen of Python by Tim Peters, which you can get by typing import this into a Python console.

Final Words

Just as punctuation came into written languages to make them more readable, programming has been undergoing a similar transition in recent years. In the case of readability in coding, it’s not the punctuation marks that make the difference but the coding style.

In Python, readability counts, as it says in the Zen of Python. And this concept is valid in all of modern programming and not just in the Python world. Even if you’re only writing code for yourself, it’s good to get into the habit of making readability count when coding. Modern IDEs help. The desire to keep variable names very short, for example, is no longer an issue when your editor will autocomplete longer variable and function names that are more descriptive, and therefore, more readable.

Always remember that you’re making your code more readable, not just for the sake of others who may read your code in the future. You’re also making life easier for your future self when you return to your code to make changes or enhancements. Spending a bit more time to make your code readable will save you a lot of time in the future trying to figure out what you wrote in the past!

Further Reading

  • A version of the Python style guide written ‘for humans’ is available at pep8.org
  • The standalone Chapter: The White Room: Understanding Programming in The Python Coding Book, is not about readability, but it’s worth a read if you’re learning to code in Python and you’d like to truly understand what’s happening behind the scenes

Get the latest blog updates

No spam promise. You’ll get an email when a new blog post is published


The post Python Readability, the PEP 8 Style Guide, and Learning Latin appeared first on The Python Coding Book.



from Planet Python
via read more

No comments:

Post a Comment

TestDriven.io: Working with Static and Media Files in Django

This article looks at how to work with static and media files in a Django project, locally and in production. from Planet Python via read...