Python Style
If you don’t know what it is, I recommend you should just play with it and don’t care about the style.
But I’d like to say Anaconda is a better choice than just Python itself. You can manage different packages in different environments with Anaconda.
This article is about what I find interesting in PEP 8 – Style Guide for Python Code1, PEP 257 – Docstring Conventions, Style guide — numpydoc v1.6.0rc1.dev0 Manual and SPT3G. This is not a guide, I recommend Google Style Guides2 as the guide.
§1 General
Readability counts. — PEP 20
- Always break your code apart by defining functions, classes, or create a new .py file and
from myproject.backend.hgwells import time_machine
. Don’t write code like a long staircase of indentation, that would drive people crazy.
- Comments are of equal importance as code. It’s for your own good, because you can’t remember everything.
§2 This and That
If your project has a style guide already, always follow that rather than this one.
§2.1 Naming
Naming is a big deal, the biggest probably. And I generally follow these rules from SPT3G.
- Function, Variable:
lower_with_under
- Class:
CapWords
- Constant:
CAPS_WITH_UNDER
, and usescipy.constants
. - Non-public class methods and instance variables should begin with a single underscore (this is baked into the way python implements classes).
See this table for the full naming convention.
§2.2 Four Spaces for Indentation
Also according to SPT3G:
CONSTANT_VALUE = 10
def function_name(variable_name, other):
do_some_things
class MyClass:
CONSTANCE_INSTANCE_VARIABLE = 100
def __init__(self, input, other_input):
self.instance_variable = input + other_input
def class_method(self, input):
do_things
§2.3 Comments and Doc Strings
You should assume the person who is reading the comments are more familiar with python than you, they just don’t understand what your code is doing:
# wrong:
x = x + 1 # Increment x
# correct:
x = x + 1 # Compensate for border
Also according to SPT3G, for classes, modules and functions, write doc strings:
def get_fft_scale_fac(res=None, n1=None, n2=None,
apod_mask=None, parent=None):
"""
Returns a scale factor to convert a 2d fft of a map into
sqrt(C_l) normalized units by scaling it by the sky area.
In particular it returns:
np.mean(apod_mask**2)**0.5 * (n1 * n2)**0.5 / reso_rad
For forward transforms: fft2(mp) / scale_fac
For inverse transforms: ifft2(mp) * scale_fac
Arguments
---------
res : float, default=None
Resolution of the map in G3Units.
Must be specified if parent is None.
n1 : int, default=None
Number of map pixels in x direction.
Must be specified if parent is None.
n2 : int, default=None
Number of map pixels in y direction.
Must be specified if parent is None.
apod_mask : FlatSkyMap or ndarray, default=None
An apodization mask.
parent : FlatSkyMap, default=None
Parent Map object containing resolution and shape info.
Must be specified if res, n1, and n2 are None.
Returns
-------
float
FFT normalization factor
See Also
-------
ft_to_map
"""
By the way, '
and "
are the same thing in code.
§2.4 Maximum Line Length is 80 Characters
If you need to wrap multiple lines, you should wrap them on the same level of syntax structure:
bridgekeeper.answer(
name="Arthur", quest=questlib.find(owner="Arthur", perilous=True))
answer = (a_long_line().of_chained_methods()
.that_eventually_provides().an_answer())
if (
config is None
or 'editor.language' not in config
or config['editor.language'].use_spaces is False
):
use_tabs()
And follow the tradition from mathematics:
income = (gross_wages
+ taxable_interest
+ (dividends - qualified_dividends)
- ira_deduction
- student_loan_interest)
§2.5 Import Order
- Python future import statements.
- Python standard library imports.
- Third-party module or package imports.
- Code repository sub-package. Absolute imports are recommended.
For example:
from __future__ import annotations
import os
import sys
import numpy as np
import tensorflow as tf
from scipy import constants
from myproject.backend.hgwells import time_machine
中文版见 Google 开源项目风格指南. ↩︎