What are the most common improvements of Python code you've applied or seen applied (to you or someone else) here on codereview?
In Python you should rarely use
while loops or
for x in range(n) loops. Python has a wide variety of tools like
itertools.* to iterate over pretty much anything with a
for loop and an iterator.
for x in range(len(data)): print(data[x])
for item in data: print(item)
for x in range(len(data)): print((x + 1, data[x]))
for index, item in enumerate(data, start=1): print((index, item))
for x in range(len(data1)): print(data1[x] + data2[x])
for item1, item2 in zip(data1, data2): print(item1 + item2)
(In Python 2, you'd use
from future_builtins import zip to get the version of
zip that returns an iterator instead of a list.)
Instead of closing files yourself, have the
with statement do it for you:
with open('filename') as filehandler: do_stuff(filehandler)
filehandler = open('filename') do_stuff(filehandler) filehandler.close()
Beyond saving you to have to close the file manually, the
with statement also ensures the file will be closed even though exceptions rise during execution of
do_stuff() function. That is, you get to avoid this ugliness:
filehandler = open('filename') try: do_stuff(filehandler) finally: filehandler.close()
PEP 8 -- Style Guide for Python Code
To follow a standard coding style is very important.
It's even more important if you want other people to look at your code.
By following the official coding style guide your code will be more readable and it will be way more easy for others programmers to understand it. You should really read PEP8, it may seem long, but it's just a bunch of rules, the sooner you'll start to follow them, the better will be.
Anyway this is an attemp to summarize the most "overlooked" ones:
Use 4 spaces per indentation level and never mix tabs and spaces.
Limit all lines to a maximum of 79 characters. 80 is okey too.
i = 10 i = i + 1 i += 1
i=10 i=i+1 i+=1
Conventions for writing good documentation strings (a.k.a. "docstrings") are immortalized in PEP 257, so take a look at that one too. Anyway in brief:
One-line Docstrings: One-liners are for really obvious cases. They should really fit on one line. For example:
def add(a, b): """Return a + b, for a and b numbers..""" return a + b
Multi-line Docstrings: Multi-line docstrings consist of a summary line just like a one-line docstring, followed by a blank line, followed by a more elaborate description.
The docstring for a function or method should summarize its behavior and document its arguments, return value(s), side effects, exceptions raised, and restrictions on when it can be called (all if applicable). Optional arguments should be indicated. It should be documented whether keyword arguments are part of the interface.
def fetch_bigtable_rows(big_table, keys, other_silly_variable=None): """Fetches rows from a Bigtable. Retrieves rows pertaining to the given keys from the Table instance represented by big_table. Silly things may happen if other_silly_variable is not None. """ # code starts from here
I don't want to make this section too complex, so other than PEP 257 you can find more in the google guidelines, at this example of pypi project, and this SO question: Docstrings - one line vs multiple line.
Note: If a docstring become too complex to write/read/follow it's usually a sign that the function need to be refactored in two or more simple ones.
You should read them all, anyway here's a small summary of the most common ones:
"normal" variables and functions:
Dumb and verbose example:
def my_function(first_arg, second_arg): sum_of_args = first_arg + second_arg # ...
class MyClass: # ...
Constants are usually defined on a module level and written in all capital letters with underscores separating words. Examples:
MAX_OVERFLOW = 100 TOTAL = 70
Have as little code as possible in the global namespace. Most logic should be in functions, classes, or methods. This helps prevent polluting the global namespace and will run faster.
On a related note, the main function should look something like this:
def main(list_of_stuff): ... if __name__ == "__main__": main(sys.argv)
This is to avoid the globally-defined things, e.g.
sys.argv in this case, to be executed should the module be called from another Python module. In our example,
main() gets its
list_of_stuff from the command line if ran directly, but if called from another module, that module must provide that list.
Looking through my own reviews, I'd say that the two issues that come up almost every time are:
Docstrings. It feels as if nearly every review I have written has begun by noting the absence of user documentation in the poster's code. (For example.) As a user I expect to be able to type
help(module.function)into the Python interpreter, and as a programmer I find that the discipline of specifying exactly what each function and class should do helps enormously to come up with good designs, good code structure, and good names.
Doctests. For some types of code these are a really simple way to combine example code with small test cases. Of course no-one should be fooled into thinking that they are a substitute for a proper test suite, but they are so easy to write that they deserve to be much more widely known and used. For example, here's a question containing a bug that would have been easily caught by a simple doctest or two. And here's another.
The third most common problem is probably inappropriate choice of data structures and algorithms (for example, trying to write a parser without a lexer). But that's not really specific to Python.