This is a collection of best practices and anti-patterns for Python and popular Python frameworks, such as Django, Flask or Odoo. Explore the different sections of this knowledge base, to increase the correctness, security, performance, maintainability, and readability of your Python code. Sign up for free to automatically monitor whether your own projects comply with all these best practices.
You can also explore the code quality of over 5.000 open source projects for free and contribute to this collection by creating or suggesting your own articles.
Python
Correctness
Assigning to built-in exception
Avoid accessing protected class members from outside
Avoid calling magic methods
Avoid calling uncallable object
Avoid concatenating different built-in types
Avoid deprecated string functions
Avoid empty exception handlers
Avoid infinite loops
Avoid misleading chained comparisons
Avoid multiple function return types
Avoid mutable default arguments
Avoid overwriting built-in functions/attributes
Avoid re-definition of unused name
Avoid repetitive element assignment
Avoid unreachable except clauses
Avoid untyped exception handlers
Avoid unused arguments
Avoid using
+=
for concatenation of non-local listsAvoid whitespaces in your replacement field names
break
/continue
outside loopCall
__init__
method from base classCheck assignment to
True
orFalse
Check
__init__
method call, from a non-direct base classCheck overload of built-in function
Check undefined name in
__all__
Class has no member
Consider using
defaultdict()
to set default valuesDo not redefine name from outer scope
Don't hide methods via attributes
Don't overload modules with loop variables
Don't redefine names through list comprehensions
Don't use
__init__
methods as generatorDon't use undefined loop variable
Don't use undefined name
Duplicate argument name in function definition
Duplicate key in dictionary
else
clause on a loop without abreak
statementEnsure child class signature matches parent class implementation
__exit__
function has the wrong signatureFirst argument of a classmethod should be called
cls
__future__
import is not the first real statement in a moduleImport naming collision
Inherit from
BaseException
for all custom exceptionsLocal variable assigned but never used
Match function call with function signature
Match number of replacement fields to
format()
argumentsMethod is abstract in class but is not overridden
NotImplemented
raised, instead ofNotImplementedError
Number replacement fields consistently
object.__members__
deprecatedOnly raise valid exception types
open
called with invalid mode stringParameter passed as both positional and keyword argument
Pass correct number of positional arguments to function call
Passing unexpected keyword argument in function call
Provide argument or
@staticmethod
to methodRemove unreachable code
Returning a value from
__init__
Return iterator in
__iter__
to avoid runtime errorsreturn
statement outside of a functionUse child class name as first argument to
super
callUse correct import name from module
Use
else
-clause in for-loopUse new-style Python classes
Use relative imports
yield
statement outside of a function or method
Maintainability
Ask for permission instead of forgiveness
Avoid consecutive if-statements
Avoid deprecated
<>
operatorAvoid manually cloning a list
Avoid "non-Pythonic" method names
Avoid temporary
kwargs
Avoid using intermediate variables whenever possible
Avoid using Java style dicts
Avoid using
len(x)
to check if x is emptyAvoid using "non-Pythonic" function names
Avoid using "non-Pythonic" variable names
Avoid using range() of len() to get index of iterable
Avoid using the
global
statementAvoid using
.update()
to create merged dictionariesAvoid using wildcard (*) imports
Consider documenting your class(es)
Consider documenting your function(s)
Consider simplifying bounds checks
Consider simplifying out-of-bounds checks
Consider splitting your assert statements
Consider using 'mpl' as alias for matplotlib imports
Consider using 'np' as alias for numpy imports
Consider using 'pd' as alias for pandas imports
Consider using 'plt' as alias for matplotlib.pyplot imports
Consider using 'sns' as alias for seaborn imports
Consider using 'sp' as alias for scipy imports
dict.has_key()
deprecatedDouble-check published secret key
Module name not matching naming conventions
object.__methods__
deprecatedPrefer explicitly numbering replacement fields in a format string
Prefer
format()
over%
for string interpolationTry to start test methods with "test_"
Use constants as default values for arguments
Use dump instead of dumps for json files
Use
isinstance()
to check for typeUse load instead of loads for json files
Use
@property
instead of Java-style of setter/getter methodsUse tuple as 2nd argument of
isinstance()
to avoid repetitionUse
.update()
instead of setting keys individuallyUsing the
global
statement is unnecessary at module level.xreadlines()
deprecated
Performance
Avoid nested loop joins
Avoid using C-style increment or decrement operators
Consider an iterator instead of materializing the inner list
Consider an iterator instead of materializing the list
Consider literals instead of
dict()
constructor to initialize dictionariesConsider using a dict comprehension instead
dict(...)
Consider using a set comprehensions instead of passing a list to
set()
Prefer static methods over instance methods when possible
Prefer
with
to open filesRefactor expensive
if-elif
statementRemove unused module(s)
Remove unused variable
Use a set instead of a list() to find key
Use
extend()
for list concatenation
Readability
Avoid assigning a
lambda
expression to a variableAvoid inline comments
Avoid
None
as a redundant second argument todict.get()
Avoid "non-Pythonic" attribute names
Avoid "non-Pythonic" class names
Avoid unnecessary name repetition in equality comparisions
Avoid unnecessary parentheses after keyword
Avoid unnecessary
pass
statementsClean up unused imports
Consider using 'dt' as alias for datetime imports
not ... is
used instead ofis not
Omit
len()
as upper boundaryOmit
len()
for indexing/slicingPrefer
.format()
over string concatenations via+
Simplify repetetive unequal checks
Test object identity with
is
oris not
Use common abbreviations for libraries
Use dict comprehension
Use
isinstance()
instead of comparing typesUse
is
oris not
to compare withNone
Use
.items()
to iterate over a dictionaryUse named tuples when returning more than one value from a function
Use new raise syntax
Use unpacking to update multiple values at once
Use
zip()
to iterate over a pair of lists
Security
Avoid using
eval()
Avoid using
exec()
Check published
CONSUMER_SECRET
Check published OAuth secret
Check published
OAuth
tokenCheck published Stripe API key
Check usage of exploitable MD5 hashes
Upgrade from
md5
tohashlib
Frameworks
Django
Access model manager through model class not instance
Always define
__str__
or__unicode__
for each modelAvoid directly altering custom many-to-many relationships
Avoid importing from
django.db.models.fields
Avoid
null=True
on string fieldsAvoid overwriting init method of model classes
Avoid two consecutive underscores in field name
Avoid using len() with RawQuerySet
Avoid using
locals()
to populate view contextAvoid using RawQuerySet as boolean value
Call
super()
when overwriting unittest methodsCheck identical value for
SERVER_EMAIL
andDEFAULT_FROM_EMAIL
Define
get_absolute_url
whenever possibleDirectly accessing
INSTALLED_APPS
Do not interact with database within ready()
Do not override field attributes in child model
Don't pass args and kwargs to
reverse()
Don't use joins with
update()
Don't use same path for
MEDIA_ROOT
andSTATIC_ROOT
Don't use same path for
MEDIA_URL
andSTATIC_URL
Don't use string formatting on raw queries
Don't use unsupported arguments on
FileField
Double-check published secret key
Duplicate application names
Ensure indexes on your Django models
Inherit proxy models from non-proxy parent
Invalid import from
django.conf.settings
Leverage queryset cache as much as possible
Missing required field in settings
Model attribute overwrites method definition
Place database manipulations in try-except blocks
Remove redundant import of global_settings
SECURE_PROXY_SSL_HEADER
setSet
ALLOWED_HOSTS
whenDEBUG=False
Try to start test methods with "test_"
Use a
NullBooleanField
Use
django.conf.urls.url()
instances for urlpatternsUse django.test.TestCase when accessing the database
Use forward slashes in settings
Use getobjector_404() instead of catching ObjectDoesNotExist
Use model class as first argument for field type
Use reverse() instead of hard-coded URL
Use
settings()
method instead of manipulating settings directlyUsing
BinaryField
to store raw binary data
Flask
Avoid two consecutive underscores in column name
Consider using
url_prefix
for views with similar routesDefine
SERVER_NAME
when using sub domainsDefine
url_prefix
orsubdomain
during blueprint registrationPrevent SQL injections by avoiding string interpolations
route
should be the outermost decoratorUse converter for type checking url variables
Use relative imports
Plone
Catching ImportError to detect package availability
Comma-separated imports
Prefer explicitly numbering replacement fields in a format string
Refactor deprecated unittest aliases
Using
request.AUTHENTICATED_USER
Odoo
Avoid calling magic methods
Avoid
None
as a redundant second argument todict.get()
Avoid temporary
kwargs
Avoid using intermediate variables whenever possible
Avoid using Java style dicts
Avoid using
len(x)
to check if x is emptyAvoid using
.update()
to create merged dictionariesdict.has_key()
deprecatedOdoo model defaults require four parameters
Use constants and avoid magic numbers
Use
isinstance()
to check for typeUse tuple as 2nd argument of
isinstance()
to avoid repetitionUse
.update()
instead of setting keys individually