Python代码规范笔记

Python代码规范笔记

1. 代码格式

- 缩进
	使用4个空格
- 行宽
	每行不超过80个字符(特殊情况不超过120)
	以下情况除外:
		长的导入模块语句
		注释里的URL(在注释中,如果必要,将长的URL放在一行上)
- 引号
	代码中多用单引号
	自然语言使用双引号
	正则表达式双引号
	文旦注释三引号
- 空行
	模块级函数和类定义之间空两行
	类成员函数之间空一行
	使用多个空行分隔多组相关的函数
	函数中可以使用空行分隔逻辑相关代码

	*定义之间空两行, 方法定义之间空一行
	*定义之间空两行, 比如函数或者类定义. 方法定义, 类定义与第一个方法之间, 都应该空一行. 函数或方法中, 某些地方要是你觉得合适, 就空一行
class A:

    def __init__(self):
        pass

    def hello(self):
        pass


def main():
    pass   

2. import语句

- 放在文件头部
# 分行书写
import os
import sys

from subprocess import Popen, PIPE

# 使用absolute import
from foo.bar import Bar

# 按照顺序排列,每组之间用空行分隔
import os
import sys

import msgpack
import zmq

import foo

# 导入其他模块的类定义可以使用相对导入
from myclass import MyClass

# 命名冲突时使用命名空间
import bar
import foo.bar

bar.Bar()
foo.bar.Bar()

3. 空格

  • 代码各处不要有多余空格
# 二元运算符两边各空一格(=,-,+=,==,>,in,is not, and)
i = i + 1
submitted += 1
x = x * 2 - 1
hypot2 = x * x + y * y
c = (a + b) * (a - b)

# 函数的参数列表中“,”之后要有空格
def complex(real, imag):
    pass

# 函数的参数列表中,默认值等号两边不要添加空格
def complex(real, imag=0.0):
    pass

4. 换行

# 括号内的换行
# 第二行缩进到括号的起始处
foo = long_function_name(var_one, var_two,
                         var_three, var_four)

# 第二行缩进 4 个空格,适用于起始括号就换行的情形
def long_function_name(
        var_one, var_two, var_three,
        var_four):
    print(var_one)

# 使用反斜杠\换行,二元运算符+` `.等应出现在行末;长字符串也可以用此法换行
session.query(MyTable).\
        filter_by(id=1).\
        one()

print 'Hello, '\
      '%s %s!' %\
      ('Harry', 'Potter')

5. docstring

  1. 所有的公共模块、函数、类、方法,都应该写 docstring 。私有方法不一定需要,但应该在 def 后提供一个块注释来说明。
  2. docstring 的结束"""应该独占一行,除非此 docstring 只有一行。
"""Return a foobar
Optional plotz says to frobnicate the bizbaz first.
"""

"""Oneline docstring"""

6. 注释

  1. 块注释
    “#”号后空一格,段落件用空行分开(同样需要“#”号)
# 块注释
# 块注释
#
# 块注释
# 块注释
  1. 行注释
    至少使用两个空格和语句分开,注意不要使用无意义的注释
x = x + 1  # 边框加粗一个像素
  1. 建议
    在代码的关键部分(或比较复杂的地方), 能写注释的要尽量写注释
    比较重要的注释段, 使用多个等号隔开, 可以更加醒目, 突出重要性
app = create_app(name, options)


# =====================================
# 请勿在此处添加 get post等app路由行为 !!!
# =====================================


if __name__ == '__main__':
    app.run()
  1. 文档注释(Docstring)
    一般出现在模块头部、函数和类的头部,可以通过对象的__doc__对象获取文档,编辑器和IDE也可以根据Docstring给出自动提示
    文档注释以 “”" 开头和结尾, 首行不换行, 如有多行, 末行必需换行, 以下是Google的docstring风格示例
# -*- coding: utf-8 -*-
"""Example docstrings.

This module demonstrates documentation as specified by the `Google Python
Style Guide`_. Docstrings may extend over multiple lines. Sections are created
with a section header and a colon followed by a block of indented text.

Example:
    Examples can be given using either the ``Example`` or ``Examples``
    sections. Sections support any reStructuredText formatting, including
    literal blocks::

        $ python example_google.py

