Skip to content

Latest commit

 

History

History
186 lines (133 loc) · 3.62 KB

File metadata and controls

186 lines (133 loc) · 3.62 KB

Common problems & best practices

This document is the result of code reviews and observations in the field. Although there are quite some style guides for Python, it may perhaps be useful to some anyway. It is of course work in progress.

Useful references:

Useful tools:

Control flow

When tempted to use pass in the body of a conditional statement, and have only statements that do actual work in the else part, simply use the negation of the condition, and dropt the else, e.g.,

if x < 10:
    pass
else:
    total += x

is better replaced by:

if x >= 10:
    total += x

A construct such as:

for i in range(len(x)):
    f(x[i], y[i])

can be replaced by:

for x_elem, y_elem in zip(x, y):
    f(x_elem, y_elem)

A construct such as:

for i in range(len(x)):
    f(i, x[i])

can be replaced by:

for i, x_elem in enumerate(x):
    f(i, x[i])

Regular expressions

When a regular expression is compiled, an object is created with its own methods, e.g., search, so

import re
reg_expr = re.compile(r'\d+')
...
if reg_expr.search(some_str):
    ...

rather than

reg_expr = re.compile(r'\d+')
...
if re.search(reg_expr, some_str):
    ...

Note the distiction between search and match: the former matches at any point in the target stting, the latter only at the beginning of the target string.

Files and I/O

When a file is opened in a with statement, i.e., under control of a context manager, one need not explicitely close the file, since this is handled by the context manager.

Data structures

When a list as a data structure where the items have non-homogeneous types, especially lists or tuples, it is probably wise to consider introducing a class to make code more robust, and easier to read and hence maintain.

When using a dictionary to represent static properties of things, consider using a collections.namedtuple, or introducnig a class.

To add all element of a list b to list a, do not use:

for x in b:
    a.append(x)

but rather:

a.extend(b)

Similarly, to add/update all key/value pair of a dictionary b to a dictionary a, don not use:

for key in b:
    a[k] = b[k]

but rater use:

a.update(b)

The set data type has an update method with similar semantics.

String formatting

It is always better to resist the temptation of using positional substitution when using format, i.e., better replace:

file_name = '{0}.txt'.format(base_name)

by:

file_name = '{base}.txt'.format(base=base_name)

Starting from Python 3.6, you can use f-strings to accomplish the same, i.e.,

file_name = f'{base_name}.txt'

It is of course possible to create format strings programmatically, e.g.,

for suffix in ['txt', 'csv']:
    file_tmpl = '{{base}}.{suffix}'.format(suffix=suffix)
    for basename in basenames:
        file_name = file_tmpl.format(base=basename)
        ...

Instead of:

data_str = '{0}\t{1}\t{2}\t{3}'.format(itme1, item2, item3, item4)

consider:

data_str = '\t'.join([itme1, item2, item3, item4])