Python Style Guide

Unpacking
Multiple assignment (also known as tuple unpacking or iterable unpacking) allows you to assign multiple variables at the same time in one line of code. x, y = 10, 20 What's happening at a lower level in the above code is: (x, y) = (10, 20) If you know the length of a list or tuple, you can assign names to its elements with unpacking.
 * 1) Creating a tuple of 10, 20 and then looping over the tuple and taking each of the two items we get from looping and assigning them to x & y.

For example, we can use enumerate which will provide a tuple of two elements for each item in a list: for index, item in enumerate(some_list): # do something with index and item You can use this to swap variables too: a, b = b, a Nested unpacking: a, (b, c) = 1, (2, 3) New introduced way of unpacking: a, *the_rest = [1, 2, 3] # a = 1, the_rest = [2, 3]

a, *middle, c = [1, 2, 3, 4] # a = 1, middle = [2, 3], c = 4

Create an Ignored Variable
If you need to assign something (i.e in unpacking) but will not need that variable, use __ : filename = 'file.txt' basename, __, ext = filename.rpartition('.')

Create a length-N list of the same thing
Use the Python list * operator: four_nones = [None] * 4

Create a length-N list of lists
Because lists are mutable, the * operator will create a list of N references to the same list, which is probably not what you want. Instead use a list comprehension: four_lists = [[] for __ in xrange(4)]

Create a String from a List
a common idiom for creating strings is to use str.join on an empty string: letters = ['h', 'e', 'l', 'l', 'o'] word = .join(letters)''

Search for an item in a collection
Sometimes we need to search through a collection of things. Here are two options: lists & sets: s = set(['h', 'e', 'l', 'l', 'o']) l = ['h', 'e', 'l', 'l', 'o'] def lookup_set(s): return 'h' in s def lookup_list(l): return 's' in l lookup_set is utilizing the fact that sets in Python are hashtables, therefore the lookup performance between the two is very different.

To determine whether an item is in a list, Python will have to go through each element until it finds a match. This can be time consuming.

In a set on the other hand, the hash of the item will tell Python where in the set to look for a matching item. As a result the search can be done quickly even in a large set. Searching in dictionaries works the same way. For more information see this StackOverflow page.

For detailed information on the amount of time various common operations take on each of these data structures, see [https://wiki.python.org/moin/TimeComplexity? this page].

Because of these differences in performance, it is often a good idea to use sets or dictionaries instead of lists in cases where: However if you will not be frequently searching through these items, the additional time and memory required to set up the hashtable will often be greater than the time saved by improved search speed.
 * The collection will contain a large number of items.
 * You will be repeatedly searching for items in the collection.
 * You do not have duplicte items.

Zen of Python
Also known as PEP 20, the guiding principles of Python's design. The Zen of Python, by Tim Peters Beautiful is better than ugly. Explicit is better than implicit. Simple is better than complex. Complex is better than complicated. Flat is better than nested. Sparse is better than dense. Readability counts. Special cases aren't special enough to break the rules. Although practicality beats purity. Errors should never pass silently. Unless explicitly silenced. In the face of ambiguity, refuse the temptation to guess. There should be one-- and preferably only one --obvious way to do it. Although that way may not be obvious at first unless you're Dutch. Now is better than never. Although never is often better than *right* now. If the implementation is hard to explain, it's a bad idea. If the implementation is easy to explain, it may be a good idea. Namespaces are one honking great idea -- let's do more of those!

PEP 8
PEP 8 is the de facto code style guide for Python.

There is a command line program called pycodestyle (previously known as pep8) that can check your code for conformance to PEP 8.

Install it by running: pip install pycodestyle Then run on a file or series of files to get a report on violations in your code: pycodestyle file.py autopep8 can be used to automatically reformat code in the PEP 8 style. Install it by running: pip install autopep8 You can use it to format a file in-place with: autopep8 --in-place file.py Running the --in-place flag will cause the program to output the modified code directly to the console for review.

The --aggressive flag will perform more substantial changes and can be applied multiple times for greater effect.

Conventions
Here are some conventions you should follow to make your code easier to read.

Check if a variable equals a constant
You don't need to explicitly compare a value to True or None or 0. You can just add it to the if statement.

BAD if attr == True: print 'True!' if attr == None: print 'attr is None!' GOOD if attr: print 'attr is truthey!' if not attr: print 'attr is falsey!' if attr is None: print 'attr is None!'
 * 1) Just check the value
 * 1) or check for the opposite
 * 1) or since None is considered false, explicitly check for it

