background
I've changed jobs and am about to use python in earnest at work, so I'd like to summarize the pythonic coding style I examined earlier as a review.
UPDATE:
Part 2 has been updated.
Contents of this page
Adhering to PEP 8 is the first basic.
There are already a lot of existing articles, including the existing Japanese translation, so I would like you to give priority to that.
Original
Japanese translation
Other Qiita articles:
Compliant with Python coding standard PEP8
Summary of Python coding standard PEP8 (1)
Purpose of creation
- Learn by translating + summarizing
- Qiita page creation practice
- I want as many people as possible to know about PEP 8
(Somehow, I feel that this kind of thing is proclaimed by someone digging out on a regular basis.)
The second time I will summarize the contents that are not in PEP 8.
If you have any supplements or suggestions (I'm not Japanese, so please point out in Japanese), please give me Masakari.
Then to the main subject ~
Premise
- Readability is important: Code is often read rather than written
- Style is changing
- Consistency is important: try to unify styles in the same function or module as much as possible
- Prefer local style if it conflicts with project local coding style
- If there is a conflict with the past style of the project, priority is given to the existing style
Code layout
Indent
- 4 spaces
- Soft tab
- Long line break method 1-Align the start of similar chords
test = long_function(var1, var2,
var3, var4)
- Long line break method 2-distinguish code with additional indentation
def long_function(
var1, var2,var3,
var4):
print(val_one)
- Long code line break method 3-Hanging indent
test = long_function(
var1, var2, var3,
va4)
- Add a comment or additional indentation when breaking a long if statement. ʻIf (`is exactly one indent, so the code can be hard to read
if (hoge1_is_true and
hoge2_is_true):
#comment
do_something()
#OR
if (hoge1_is_true
and hoge2_is_true):
do something
- Line breaks () [] The closing parenthesis of the structure may or may not be indented
my_list = [
1, 2, 3,
4, 5, 6
]
#OR
my_list = [
1, 2, 3,
4, 5, 6
]
Line length
- The code should be MAX 79 characters
- Maximum 72 characters for string data and comments with less format restrictions
- It is recommended to put the code in parentheses at the time of line break
- "" May be used for things that already have parentheses such as with, assert
Use parentheses:
if (hoge1 and hoge2
hoge3 and hoge4):
do_something
""use:
with open(filepath1, "r") as file1, \
open(filepath2, "r") as file2:
do_something
Line break location
Line breaks before operators for readability
revenue = gacha1_price * payers1
+ gacha2_price * payers2
+ gacha3_price * payers3
Blank line
- 2 blank lines between top-level classes and global functions
- 1 blank line between methods
- Add blank lines to different types of methods and code
- It's okay if there is no blank line between similar one liners
Source file Encoding
- Basically use UTF-8
- Exception:
- Special test case
- When you absolutely need to write a name that contains characters that are not included in UTF-8
import
- Directly ʻimport` should be done on a separate line
import pandas
import numpy
- In case of
from ... import
, there may be more than one
from sklearn.linear_model import LinearRegression, LogisticRegression
- The import location must be after the module description and before the global variable definition.
- Import is divided into the following groups, and a blank line is inserted between the groups.
- standard library
- 3rd party library
- local library
- Use absolute import. Avoid relative imports
- Do not use
from <module> import *
! If you do it without a namespace, you won't know what's being imported
Module level dunder statement location
- After module description
- Before the import statement
- After
__future__
import
"""This is the example module.
This module does stuff.
"""
from __future__ import barry_as_FLUFL
__all__ = ['a', 'b', 'c']
__version__ = '0.1'
__author__ = 'Cardinal Biggles'
import os
import sys
other
- Avoid compound statements
#Yes
if foo == 'blah':
do_blah_thing()
do_one()
do_two()
do_three()
#No:
if foo == 'blah': do_blah_thing()
do_one(); do_two(); do_three()
Quotation
- Python doesn't distinguish between
"
and'
, so it's okay if you unify it in your code
- However, use
" ""
for three-quotation comments.
"""This is how you write
documentatoin string.
"""
Space in code
Avoid the following spaces
#Yes
buger(bread[2], {cheese: 1})
#No
buger( bread[ 2 ], { cheese: 1 } )
- Between the comma and the closing brace
#Yes
a_tuple = (0,)
#No
a_tuple = (0, )
- Comma, semicolon, just before colon
#Yes
if a: print x, y; x, y = y, x
#No
if a : print x , y ; x , y = y , x
- When sliced, the colon is treated as an operator, so basically put the same amount of space on both sides (except when omitted).
#Yes
ham[1:9], ham[1:9:3], ham[:9:3], ham[1::3], ham[1:9:]
#No
ham[1: 9], ham[1 :9], ham[1:9 :3]
- When slicing, put spaces on both sides of the colon for formulas and function calls.
#Yes
ham[lower+offset : upper+offset], ham[: upper_fn(x) : step_fn(x)]
#No
ham[lower + offset:upper + offset]
- Immediately before the variable list of the function call
#Yes
func_call(params)
#No
func_call (params)
- Immediately before index of list or dictionary
#Yes
dct['key'] = lst[index]
#No
dct ['key'] = lst [index]
- When substituting, let's make one space next to
=
#Yes
x = 1
y = 2
long_variable = 3
#No
x = 1
y = 2
long_variable = 3
- Extra space at the end of the line
- Assignment to keyword variable when calling a function
#Yes
def complex(real, imag=0.0):
return magic(r=real, i=imag)
#No
def complex(real, imag = 0.0):
return magic(r = real, i = imag)
Let's put the following space
- Usually one space on each side of the operator below
- Substitution system
=, + =,-=
, etc
- Comparison system
==, <,>,! =, <>, <=,> =, in, not in, is, is not
- boolean ʻand, or, not`
- When operators with different priorities are used, on both sides of the operator with the lower priority
- Avoid more than one space
- Make the number of spaces on both sides the same
#Yes
i = i + 1
submitted += 1
x = x*2 - 1
hypot2 = x*x + y*y
c = (a+b) * (a-b)
#No
i=i+1
submitted +=1
x = x * 2 - 1
hypot2 = x * x + y * y
c = (a + b) * (a - b)
- At the time of function annotation
- One after the colon
- Both sides of
->
#Yes
def munge(input: AnyStr): ...
def munge() -> AnyStr: ...
#No
def munge(input:AnyStr): ...
def munge()->PosInt: ...
- Put both variable annotation and normal assignment in
=
when they occur at the same time.
#Yes
def munge(sep: AnyStr = None): ...
def munge(input: AnyStr, sep: AnyStr = None, limit=1000): ...
#No
def munge(input: AnyStr=None): ...
def munge(input: AnyStr, limit = 1000): ...
Trailing comma
- May be attached
- Basically enclose in parentheses
#Yes
FILES = ('setup.cfg',)
#No
FILES = 'setup.cfg',
#Yes
FILES = [
'setup.cfg',
'tox.ini',
]
initialize(FILES,
error=True,
)
#No
FILES = ['setup.cfg', 'tox.ini',]
initialize(FILES, error=True,)
comment
General
- It is better not to make comments that are inconsistent with the code, and make sure that the comments are always up to date.
- Make comments as proper as possible
- If it is a short comment, you can omit the punctuation mark, but basically let's add it properly
- Insert two spaces after the Kuten in the document
- Write comments in English as much as possible. Someday it may be read by someone who doesn't know the language of the code writer.
Block comment
- Basically what you write for some code
- Take the same indentation as the target code
- Basically start each line with
#
- Separate paragraphs in the document with only
#
lines
Inline comment
- Do not use too much
- Leave at least 2 spaces before in-line comments
- In-line comments start with
#
- Inline comments that are too obvious are meaningless, so avoid them
Documentation description
- See PEP257 for how to write
- It is used to explain modules, classes and methods, so put it under the
def
line.
- If there are multiple lines, the ending
" ""
occupies one line, but in the case of one liner, place them on the same line.
About naming
Basic
- This is definitely not perfect because it's been a mess so far, but for the time being, let's follow this rule as much as possible when writing new things in the future
- User-visible public API naming should basically reflect functionality, not implementation
- Recognizing which naming style is used is just as important as recognizing where it is used. Basically, the following patterns exist
b #Single lowercase
B #Single uppercase
lowercase #All lowercase
lower_case_with_underscores # _Lowercase letters with
UPPERCASE #All capital letters
UPPER_CASE_WITH_UNDERSCORES # _Uppercase with
CapitalizedWords #Uppercase initials
CapitalizeAbbreviationLikeHTTP #For capital initials, all proper abbreviations should be capitalized
mixedCase #composite
Capitalized_Words_With_Underscores #Ugly capital initials+ _
_single_leading_underscore #When using only inside, like private
single_trailing_underscore_ #To avoid conflicts with Python keywords
__double_leading_underscore #Qualifications when naming class variables
__double_leading_and_trailing_underscore__ #Never define it yourself
Use of naming style
joined_lower
is used for ** module names, functions, methods, instance variables, global variables **
JOINED_UPPER
is used for ** constants **
CapWords
is used for ** classes and type variables **
- The exception is a class, so the same ** CapWords rule **, but always put ʻError` at the end
- Never use'l'(lower L),'O' (Oh),'I' (Upper i) alone. Hard to distinguish
Other naming rules
- The first variable of the instance method is self, the first variable of the class method is cls. If a variable and keyword collide, put a'_' at the end to correspond
- There is no'_' at the beginning of public methods
- For simple public data, it is better to publish the parameters directly than to prepare an accessor.
- Variables in the class that will be inherited can avoid name conflicts by putting a double underscore at the beginning of the variable name.
- Backward compatibility basically applies only to the public interface.
- To make it easier to distinguish between public and private interfaces, define the public interface as a list in
__all__
when defining the module.