Click here to code!

Beautiful, idiomatic Python

Posted by Bob on Tue 10 January 2017 in Best practices • 2 min read


The slidedeck is here. Thanks Jeff Paine for this awesome set of notes.

When you see this, do that instead

A quick digest below. Note that Python3 takes some of these features to the next level, so switching from 2 to 3 is a good idea :)

  • Use enumerate to loop over collections and indices, use reversed(collections) to loop backwards.

  • Use the zip built-in to loop over two collections: zip(collection1, collection2). To make a dict from two collections: dict(zip(names, colors)). Use zip_longest if the collections are not of the same length.

  • Use the sorted key argument to customize sort order of a collection, so to sort by dict value you can use: sorted(d.items(), key=lambda a: a[1])

  • Use iter() if you need to call a function until a sentinel value, see a good example here.

  • The for / else construct can be useful to know if a loop made it to the end (that is no break was hit).

  • Dicts: don't mutate a dictionary when looping over it! In Python3 dictionaries have view objects: "The objects returned by dict.keys(), dict.values() and dict.items() are view objects. They provide a dynamic view on the dictionary’s entries, which means that when the dictionary changes, the view reflects these changes.". For Python2 use iteritems() which returns an iterator (faster).

  • Use collections.defaultdict to prevent initializing keys manually.

  • Use ChainMap to link (concatenate) dictionaries together.

  • Keyword arguments can make a function more readable, same goes for the light-weight namedtuple (collections module).

  • Unpacking: bob, julian = 'bob julian'.split(), or a variable swap is as easy as a, b = b, a (no temp variable).

  • Use ''.join(collection) instread of concatenating a string in a loop (more efficient).

  • Use deque if you need a stack / queue ('linked list') instead of a regular list ('array'). When you do somecollection.insert(0, 'value'), it is time to change to a deque structure and use somecollection.appendleft('value').

  • Use decorators to factor-out administrative logic, for example @cache, @timeit, etc. (use functools.lru_cache for caching starting 3.2).

  • Use the with statement (context manager) to open and (automatically) close files. Another use case is threading locks or more generically when you need to factor-out "temporary contexts".

  • Generator expressions are faster, you can use them (instead of list comprehensions) in sum() / max() / min() to gain performance. Hard to beat this for compactness: sum(i**2 for i in range(10))

See an error in this post? Please submit a pull request on Github.