Zen of Python 'Explicit is better than implicit'

Question:

I’m not sure if this is an opinionated question or if it is me misunderstanding what ‘implicit’ and ‘explicit’ really means in the context of Python.

a = []

# my understanding is that this is implicit
if not a:
   print("list is empty")

# my understanding is that this is explicit
if len(a) == 0:
   print("list is empty")

I’m trying to follow the Zen of Python rule, but I’m curious to know if this applies in this situation or if I am over-thinking it? Appreciate any guidance I can get.

Asked By: sir_chocolate_soup

||

Answers:

The two statements have very different semantics. Remember that Python is dynamically typed.

For the case where a = [], both not a and len(a) == 0 are equivalent. A valid alternative might be to check not len(a). In some cases, you may even want to check for both emptiness and listness by doing a == [].

But a can be anything. For example, a = None. The check not a is fine, and will return True. But len(a) == 0 will not be fine at all. Instead you will get TypeError: object of type 'NoneType' has no len(). This is a totally valid option, but the if statements do very different things and you have to pick which one you want.

(Almost) everything has a __bool__ method in Python, but not everything has __len__. You have to decide which one to use based on the situation. Things to consider are:

  • Have you already verified whether a is a sequence?
  • Do you need to?
  • Do you mind if your if statement crashed on non-sequences?
  • Do you want to handle other falsy objects as if they were empty lists?

Remember that making the code look pretty takes second place to getting the job done correctly.

Answered By: Mad Physicist

Try to think of:

if not a:
    ...

as shorthand for:

if len(a) == 0:
    ...

I don’t think this is a good example of a gotcha with Python’s Zen rule of "explicit" over "implicit". This is done rather mostly because of readability. It’s not that the second one is bad and the other is good. It’s just that the first one is more skillful. If one understands boolean nature of lists in Python, I think you find the first is more readable and readability counts in Python.

Answered By: Harlin

Though this question is old, I’d like to offer a perspective.

In a dynamic language, my preference would be to always describe the expected type and objective of a variable in order to offer more purpose understanding. Then use the knowledge of the language to be succinct and increase readability where possible (in python, an empty list’s boolean result is false). Thus the code:

lst_colours = [] 

if not lst_colours: 
  print("list is empty")

Even better to convey meaning is using a variable for very specific checks.

lst_colours = []
b_is_list_empty = not lst_colours

if b_is_list_empty: 
  print("list is empty")

Checking a list is empty would be a common thing to do several times in a code base. So even better such things in a separate file helper function library. Thus isolating common checks, and reducing code duplication.

lst_colours = []

if b_is_list_empty(lst_colours): 
  print("list is empty")


def b_is_list_empty (lst):
  ......

Most importantly, add meaning as much as possible, have an agreed company standard to chose how to tackle the simple things, like variable naming and implicit/explicit code choices.

Answered By: ips1 38
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.