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 canjust add it to the if statement. See Truth Value Testing for alist of what is considered false.

Bad:

  1. if attr == True:
  2. print 'True!'
  3.  
  4. if attr == None:
  5. print 'attr is None!'

Good:

  1. # Just check the value
  2. if attr:
  3. print 'attr is truthy!'
  4.  
  5. # or check for the opposite
  6. if not attr:
  7. print 'attr is falsey!'
  8.  
  9. # or, since None is considered false, explicitly check for it
  10. if attr is None:
  11. print 'attr is None!'

Access a Dictionary Element

Don’t use the dict.has_key() method. Instead, use x in d syntax,or pass a default argument to dict.get().

Bad:

  1. d = {'hello': 'world'}
  2. if d.has_key('hello'):
  3. print d['hello'] # prints 'world'
  4. else:
  5. print 'default_value'

Good:

  1. d = {'hello': 'world'}
  2.  
  3. print d.get('hello', 'default_value') # prints 'world'
  4. print d.get('thingy', 'default_value') # prints 'default_value'
  5.  
  6. # Or:
  7. if 'hello' in d:
  8. print d['hello']

Short Ways to Manipulate Lists

List comprehensionsprovide a powerful, concise way to work with lists.

Generator expressionsfollow almost the same syntax as list comprehensions but return a generatorinstead of a list.

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

Bad:

  1. # needlessly allocates a list of all (gpa, name) entires in memory
  2. valedictorian = max([(student.gpa, student.name) for student in graduates])

Good:

  1. valedictorian = max((student.gpa, student.name) for student in graduates)

Use list comprehensions when you really need to create a second list, forexample if you need to use the result multiple times.

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

Good:

  1. def make_batches(items, batch_size):
  2. """
  3. >>> list(make_batches([1, 2, 3, 4, 5], batch_size=3))
  4. [[1, 2, 3], [4, 5]]
  5. """
  6. current_batch = []
  7. for item in items:
  8. current_batch.append(item)
  9. if len(current_batch) == batch_size:
  10. yield current_batch
  11. current_batch = []
  12. yield current_batch

Never use a list comprehension just for its side effects.

Bad:

  1. [print(x) for x in seqeunce]

Good:

  1. for x in sequence:
  2. print(x)

Filtering a list

Bad:

Never remove items from a list while you are iterating through it.

  1. # Filter elements greater than 4
  2. a = [3, 4, 5]
  3. for i in a:
  4. if i > 4:
  5. a.remove(i)

Don’t make multiple passes through the list.

  1. while i in a:
  2. a.remove(i)

Good:

Use a list comprehension or generator expression.

  1. # comprehensions create a new list object
  2. filtered_values = [value for value in sequence if value != x]
  3.  
  4. # generators don't create another list
  5. filtered_values = (value for value in sequence if value != x)

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.

  1. # replace the contents of the original list
  2. sequence[::] = [value for value in sequence if value != x]

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 them all.

  1. # Add three to all list members.
  2. a = [3, 4, 5]
  3. b = a # a and b refer to the same list object
  4.  
  5. for i in range(len(a)):
  6. a[i] += 3 # b[i] also changes

Good:

It’s safer to create a new list object and leave the original alone.

  1. a = [3, 4, 5]
  2. b = a
  3.  
  4. # assign the variable "a" to a new list without changing "b"
  5. a = [i + 3 for i in a]

Use enumerate() keep a count of your place in the list.

  1. a = [3, 4, 5]
  2. for i, item in enumerate(a):
  3. print i, item
  4. # prints
  5. # 0 3
  6. # 1 4
  7. # 2 5

The enumerate() function has better readability than handling acounter manually. Moreover, it is better optimized for iterators.

Read From a File

Use the with open syntax to read from files. This will automatically closefiles for you.

Bad:

  1. f = open('file.txt')
  2. a = f.read()
  3. print a
  4. f.close()

Good:

  1. with open('file.txt') as f:
  2. for line in f:
  3. print line

The with statement is better because it will ensure you always close thefile, even if an exception is raised inside the with block.

Line Continuations

When a logical line of code is longer than the accepted limit, you need tosplit it over multiple physical lines. The Python interpreter will joinconsecutive lines if the last character of the line is a backslash. This ishelpful 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 thecode and may have unexpected results.

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

Bad:

  1. my_very_big_string = """For a long time I used to go to bed early. Sometimes, \
  2. when I had put out my candle, my eyes would close so quickly that I had not even \
  3. time to say “I’m going to sleep.”"""
  4.  
  5. from some.deep.module.inside.a.module import a_nice_function, another_nice_function, \
  6. yet_another_nice_function

Good:

  1. my_very_big_string = (
  2. "For a long time I used to go to bed early. Sometimes, "
  3. "when I had put out my candle, my eyes would close so quickly "
  4. "that I had not even time to say “I’m going to sleep.”"
  5. )
  6.  
  7. from some.deep.module.inside.a.module import (
  8. a_nice_function, another_nice_function, yet_another_nice_function)

However, more often than not, having to split a long logical line is a sign thatyou are trying to do too many things at the same time, which may hinderreadability.