Python 的常用规范

编码及摘要

脚本两行指标 Python 运行环境及编码内容

① 一般环境定义
注:由于Python2.x默认采用 ASCII ,因此使用中文时要在源文件开头加上源文件的编码格式说明,Python3.x 默认采用 UTF-8,因此不需要

#!/usr/bin/python
# _*_ coding: utf-8

② Abaconda 环境参数定义

#!/appcom/install/anaconda/bin/python
# _*_ coding: utf-8

代码及缩进

每级缩进用四个空格,切勿使用 Tab 键进行缩进;

当参数过长的时候,采用 垂直隐式缩进悬挂缩进

① 垂直隐式缩进

# (垂直隐式缩进)对准左括号
foo = long_function_name(var_one, var_two,
                         var_three, var_four)

② 悬挂缩进

# (悬挂缩进)一般情况只需多一层缩进
foo = long_function_name(
    var_one, var_two,
    var_three, var_four)
# (悬挂缩进)但下面情况, 需再加多一层缩进, 和后续的语句块区分开来
def long_function_name(
        var_one, var_two, var_three,
        var_four):
    print(var_one)

③ 多行结构

# 多行结构中的大括号、中括号、小括号的右括号可与内容对齐单独起一行作为最后一行的第一个字符
my_list = [
    1, 2, 3,
    4, 5, 6,
    ]

result = some_function_that_takes_arguments(
    'a', 'b', 'c',
    'd', 'e', 'f',
    )
# 也可以与多行结构的第一行第一个字符对齐
my_list = [
    1, 2, 3,
    4, 5, 6,
]
result = some_function_that_takes_arguments(
    'a', 'b', 'c',
    'd', 'e', 'f',
)

④ IF 语句的缩进

当 IF 语句的条件判断部分长到需要换行写的时候,可以在 IF 后面增加一个空格,再增加一个左括号来创造一个 4空格 缩进的多行条件

# 没有额外的缩进,但条件判断的语句会和后面的语句产生视觉冲突
if (this_is_one_thing and
    that_is_another_thing):
    do_something()

# 增加一个注释,在能提供语法高亮的编辑器中可以有一些区分
if (this_is_one_thing and
    that_is_another_thing):
    # 这里添加注释,区分前后两部分的语句
    do_something()

# 在条件判断的语句添加额外的缩进,和后面语句区分
if (this_is_one_thing
        and that_is_another_thing):
    do_something()

换行

每行代码控制在120个字符以内(文档/注释限制在72个字符以内)

优先选择在小括号、中括号以及大括号中的隐式续行方式,比如通过小括号内表达式的换行方式将长串折成多行

query_str = ("select DriveLetter " 
             "from Win32_Volume " 
             "where Label = \"%s\"") % (args.logusn)

如果如无法使用隐式续行,则使用反斜杠 \ 续行

with open('/path/to/some/file/you/want/to/read') as file_1, \
     open('/path/to/some/file/being/written', 'w') as file_2:
    file_2.write(file_1.read())

公式应该在二元运算符之前中断换行,即换行之后的续行一开始是二元运算符,这样运算符和操作数容易进行匹配

income = (gross_wages
          + taxable_interest
          + (dividends - qualified_dividends)
          - ira_deduction
          - student_loan_interest)

不要使用复合语句(同一行中存在多个语句),错误如下所示

if foo == 'something': do_blah_thing()
do_one(); do_two(); do_three()

换行

模块级函数和类定义之间空两行,类成员函数之间空一行,在函数中使用空行来区分逻辑段(谨慎使用)

class Common(object):
    """common class,提供通用的方法"""
    def __init__(self):
        """common的构造器:"""
        pass

    def method1(self):
        pass

    def method2(self):
        pass


def method3():
    pass

命名

变量命名
自定义变量时,需要满足通用的标识符规则

① 由数字、字母、下划线组成
② 不能数字开头
③ 严格区分⼤小写
④ 不能使⽤内置关键字作为变量名称

在这里插入图片描述

