print('some string') # good
print 'some string' # bad
print()
has been moved to a function in Python 3 docs.
It has been backported to 2.7.
'{0.name} {0.address} {0.city}'.format(k) # good
'%s %s %s' % (k.name, k.address, k.city) # bad
String formatting with format()
is replacing %
. It is more powerful (argument unpacking, etc) and clear.
def do(a, b, c): # good
"""
does something
"""
pass
def do(a, b, c): # bad
'''
does something
'''
pass
Docstrings with single quotes don't follow ReST format, and can't be picked up by Sphinx.
quote = 'it isn\'t the gravity # good
quote = "it isn't the gravity" # bad
Single-quoted strings follows pep8, consistency is good across code base
def rotate_head(x, y, z, reverse=False):
pass
rotate_head(x=15, y=11, z=20, reverse=True) # good
rotate_head(15, 11, 20, True) # bad
Sacrificing brevity for readability is okay in this case. Makes a big difference for code clarity.
def filter_gradient(x, y, colors=None, timestamp=None): # good
if colors is None:
colors = []
if timestamp is None:
timestamp = datetime.now()
def filter_gradient(x, y, colors=[], timestamp=datetime.now()): # bad
pass
Default parameters are bound at function declaration, and not execution.
In the bad example above, multiple calls to filter_gradients
would mutate colors
every time.
For timestamp
, datetime.now()
is not called every time the function is invoked. So timestamp would be identical every time you called it.
Let git keep your history for you; if you comment out a block of code, consider just removing it instead. If you need it back, you can retrieve it from the git history. This keeps your code clean and minimizes confusion.
In the case where you are passing 5+ args to a function, it is probably better to split it up into either smaller functions or use **kwargs
. If you use **kwargs
be sure to document what keyword arguments will change the execution of your function.
For classes that are keeping the state of many things, first of all think about whether this needs to be a class. If it is a singleton, you probably can namespace it at the module level. If it needs to be a class, breaking it up into smaller classes and composing it using multiple inheritance can help manage the complexity. It will also make testing easier.
From PEP8, lines in python should be 79 lines or less. Some devs whine about this, but if you have a line longer than 79 chars, you're probably trying to do too much in that line. Examples of this: complicated list comprehensions and appending long strings. List comprehensions should be simple (comprehendable) and ''.join(iterable)
is the best way to join those strings. Each statement should read like a simple English sentence, not a paragraph or complex sentence.
animals = ['tiger', 'bear', 'cat, 'dog', 'donkey', # bad, make this all one line, or indent so each item has its own line
'zebra', 'lion', 'wallaby', 'chipmunk']
# same with dicts, but even more so
animals = { # good indentation
'name': 'tiger'
'species': 'feline',
'age': 10
}
For clarity, indent out your dicts and lists if they start to get long.
A lot of data structures in Python can be used interchangably, but each is suited to a specific purpose.
dict
- use when you have key:value pairs and order doesn't matter, use OrderedDict
if order matters
set
- use when you have homogenous items, they need to be unique, and order doesn't matter
list
- use when you have homogenous items, order matters, and its size won't change much
tuple
- use when position matters, heterogeneous items, and size never changes - can use namedtuple
for clarity
deque
- use when you would use a list, but you know you will be adding or removing elements from either end - much faster