Section breaks are created by resuming unindented text. Section breaks
are also implicitly created anytime a new section starts.
"""

具体描述其具体内容, 解释具体参数和返回值等

def function(a, b):
    """计算并返回a到b范围内数据的平均值"""
    ... ...

对函数参数、返回值等的说明采用numpy标准

def func(arg1, arg2):
    """在这里写函数的一句话总结(如: 计算平均值).

    这里是具体描述.

    参数
    ----------
    arg1 : int
        arg1的具体描述
    arg2 : int
        arg2的具体描述

    返回值
    -------
    int
        返回值的具体描述

    参看
    --------
    otherfunc : 其它关联函数等...

    示例
    --------
    示例使用doctest格式, 在`>>>`后的代码可以被文档测试工具作为测试用例自动运行

    >>> a=[1,2,3]
    >>> print [x + 3 for x in a]
    [4, 5, 6]
    """

文档注释不限于中英文, 但不要中英文混用
文档注释不是越长越好, 通常一两句话能把情况说清楚即可
模块、公有类、公有方法, 能写文档注释的, 应该尽量写文档注释

  • 文档注释
    首先是一行以句号, 问号或惊叹号结尾的概述(或者该文档字符串单纯只有一行). 接着是一个空行. 接着是文档字符串剩下的部分, 它应该与文档字符串的第一行的第一个引号对齐

  • 模块
    每个文件应该包含一个许可样板. 根据项目使用的许可

  • 函数和方法
    一个函数必须要有文档字符串, 除非它满足以下条件:
    1. 外部不可见
    2. 非常短小
    3. 简单明了
    文档字符串应该包含函数做什么, 以及输入和输出的详细描述. 通常, 不应该描述"怎么做", 除非是一些复杂的算法. 文档字符串应该提供足够的信息, 当别人编写代码调用该函数时, 他不需要看一行代码, 只要看文档字符串就可以了. 对于复杂的代码, 在代码旁边加注释会比使用文档字符串更有意义.

    关于函数的几个方面应该在特定的小节中进行描述记录, 这几个方面如下文所述. 每节应该以一个标题行开始. 标题行以冒号结尾. 除标题行外, 节的其他内容应被缩进2个空格.

    Args:
    列出每个参数的名字, 并在名字后使用一个冒号和一个空格, 分隔对该参数的描述.如果描述太长超过了单行80字符,使用2或者4个空格的悬挂缩进(与文件其他部分保持一致). 描述应该包括所需的类型和含义. 如果一个函数接受foo(可变长度参数列表)或者**bar (任意关键字参数), 应该详细列出foo和**bar.
    Returns: (或者 Yields: 用于生成器)
    描述返回值的类型和语义. 如果函数返回None, 这一部分可以省略.
    Raises:
    列出与接口有关的所有异常.

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.

    Args:
        big_table: An open Bigtable Table instance.
        keys: A sequence of strings representing the key of each table row
            to fetch.
        other_silly_variable: Another optional variable, that has a much
            longer name than the other args, and which does nothing.

    Returns:
        A dict mapping keys to the corresponding table row data
        fetched. Each row is represented as a tuple of strings. For
        example:

        {'Serak': ('Rigel VII', 'Preparer'),
         'Zim': ('Irk', 'Invader'),
         'Lrrr': ('Omicron Persei 8', 'Emperor')}

        If a key from the keys argument is missing from the dictionary,
        then that row was not found in the table.

    Raises:
        IOError: An error occurred accessing the bigtable.Table object.
    """
    pass

  • 类应该在其定义下有一个用于描述该类的文档字符串. 如果你的类有公共属性(Attributes), 那么文档中应该有一个属性(Attributes)段. 并且应该遵守和函数参数相同的格式.
class SampleClass(object):
    """Summary of class here.

    Longer class information....
    Longer class information....

    Attributes:
        likes_spam: A boolean indicating if we like SPAM or not.
        eggs: An integer count of the eggs we have laid.
    """

    def __init__(self, likes_spam=False):
        """Inits SampleClass with blah."""
        self.likes_spam = likes_spam
        self.eggs = 0

    def public_method(self):
        """Performs operation blah."""

如果一个类不继承自其它类, 就显式的从object继承. 嵌套类也一样.

class SampleClass(object):
    pass


class OuterClass(object):

    class InnerClass(object):
        pass


class ChildClass(ParentClass):
    """Explicitly inherits from another class already."""

继承自 object 是为了使属性(properties)正常工作, 并且这样可以保护你的代码, 使其不受Python 3的一个特殊的潜在不兼容性影响. 这样做也定义了一些特殊的方法, 这些方法实现了对象的默认语义, 包括 new, init, delattr, getattribute, setattr, hash, repr, and str .

  • TODO注释
    为临时代码使用TODO注释, 它是一种短期解决方案. 不算完美, 但够好了.
    TODO注释应该在所有开头处包含"TODO"字符串, 紧跟着是用括号括起来的你的名字, email地址或其它标识符. 然后是一个可选的冒号. 接着必须有一行注释, 解释要做什么. 主要目的是为了有一个统一的TODO格式, 这样添加注释的人就可以搜索到(并可以按需提供更多细节). 写了TODO注释并不保证写的人会亲自解决问题. 当你写了一个TODO, 请注上你的名字.
# TODO(kl@gmail.com): Use a "*" here for string repetition.
# TODO(Zeke) Change this to use relations.

如果你的TODO是"将来做某事"的形式, 那么请确保你包含了一个指定的日期(“2009年11月解决”)或者一个特定的事件(“等到所有的客户都可以处理XML请求就移除这些代码”).

7. 命名规范

  1. 模块
    模块尽量使用小写命名,首字母保持小写,尽量不要用下划线(除非多个单词,且数量不多的情况)
import decoder
import html_parser
  1. 类名
    类名使用驼峰(CamelCase)命名风格,首字母大写,私有类可用一个下划线开头
class Farm():
    pass

class AnimalFarm(Farm):
    pass

class _PrivateFarm(Farm):
    pass

将相关的类和*函数放在同一个模块里

  1. 函数
    函数名一律小写,如有多个单词,用下划线隔开
def run():
    pass

def run_with_env():
    pass

私有函数在函数前加一个下划线_

class Person():

    def _private_func():
        pass
  1. 变量名
    变量名尽量小写, 如有多个单词,用下划线隔开
if __name__ == '__main__':
    count = 0
    school_name = ''
  1. 常量
    常量采用全大写,如有多个单词,使用下划线隔开
MAX_CLIENT = 100
MAX_CONNECTION = 1000
CONNECTION_TIMEOUT = 600
上一篇:C标准函数库中获取时间与日期、对时间与日期数据操作及格式化


下一篇:每日一题(2020年C/C++ B组第二场省赛第六题编程题)