The Little Book of Python Anti-Patterns¶
Welcome, fellow Pythoneer! This is a small book of Python anti-patterns and worst practices.
Learning about these anti-patterns will help you to avoid them in your own code and make you a better programmer (hopefully). Each pattern comes with a small description, examples and possible solutions. You can check many of them for free against your project at QuantifiedCode.
Why did we write this?¶
Short answer: We think that you can learn as much from reading bad code as you can from reading good one.
Long answer: There is an overwhelming amount of Python books that show you how to do things by focusing on best practices and examples of good code. There are only very few books out there that show you how not to do things. We wanted to change that by providing you with an anti-book that teaches you things which you should never do in practice.
Who are we?¶
We’re QuantifiedCode, a Berlin-based startup. Our mission is to help programmers write better code! Our first product is an online tool for automated, data-driven code review. When building this tool we learned a lot about code quality in Python and decided to compile our knowledge into this book.
How is this book organized?¶
This book contains anti- and migrations pattern for Python and for popular Python frameworks, such as Django. We categorized the patterns as follows:
- Correctness: Anti-patterns that will literally break your code or make it do the wrong things.
- Maintainability: Anti-patterns that will make your code hard to maintain or extend.
- Readability: Anti-patterns that will make your code hard to read or understand.
- Performance: Anti-patterns that will unnecessarily slow your code down.
- Security: Anti-patterns that will pose a security risk to your program.
- Migration: Patterns that help you migrate faster to new versions of a framework
Some patterns can belong in more than one category, so please don’t take the choice that we’ve made too serious. If you think a pattern is grossly misplaced in its category, feel free to create an issue on Github.
References¶
Whenever we cite content from another source we tried including the link to the original article on the bottom of the page. If you should have missed one, please feel free to add it and make a pull request on Github. Thanks!
Licensing¶
This document is licensed under a creative-commons NC license, so you can use the text freely for non-commercial purposes and adapt it to your needs. The only thing we ask in return is the inclusion of a link to this page on the top of your website, so that your readers will be able to find the content in its original form and possibly even contribute to it.
Contributing¶
If you think this collection can be improved or extended, please contribute! You can do this by simply forking our Github project and sending us a pull request once you’re done adding your changes. We will review and merge all pull requests as fast as possible and be happy to include your name on the list of authors of this document.
We would also like to thank all contributors to this book for their effort. A full list of contributors can be found at Github.
List of Maintainers¶
If you have any questions concerning this project, please contact one of the maintainers:
Index Of Patterns¶
Here’s the full index of all anti-patterns in this book.
- Correctness
- Accessing a protected member from outside the class
- Assigning a lambda expression to a variable
- Assigning to built-in function
- Bad except clauses order
- Bad first argument given to
super()
else
clause on loop without abreak
statement__exit__
must accept 3 arguments: type, value, traceback- Explicit return in __init__
__future__
import is not the first non-docstring statement- Implementing Java-style getters and setters
- Indentation contains mixed spaces and tabs
- Indentation contains tabs
- Method could be a function
- Method has no argument
- Missing argument to
super()
- Using a mutable default value as an argument
- No exception type(s) specified
- Not using
defaultdict()
- Not using
else
where appropriate in a loop - Not using explicit unpacking
- Not using
get()
to return a default value from a dict - Not using
setdefault()
to initialize a dictionary
- Maintainability
- Readability
- Asking for permission instead of forgiveness
- Comparing things to None the wrong way
- Comparing things to True the wrong way
- Using type() to compare types
- Not using dict comprehensions
- Not using dict keys when formatting strings
- Not using
items()
to iterate over a dictionary - Not using named tuples when returning more than one value from a function
- Not using unpacking for updating multiple values at once
- Not using
zip()
to iterate over a pair of lists - Putting type information in a variable name
- Test for object identity should be
is
- Using an unpythonic loop
- Using
map()
orfilter()
where list comprehension is possible - Using CamelCase in function names
- Security
- Performance
- Django