模块命名

模块名应该简短,全部用小写字母,多字母之间可以使用单下划线连接;

包命名

包(通常是包含 __init__.py 及其他模块文件的目录文件)名也应该使用简短全小写的名字,但不建议用下划线

package
├── __init__.py
├── sub_pkg1
│   ├── __init__.py
│   ├── module_x.py
│   ├── module_y.py
└── sub_pkg2
    ├── __init__.py
    └── module_z.py

类命名

类名使用驼峰命名风格,首字母大写,私有类用 _ 开头

class BackupFile(object):
    """Backup_File class"""

异常

异常也是类,所以也使用类名规则,但是应该增加后缀 Error

class SomeCustomError(Exception):
    def __init__(self,str_length):
        super(SomeCustomError,self).__init__()
        self.str_length = str_length
        
try:
    s = raw_input("输入一行字符串:\n")
    # 输入字符串长度超过指定长度范围,引发异常
    if (length < len(s)):
        raise SomeCustomError(length)
except SomeCustomError as x:
    print("捕获自定义异常")

全局变量

全局变量名应尽量只在模块内部使用, 对可能使用语句 from moduleName import variableName 而被导入的模块,应采用 __all__ 机制来防止全局变量被别的模块导入, 或者在全局变量名开头加一个前置下划线

__all__ = ['var1', 'var2', 'var3']
_name = 'var4'

函数和变量

函数和变量名一律小写,如果想提高可读性可以用下划线分隔

status_code = 0

def thread_fun(self, cmdstr):
    """单个线程"""

方法参数

类的方法第一个参数必须是 self,而类方法第一个参数必须是 cls

class Kls(object):
    no_inst = 0
    def __init__(self):
        Kls.no_inst = Kls.no_inst + 1

    @classmethod
    def get_no_of_instance(cls):
        return cls.no_inst

常量

常量命名使用全部大写的方式,可以使用下划线

HOST = "192.168.1.10"
PORT = 7777
NUM_LOG = 100000

异常

自定义异常类尽量继承 Exception ,而不是 BaseException

class AccessError(Exception):
    def __init__(self,str_length):
        super(AccessError,self).__init__()
        self.str_length = str_length

捕捉异常的时候使用 as 定义异常

# 捕获全局异常
try:
    process_data()
except Exception as exc:
    raise DataProcessingFailedError(str(exc))

捕获其它异常

try:
    value = collection[key]
except KeyError:
    return key_not_found(key)
else:
    return handle_value(value)

注释

注释一般为公共模块,函数,类以及方法编写

① 单行注释

单行的文档说明,尾部的三引号应该和文档在同一行

def mount(args):
    '''mount to new mysql instance'''
    target_dir = args.target_dir

② 多行注释

多行的文档说明,使用的结尾三引号应该自成一行

"""
This is the example module.
This module does stuff.
"""

③ 方法注释

公共方法的文档说明要注明入参和返回值

def backup_alone(self, args):  
    """单通道备份函数
    Parameters:
        filesystem(str): 文件系统
        mountpoint(str): 挂载点
        include(str): 包含文件
        exclude(str): 排除文件
    Returns:
        pid(str): 进程号   
    """

非公共的方法没有必要写文档说明,但是应该有一个描述方法具体作用的注释,这个注释应该在def那一行之后

def backup_synth(args):
    # 增量备份
    logger.info('backup_synth')

④ 文档注释

