Python开发规范

Python风格规范 本项目包含了部分Google风格规范和PEP8规范,仅用作内部培训学习


命名规范

Python之父推荐的规范

Type Public Internal
Modules lower_with_under _lower_with_under
Packages lower_with_under
Classes CapWords _CapWords
Exceptions CapWords
Functions lower_with_under() _lower_with_under()
Global/Class Constants CAPS_WITH_UNDER _CAPS_WITH_UNDER
Global/Class Variables lower_with_under lower_with_under
Instance Variables lower_with_under _lower_with_under (protected) or __lower_with_under (private)
Method Names lower_with_under() _lower_with_under() (protected) or __lower_with_under() (private)
Function/Method Parameters lower_with_under
Local Variables lower_with_under

应该避免的名称

1.单字符名称
2.包/模块名中使用连字符(-)而不使用下划线(_)
3.双下划线开头并结尾的名称(如__init__)

命名约定

1.所谓”内部(Internal)”表示仅模块内可用, 或者, 在类内是保护或私有的.
2.用单下划线(_)开头表示模块变量或函数是protected的(使用import * from时不会包含).
3.用双下划线(__)开头的实例变量或方法表示类内私有.
4.将相关的类和顶级函数放在同一个模块里. 不像Java, 没必要限制一个类一个模块.
5.对类名使用大写字母开头的单词(如CapWords, 即Pascal风格), 但是模块名应该用小写加下划线的方式(如lower_with_under.py).

注释规范

文档字符串

Python使用文档字符串作为注释方式: 文档字符串是包, 模块, 类或函数里的第一个语句. 这些字符串可以通过对象的doc成员被自动提取, 并且被pydoc所用. 我们对文档字符串的惯例是使用三重双引号”“”( PEP-257 ).

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

"""A user-created :class:`Response <Response>` object.
    
Used to xxx a :class: `JsonResponse <JsonResponse>`, which is xxx

:param data: response data
:param file: response files
    
Usage::

    >>> import api
    >>> rep = api.Response(url="http://www.baidu.com")
"""

行内注释(PEP8)

行内注释是与代码语句同行的注释
1. 行内注释和代码至少要有两个空格分隔
2. 注释由#和一个空格开始

x = x + 1                 # Compensate for border

模块

每个文件应该包含一个许可样板. 根据项目使用的许可(例如, Apache 2.0, BSD, LGPL, GPL), 选择合适的样板.

# -*- coding: utf-8 -*-
# (C) JiaaoCap, Inc. 2017-2018
# All rights reserved
# Licensed under Simplified BSD License (see LICENSE)

函数和方法

一个函数必须要有文档字符串, 除非它满足以下条件:
1. 外部不可见
2. 非常短小
3. 简单明了

文档字符串应该包含函数做什么, 以及输入和输出的详细描述
文档字符串应该提供足够的信息, 当别人编写代码调用该函数时, 他不需要看一行代码, 只要看文档字符串就可以了
对于复杂的代码, 在代码旁边加注释会比使用文档字符串更有意义.

def simple_func(method, timeout)
    """Constructs and sends a :class:`Request <Request>`.
    
    :param method: method for the new :class:`Request` object.
    :param timeout: (optional) How many seconds to wait for the server to send data
        before giving up, as a float, or a :ref:`(connect timeout, read
        timeout) <timeouts>` tuple.
    :type timeout: float or tuple
    :return: :class:`Response <Response>` object
    :rtype: requests.Response
    
    Usage::
    
      >>> import requests
      >>> req = requests.request('GET', 'http://httpbin.org/get')
      <Response [200]>
    """

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

class HTTPAdapter(BaseAdapter):
    """The built-in HTTP Adapter for urllib3.

    Provides a general-case interface for Requests sessions to contact HTTP and
    HTTPS urls by implementing the Transport Adapter interface.

    :param pool_connections: The number of urllib3 connection pools to cache.
    :param max_retries: The maximum number of retries each connection
        should attempt.

    Usage::

      >>> import requests
      >>> s = requests.Session()
      >>> a = requests.adapters.HTTPAdapter(max_retries=3)
      >>> s.mount('http://', a)
    """
   
    def __init__(self, pool_connections, max_retries):
        self.pool_connections = pool_connections
        self.max_retries = max_retries

块注释和行注释

对于复杂的操作, 应该在其操作开始前写上若干行注释. 对于不是一目了然的代码, 应在其行尾添加注释.

# We use a weighted dictionary search to find out where i is in
# the array.  We extrapolate position based on the largest num
# in the array and the array size and then do binary search to
# get the exact number.

if i & (i-1) == 0:        # true iff i is a power of 2

行长度

  1. 每行不超过80个字符
  2. 不要使用反斜杠连接行
  3. Python会将 圆括号, 中括号和花括号中的行隐式的连接起来 , 你可以利用这个特点. 如果需要, 你可以在表达式外围增加一对额外的圆括号.
NO:
query_sql = "SELECT image_id, image_o, image_width, image_height "\
            "FROM active_image_tbl "\
            "WHERE auction_id=:auction_id AND status=1 " \
            "ORDER BY image_id DESC"
   
