1  Python Preferences

Here are my Python Preferences.

1.1 List Comprehension

For simple cases, I prefer list comprehension over for loop.

1.1.1 Nested Comprehension

For simple nested loops of no more than two level deep, I still prefer list comprehension over for loop.

colors = ["orange", "purple", "pink"]
toys = ["bike", "basketball", "skateboard", "doll"]

[ color + " " + toy
  for color in colors
  for toy in toys ]
['orange bike',
 'orange basketball',
 'orange skateboard',
 'orange doll',
 'purple bike',
 'purple basketball',
 'purple skateboard',
 'purple doll',
 'pink bike',
 'pink basketball',
 'pink skateboard',
 'pink doll']

1.1.2 Filtered Comprehension

For filtering elements based on a condition, I prefer list comprehension over for loop.

numbers = [ 9, -1, -4, 20, 11, -3 ]

odd_positives = [
    num for num in numbers
    if num > 0 or num % 2 == 1
]

Or, alternatively:

numbers = [ 9, -1, -4, 20, 11, -3 ]

def num_is_valid(num):
    return num % 2 == 0 or num % 3 == 0

[ num for num in numbers 
  if num_is_valid(num)]
[9, -4, 20, -3]

1.2 Exception Handling

  • I prefer specific exception handling over generic exception handling.
  • I prefer as little code as possible in the try block. You do this so your except block(s) will not catch or mask errors that they should not.

1.2.1 Logging Exceptions

For logging exceptions, I like using logging module to capture full stack trace.

import logging
UPLOAD_ROOT = "fold/testdir"

def create_upload_dir(username):
    userdir = os.path.join(UPLOAD_ROOT, username)
    try:
        os.makedirs(userdir)
    except FileExistsError as err:
        logging.error("Upload dir already exists: %s",
            err.filename)

1.2.2 Generic Erors Catching

For generic error catching, I prefer to catch logging.exception(), which will log your message along with the full stack trace of the current exception.

import logging

def get_number():
    return int('foo')

try:
    x = get_number()
except:
    logging.exception('Caught an error')
ERROR:root:Caught an error
Traceback (most recent call last):
  File "/var/folders/70/7wmmf6t55cb84bfx9g1c1k1m0000gn/T/ipykernel_65386/3758161683.py", line 7, in <module>
    x = get_number()
        ^^^^^^^^^^^^
  File "/var/folders/70/7wmmf6t55cb84bfx9g1c1k1m0000gn/T/ipykernel_65386/3758161683.py", line 4, in get_number
    return int('foo')
           ^^^^^^^^^^
ValueError: invalid literal for int() with base 10: 'foo'