Improve Your Python

3 Shortcuts for More Concise and Meaningful Python

David Muller
The Pragmatic Programmers

--

My first book, Intuitive Python: Productive Development for Projects that Last, is now available from The Pragmatic Programmers. In fact, if you make it to the end of this article, you’ll get a promo code that will save you 35 percent on the ebook. With Intuitive Python, you hone your Python skills with a guided tour of the standard library and excellent third-party tools.

Many of my favorite Python patterns and idioms are in Intuitive Python, but not all of them. These three shortcuts will help you write more concise and meaningful Python. We’ll start off with a tip for manipulating files easily.

Shortcut 1

Use pathlib to read files without using a with context manager

You’ll often use a with context manager when reading a file in Python to ensure that the underlying file is closed even if your program raises an unexpected exception. For example:

In the canonical example above, we opened example-file.txt using with context manager. f is bound to a file object that you can use to interact with the file. In this case, we fetch the contents of example-file.txt using the read method. with open returns a context manager that ensures the underlying file is closed either at the end of the with block or after an unexpected exception is raised in the body of the with statement.

The example works well, but it is a little verbose. The pathlib module offers a number of conveniences for working with file system paths and files on your file system---I highly recommend it in general. One particular convenience offered by pathlib is the pathlib.Path.read_text method. pathlib.Path.read_text lets you read the contents of a file without explicitly using a context manager:

In the above example, you instantiate a Path object with the path you are interested in opening: example-file.txt. Calling the read_text method of the new Path object returns the text contained in the underlying file. The value of contents is the same as the value of contents in the first example.

In case you are concerned about files being closed properly, note that Path.read_text uses a with context manager under the hood to ensure that the underlying file is closed appropriately. The with context manager is still in play to ensure the file is closed for you, just abstracted away.

Path also offers three related additional methods beyond read_text. Namely: read_bytes, write_text, and write_bytes. With these four methods, you can cover the majority of your file reading/writing needs without repeatedly writing with open(...) context managers.

As you start working more withPath objects, you’ll also find that Path objects can augment and improve on functions you’re used to importing from the os module.

With pathlib added to your toolbelt, let’s look at another shortcut. Next, we’ll count iterations of a loop with the built-in function enumerate.

Shortcut 2

Get the current index in a for loop using enumerate

Image by Lotus_studio on Shutterstock

It’s often useful to have a loop counter in a for loop. To get the current index in a for loop, you could initialize a counter variable and manually increment it. It's more concise, however, to use the Python built-in function enumerate:

story defines a string with three phrases all separated by newlines (\n). Splitting on \n creates a list with three entries: "What", "is", and "your favorite color?". This list is bound to the variable named lines. Iterating over the lines list with a for loop successively yields all three parts of the story. Wrapping lines in a call to enumerate makes Python yield an additional element on every iteration of the for loop. index is bound to the return value from enumerate (which is an increasing integer counter), and line is an entry from the lines list. The final result is that 0 is yielded with "What", 1 is yielded with "is", and 2 is yielded with "your favorite color?". You've just used enumerate to generate line numbers for every line in a string.

enumerate also supports a start argument that allows you to modify which integer enumerate begins counting at. For example, if you wanted to start your loop counter at 1 you could write the following:

The above example is identical to the previous one, except we’ve added start=1 as an argument to enumerate. This change adjusts the final outputted counting sequence of line numbers from 0, 1, 2 to 1, 2, 3.

Now you know how to save some time with enumerate. Next up is a special class that allows your code to present a dictionary interface that doesn’t allow modifications.

Shortcut 3

Use MappingProxyType to create a read-only dictionary

Photo by Fallon Michael on Unsplash

You can manipulate a normal Python dictionary several ways: add keys, remove keys, and update keys to point to new values. If you are passing around data that shouldn’t be modified, like configuration data, special user data, and so on, you’ll want to create a dictionary data structure that cannot have keys added, removed, or changed. That’s where MappingProxyType comes in handy.

You can use MappingProxyType to create a view on a dictionary that cannot be updated, like this:

In the above example, we instantiated a MappingProxyType instance using a dictionary of user attributes. The returned MappingProxyType instance is bound to a variable named user_details. Trying to change the value of the "id" key to 44 results in a TypeError Exception--- user_dict doesn't allow keys to be added, removed, or replaced.

Similarly, if you tried to say user_details.pop("id") or user_detail["new-key"] = "new-value" you would also have gotten an Exception forbidding the change. MappingProxyType can be useful when you want to pass a mapping to code you might not necessarily trust---you can help guarantee that your input object won't be manipulated unexpectedly.

Python’s built-in frozenset type may also be of interest to you. Similar to how MappingProxyType creates a read-only view of a dictionary, you can use frozenset to create a read-only view of a set data structure.

You’ve just learned about three quick shortcuts that can improve your Python. If you’d like to dig into more Python, check out Intuitive Python. Through July 15th, you can use promo code intuitivepython35 on The Pragmatic Bookshelf website to save 35% on the ebook. Note that promo codes are not applicable to prior purchases.

--

--

The Pragmatic Programmers
The Pragmatic Programmers

Published in The Pragmatic Programmers

We create timely, practical books and learning resources on classic and cutting-edge topics to help you practice your craft and accelerate your career.

David Muller
David Muller

Written by David Muller

Professional software engineer, and author of Intuitive Python.