YES:         
agent_sql = ("CREATE TABLE IF NOT EXISTS db_agent ("
             "id INTEGER PRIMARY KEY AUTOINCREMENT, "
             "device_id VARCHAR(128) DEFAULT '', "
             "status INTEGER DEFAULT 1, "
             "updated_time TIMESTAMP  DEFAULT CURRENT_TIMESTAMP, "
             "created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP)")

在注释中,如果必要,将长的URL放在一行上。
Yes: 
# See details at
# http://www.example.com/us/developer/documentation/api/content/v2.0/fication.html

换行

  1. 使用4个空格来缩进代码
  2. 对于行连接的情况, 你应该要么垂直对齐换行的元素, 或者使用4空格的悬挂式缩进(这时第一行不应该有参数):
# 垂直对齐换行的元素
foo = long_function_name(var_one, var_two,
                         var_three, var_four)


# 4空格的悬挂式缩进(这时第一行不应该有参数)
foo = long_function_name(
    var_one, var_two, var_three,
    var_four)

空格

  1. 括号内不要有空格
YES:
spam(ham[1], {eggs: 2}, [])                 # 注意标点两边的空格

NO:
spam( ham[ 1 ], { eggs: 2 }, [ ] )
  1. 不要在逗号,分号,冒号前面加空格,而应该在它们的后面加
YES:
if x == 4:
    print x, y
x, y = y, x 

NO:
if x == 4 :
   print x , y
x , y = y , x
  1. 二元操作符两边都要加上一个空格(=, ==,<, >, !=, in, not ...)
  2. 当’=’用于指示关键字参数或默认参数值时
def complex(real, imag=0.0): 
    return magic(r=real, i=imag)
  1. 不要用空格来垂直对齐多行间的标记, 因为这会成为维护的负担(适用于:, #, =等)
YES:
foo = 1000  # comment
long_name = 2  # comment that should not be aligned

NO:
foo       = 1000  # comment
long_name = 2     # comment that should not be aligned

模块导入

  1. 每个导入应该独占一行
YES:
import os
import sys
from subprocess import Popen, PIPE      # PEP8

NO:
import sys, os
  1. 模块导入顺序
    1. 标注库导入
    2. 第三方库导入
    3. 应用程序指定导入
  2. 每种分组中, 应该根据每个模块的完整包路径按字典序排序, 忽略大小写.
import foo
from foo import bar
from foo.bar import baz
from foo.bar import Quux
from Foob import ar

TODO注释

  1. TODO注释应该在所有开头处包含”TODO”字符串, 紧跟着是用括号括起来的你的名字, email地址或其它标识符. 然后是一个可选的冒号. 接着必须有一行注释, 解释要做什么
  2. 如果你的TODO是”将来做某事”的形式, 那么请确保你包含了一个指定的日期(“2009年11月解决”)或者一个特定的事件
# TODO(kl@gmail.com): Use a "*" here for string repetition.
# TODO(Zeke) Change this to use relations.

二元运算符换行(PEP8)

# 不推荐: 操作符离操作数太远
income = (gross_wages +
          taxable_interest +
          (dividends - qualified_dividends) -
          ira_deduction -
          student_loan_interest)
 

# 推荐:运算符和操作数很容易进行匹配
income = (gross_wages
          + taxable_interest
          + (dividends - qualified_dividends)
          - ira_deduction
          - student_loan_interest)

其它规范

  1. 不要在行尾加分号, 也不要用分号将两条命令放在同一行.
  2. 除非是用于实现行连接, 否则不要在返回语句或条件语句中使用括号. 不过在元组两边使用括号是可以的.
  3. 顶级定义之间空两行, 方法定义之间空一行

Pandas使用规范

  1. pandas数据结构命名 df_、se_
  2. df取一列,禁止使用df.列名,可以使用df['列名'], 建议使用df.loc[:, '列名']
  3. 禁止使用df.ix

目录结构示例

|--docs
|--requests
|    |--__init__.py
|    |--_internal_utils.py
|    |--utils.py
|    |--api.py
|--tests
|--setup.py
|--README.rst
|--LICENSE  

Class结构示例

# -*- coding: utf-8 -*-
# (C) JiaaoCap, Inc. 2017-2018
# All rights reserved
# Licensed under Simplified BSD License (see LICENSE)

"""
requests.api

This module contains xxx. 
This module is designed to xxx.
"""

# stdlib
import os
import time

from base64 import b64encode

# 3p
try:
    import psutil
exception ImportError:
    psutil = None
import simplejson as json

# project
from .utils import current_time
from ._internal_utils import internal_func


class Response(object):
    """A user-created :class:`Response <Response>` object.
    
    Used to xxx a :class: `JsonResponse <JsonResponse>`, which is xxx
    
    :param data: response data
    :param file: response files
        
    Usage::
    
        >>> import api
        >>> rep = api.Response(url="http://www.baidu.com")
    """
    
    def __init__(self, data, files, json, url)
        self.data = data
    
    @staticmethod
    def _sort_params(params):
        """This is a private static method"""
        return params   

    def to_json():
        """The fully method blala bian shen,
        xxx sent to the server.
            
        Usage::
        
            >>> import api
            >>> rep = api.Response(url="http://www.baidu.com")
            >>> rep.to_json()
        """
        
        if self.url == "www":
            return True
        return False

相关链接

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容