earn the White PyBites Ninja earn the Yellow PyBites Ninja earn the Orange PyBites Ninja right arrow earn more PyBites Ninja belts and certificates
The best way to learn to code in Python is to actually use the language.

Our platform offers effective Test Driven Learning which will be key to your progress.

Join thousands of Pythonistas and start coding!

Join us on our PyBites Platform
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.