Ditch These 7 Habits From Your Python Codebases

Advertisements

Working with file streams is probably the most common thing that we do as we started learning Python. Most of the tutorials would start off by telling us to open and close files using the example below:

Support Us

BTC:bc1qsg4s7gmxj88ztnux6en577anzuvm0rvjhne8cp

ETH:0xBB0f503e443F2b2646785B014A951Fc8AAd9561E

Donation
f = open("stocks.txt", "r")
data = f.read()
f.close() # NOTE: Always remember to close!

In such cases, we would often be reminded to always close the file after using it because:

  • It consumes our limited system resource
  • It prevents us from moving or deleting the files

Instead, the best practice here is to always use context manager (the with statement) in Python while dealing with file operations. Here’s an example:


with open("stocks.txt", "r"):
data = f.read()

Using context manager here also helps us with closing the file during exceptions.

Well, you could argue that we could also use the try-finally approach here instead. Though, the with statement simplifies our code to just two lines.

This is probably one of the more confusing gotchas for newcomers in Python.

I must admit, this one caught me off guard when I first started learning Python many years ago. I remember when I was first introduced to the wonders of default arguments when working with functions, I was using it mindlessly like nobody’s business. Here’s an example:

When a function is defined, the default arguments (e.g. storage in the example above) are created (i.e. evaluated) only once.

As a list in Python is mutable, the list will be modified every time you call the add_book function. Here, the same list is used over and over again instead of creating a new list.

The same concept applies while working with other mutable objects, i.e. dictionary in Python.

List comprehension is undoubted one of the most distinct features in Python. Unarguably, it helps to improve code readability and is often considered more elegant and “pythonic”.

Having that said, new Python developers may struggle to fully leverage this feature, or at least get used to using it at the beginning. Here’s an example:

Learn to use list comprehension

If you are new to Python, take a breath and spend some time learning list comprehensions. It will help you immensely, I promise.

The same logic applies to using dictionary comprehensions in Python.

We get it. List comprehensions are “pythonic”. However, I have seen way too many instances where the use of list comprehension is being abused in various forms.

Worse, some list comprehensions are written to the extent that the code is not even readable anymore, defeating the original purpose of using list comprehensions.

Here’s an example of what you should NOT do:

Don’t do these

While list comprehensions are more compact and run faster, we should avoid writing long and complex list comprehensions (especially in a single line) to ensure code readability. Do not get bogged down with list comprehensions.

I was guilty of this. Very guilty. As a beginner, I did not appreciate how some codebases explicitly catch exceptions. Back then, I find them overly verbose and redundant. I guess I was just being lazy.

Here’s an example of what a bare except look like:

Avoid doing this

In short, we should never use bare except as it catches all exceptions, including some that don’t want, i.e. KeyboardInterrupt in this example where we want to exit our application.

On top of that, it makes debugging a nightmare as it can cause our application to fail without us knowing why. So, stop using exceptions like this.

Does it really matter though? I have seen too many in wild Python code. In case you didn’t know, they are different.

  • The is operator checks if the two items reference the same object (i.e. present in the same memory location). A.k.a reference equality.
  • The == operator checks for value equality.

Here’s a brief example of what I mean:

Remember, listA and listB are different objects

Here’s a summary of the Do’s and Don’ts of using is and == operator:

Using if baz and if not baz

Many would consider this an act of convenience. But this is just plain lazy.

By using import *, you risk polluting the current namespace as it imports all the functions and classes from the library.

What does “polluting namespace” even mean? Well, in layman terms, it basically means that whatever functions (or classes) that you have imported with import * may clash with the functions defined by you.

Basically, you run the risk of overriding variables or functions and eventually it becomes incredibly hard to tell which function is from which.

Source

Leave a comment

Your email address will not be published. Required fields are marked *