Skip to content
All Posts

Python Tips, Part 2

A second collection of Python 2 techniques for strings, lists, mutable references, slicing, ellipses, and file operations.

Using join

For combining strings, join is generally recommended. The most frequently used string operations include join, split, and replace, along with partition.

You can pass a generator expression directly to join:

m = map(str, range(9))
','.join(x for x in m if x != '3')
# Rather than
','.join([x for x in m if x != '3'])

Removing multiple equal values from a list

list.remove is not suitable here because it deletes only the first matching value from left to right. Two better approaches are:

m = ['a', 'b', 'c', 'a']
m = filter(lambda x: x !='a', m)

Or:

m[:] = (x for x in m if x != 'a')

Generating a random string of n characters

import random
import string
rand_str = "".join([random.choice(string.letters+string.digits) for _ in xrange(n)])

Reference-type pitfalls

Function arguments

A default argument is evaluated only once, when the function is defined. Multiple calls therefore reuse the same mutable object:

Terminal window
def test(data, x=[]):
x.append(data)
return x
print test(3)
# [3]
print test(4)
# [3, 4]

Default values with dict.fromkeys

This has the same problem as a mutable default argument: the values for multiple keys refer to the same list. Using {} produces the same result.

>>> a = dict.fromkeys('bc', [])
>>> a['b'].append(6)
>>> a
{'b': [6], 'c': [6]}

Declaring multiple variables

It is common to need several empty lists or dictionaries. The following incorrect form makes multiple variables share the same [] or {}:

a = b = []
c = d = {}

Use separate objects instead:

a, b = [], []
# for a lot of var
c, d, e, f = [{} for _ in xrange(4)]

Immutable values such as int, str, and bool do not have this problem, so this is fine:

a = b = True

You can also delete multiple items in one del statement:

>>> a = range(3)
>>> del a[2], a[0]
>>> a
[1]

Slicing

Use a step of -1 to reverse a list:

>>> a = range(7)
>>> a[::-1]
[6, 5, 4, 3, 2, 1, 0]
>>> a[::2]
[0, 2, 4, 6]

Assigning an empty list to a slice removes that range, just like del a[1:4]:

>>> a = [1, 2, 3, 4, 5, 6, 7]
>>> a[1:4] = []
>>> a
[1, 5, 6, 7]

Remove items at even indexes:

>>> a = [0, 1, 2, 3, 4, 5, 6, 7]
>>> del a[::2]
>>> a
[1, 3, 5, 7]

Ellipsis

Ellipsis is mainly useful with multidimensional arrays, where it reduces the complexity of indexing. I rarely use it; a more detailed explanation can be found elsewhere.

>>> class C(object):
... def __getitem__(self, item):
... return item
...
>>> C()[1:2, ..., 3]
(slice(1, 2, None), Ellipsis, 3)

File operations

Reading an entire file

Use binary mode, such as rb. With r, only part of the file may be read.

with open(path, 'rb') as f:
return f.read()

Reading line by line

Treat the file object as an iterator:

Terminal window
with open(path, 'r') as f:
for line in f:
print line

Originally published on SegmentFault.