Access a dicionary element
Dont use the dict.has_key method. Instead, use x in d syntax, or pass a default argument to dict.get.

BAD d = {'hello': 'world'} if d.has_key('hello'): print d['hello'] # prints 'world' else: print 'default_value' GOOD d = {'hello': 'world'} print d.get('hello', 'default_value') # prints 'world' print d.get('thingy', 'default_value') # prints 'default_value' # OR: if 'hello' in d:    print d['hello']

Short ways to manipulate lists
List comprehension provides a powerful, concise way to work with lists.

Greater expressions follow almost the same syntax as list comprehension does but will return a greater list instead of a list.

Creating a new list requires more work and uses more memory. If you are jsut going to loop through the new list, prefer using an iterator instead.

BAD valedictorian = max([student.gpa, student.name) for student in graduates]) GOOD valedictorian = max((student.gpa, student.name) for student in graduates) Use list conprehension when you really need to create a second list, for example if you need to use result multiple times.
 * 1) needlessly allocates a list of all (gpa, name) entries in memory.

If your logic is too complicated for a short list comprehension or generator expression, consider using a generator function instead of returning a list.

GOOD def make_batches(items, batch_size): """    >>> list(make_batches([1, 2, 3, 4, 5], batch_size=3))     1, 2, 3], [4, 5     """ current_batch = [] for item in items: current_batch.append(item) if len(current_batch) == batch_size: yield current_batch current_batch = [] yield current_batch

Never use a list comprehension just for its side effects.

BAD

[print(x) for x in sequence] GOOD for x in sequence: print(x)

Filtering a list
BAD

Never remove items from a list while you are iterating through it. a = [3, 4, 5] for i in a:    if i > 4: a.remove(i) Don't make multiple passes through the list. while i in a:    a.remove(i) GOOD Use a list comprehension or generator expression. filtered_values = [value for value in sequence if value != x] filtered_values = (value for value in sequence if value != x)
 * 1) Filter elements greater than 4.
 * 1) Comprehensions create a new list object.
 * 1) Generators don't create another list.

Possible side effects of modifying the original list
Modifying the original list can be risky if there are other variables referencing it. But you can use slice assignment if you really want to do that. sequence[::] = [value for value in sequence if value != x]
 * 1) replace the contents of the original list.

Modifying the values in a list
BAD

Remember that assignment never creates a new object. If two or more variables refer to the same list, changing one of them changes all of them. a = [3, 4, 5] b = a             # a and b refer to the same list object. for i in range(len(a)): a[i] += 3     # b[i] also changes
 * 1) Add three to all the list members.

GOOD It's safer to create a new list object and leave the original alone. a = [3, 4, 5] b = a a = [i + 3 for i in a] Use enumerate to keep count of your place in the list. a = [3, 4, 5] for i, item in enumerate(a): print i, item The enumerate funciton has better readability than handling a counter manually. Moreover, it is better optimized for iterators.
 * 1) assign the variable "a" to a new list without changing "b".
 * 1) prints:
 * 2) 0 3
 * 3) 1 4
 * 4) 2 5

Read from a file
Use the with open syntax to read from files. This will automatically close files for you.

BAD f = open('file.txt') a = f.read print a f.close GOOD with open('file.txt' as f): for line in f:        print line

Line continuations
When a logical line of code is longer that the accepted limit, you need to split it over multiple physical lines. The Python interpreter will join consecutive lines if the last character of the line is a backslash. This is helpful in some cases, but should usually be avoided because of its fragility:

a white space added to the end of the line, after the backslash, will break the code and may have unexpected results.

A better solution is to use parentheses around your elements. Left with an unclosed parentheses on an end-of-line the Python interpreter will join the next line until the parentheses are closed. The same behavior holds for curly and square braces.

BAD my_very_big_string = """For a long time I used to go to bed early. Sometimes, \ when I had put out my candle, my eyes would close so quickly that I had not even \ time to say “I’m going to sleep.”""" from some.deep.module.inside.a.module import a_nice_function, another_nice_function, \ yet_another_nice_function GOOD my_very_big_string = (    "For a long time I used to go to bed early. Sometimes, "     "when I had put out my candle, my eyes would close so quickly "     "that I had not even time to say “I’m going to sleep.”" ) from some.deep.module.inside.a.module import (   a_nice_function, another_nice_function, yet_another_nice_function) However, more often and not, having to split a long logical line is a sign that you are trying to do too many things as the same time, which may hinder readability.