文档注释一般出现在模块头部,函数和类的头部,文档注释以 """ 开头和结尾

https://www.sphinx-doc.org/en/master/usage/extensions/example_google.html

"""Example docstrings.
Examples can be given using either the ...
"""

⑤ 重点注释

重点注释在代码逻辑复杂地方尽量写注释,并用多个等号隔开,突出重要性

app = create_app(name,options)
# ================================
# 请勿在此处添加 get post等app路由行为!!!
# ================================
if _name_=='_main_':
app.run()

导入

每个 import 应该独立成行

import os
import sys

import 总是位于文件的顶部,在模块注释和文档字符串之后,在模块的全局变量与常量之前

按照以下顺序 import,且各 import 类型之间需要用空行隔开

1、标准库
2、第三方库
3、本地库

避免使用通配符进行 import,即 from xxx import *,建议使用如下形式

from subprocess import Popen, PIPE

__all__ , __author__ , __version__ 等这样的模块级属性,应该放在文档字符串的后面,以及除 from __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__ = 'John'

import os
import sys

包(package)内的模块导入

包是一个含有多个模块文件的文件夹,python2 需要在这个文件内添加一个 __init__.py 文件,该文件内容可以为空,python3 可加可不加 __init__.py,但为了规范最好加上

包内的模块文件不能作为顶层模块来执行,即不能作为主函数的入口

包内的模块文件避免使用隐式相对导入同目录下的其它模块(python3禁止使用),建议在包内使用相对导入,在包外使用绝对导入

package
├── __init__.py
├── sub_pkg1
│   ├── __init__.py
│   ├── module_x.py
│   ├── module_y.py
└── sub_pkg2
    ├── __init__.py
    └── module_z.py

# module_x.py
import module_y  # 隐式相对导入
from module_y import var  # 隐式相对导入
from . import module_y  # 显式相对导入
from .module_y import var  # 显式相对导入
from sub_pkg1 import module_y  # 绝对导入

表达式和语句中的空格

二元运算符两边要放置一个空格

赋值( = )
增量赋值( += , -=)
比较运算( == , < , > , != , <> , <= , >= , in , not in , is , is not )
布尔运算( and , or , not )

如果使用具有不同优先级的运算符,请考虑在具有最低优先级的运算符周围添加空格。有时需要通过自己来判断,但是不要使用一个以上的空格,并且在二元运算符的两边使用相同数量的空格

i = i + 1
submitted += 1
x = x*2 - 1
hypot2 = x*x + y*y
c = (a+b) * (a-b)

函数参数列表中,逗号之后要有空格,但在制定关键字参数或者默认参数值的时候,不要在 = 附近加上空格

# 正确写法
def complex(real, imag=0.0):
    return magic(r=real, i=imag)

# 错误写法
def complex(real,imag = 0.0):
    return magic(r = real, i = imag)

其他注意事项

一行的尾部不要有空格

紧接着圆括号、方括号和花括号的内侧不加空格

# 正确写法
spam(ham[1], {eggs: 2})

# 错误写法
spam( ham[ 1 ], { eggs: 2 } )

逗号及后面的括号之间不加空格

# 正确写法
foo = (0,)

# 错误写法
bar = (0, )
# 正确写法
if x == 4: print x, y; x, y = y, x

# 错误写法
if x == 4 : print x , y ; x , y = y , x

在切片中

在切片中,冒号就像一个二元运算符(把它当作优先级最低的运算符),在冒号两边应该有相等的空格数量,但当一个切片参数被省略时,空格也被省略了

# 正确写法
ham[1:9], ham[1:9:3], ham[:9:3], ham[1::3], ham[1:9:]
ham[lower:upper], ham[lower:upper:], ham[lower::step]
ham[lower+offset : upper+offset]
ham[: upper_fn(x) : step_fn(x)], ham[:: step_fn(x)]
ham[lower + offset : upper + offset]

# 错误写法
ham[lower + offset:upper + offset]
ham[1: 9], ham[1 :9], ham[1:9 :3]
ham[lower : : upper]
ham[ : upper]

函数及赋值语句中

函数调用参数列表的圆括号前不加空格

# 正确写法
spam(1)

# 错误写法
spam (1)

索引或切片的方括号前不加空格

# 正确写法
dct['key'] = lst[index]

# 错误写法
dct ['key'] = lst [index]

在赋值语句的运算符周围,不要为了对齐而使用多个空格

# 正确写法
x = 1
y = 2
long_variable = 3

# 错误写法
x             = 1
y             = 2
long_variable = 3
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值