个人学习记录,若有侵权,请联系删除。
一、代码布局
1、分号
不要在行尾加分号,也不要用分号将两条命令放在同一行
2、缩进
每级缩进使用四个空格(不要使用tab)
推荐写法
a = 1
if a == 1:
print(a)
不推荐写法
a = 1
if a == 1:
print(a)
(1)续行:续行应与其包裹元素对齐
①推荐写法
# 与左括号对齐(垂直对齐)
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)
②不推荐写法
# 第一行有参数时没有垂直对齐
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)
(2)括号:右括号(小括号、中括号、花括号)可以放在最后一行第一个非空字符的正下方/放在最后以行下方的开头
①推荐写法一
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',
)
(3)多行if
推荐写法
if (this_is_one_thing
and that_is_another_thing):
do_something()
3、行长度
(1)所有行限制的最大字符数为79
(2)较少结构化限制的长文本流(文档字符或注释),每行最大字符数限制在72
注:可以通过将括号中的表达式换行来将长行折断成多行。
①推荐写法一
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)
4、空行
(1)顶层函数和类的定义,前后用两个空行隔开
(2)类里面的方法定义用一个空行隔开
5、空格
(1)括号内不要有空格
# 正确写法
spam(ham[1], {eggs: 2}, [])
# 错误写法
spam( ham[ 1 ], { eggs: 2 }, [ ])
(2)逗号,分号,冒号前不加空格,在后面加空格(除行尾外)
# 正确写法
if x == 4:
print(x, y)
# 错误写法
if x == 4:
print(x , y)
(3)在二元操作符两边都加上一个空格,如赋值(=),比较(==, <, >, !=, <>, <=, >=, in, not in, is, isnot),布尔(and, or, not)
# 推荐写法
x == 1
# 不推荐写法
x<1
(4)当“=”用于指示关键字参数或默认参数值时,不要在其两侧使用空格
# 推荐写法
def complex(real, imag=0.0):
return magic(r=real, i=imag)
# 不推荐写法
def complex(real, imag = 0.0):
return magic(r = real, i = imag)
注:当将参数注释与默认值结合使用时,在“=”两侧使用空格
# 推荐写法
def munge(sep: AnyStr = None): ...
# 不推荐写法
def munge(input: AnyStr=None): ...
(5)切片参数被忽略时,空格被忽略
# 推荐写法
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]
二、注释
1、行内注释
行内注释是和语句在同一行,至少用两个空格和语句分开。行内注释不是必需的
x = x + 1 # Increment x
2、文档字符串
为所有公共模块、函数、类和方法书写文档字符串。
注:多行文档字符串时,注意结尾的"""应该单独成行;单行时结尾的"""在同一行
"""Return a foobang
Optional plotz says to frobnicate the bizbaz first.
"""
(1)函数和方法
标题行(如Args、Returns)以冒号结尾,除标题行外,节的其他内容应被缩进
- Args
列出每个参数的名字,并在名字后使用一个冒号和一个空格,分隔对该参数的描述(包括所需的类型和含义)。如果一个函数接受*args(可变长度参数列表)或**kwargs(任意关键字参数), 应该详细列出**args和**kwargs。如果描述太长超过了单行79字符,使用2或4个空格的悬挂缩进。
- Rerturns/Yields(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 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
(2)类
类应该在其定义下有一个用于描述该类的文档字符串。如果类中有公共属性,那么文档中应该有一个属性(Attributes)段,并且应该遵守和函数参数相同的格式。
class SampleClass(object):
"""Summary of class here.
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."""
3、TODO注释
为临时代码使用TODO注释;TODO注释应该在所有开头处包含"TODO"字符串,紧跟着是用括号括起来的名字,email地址或其他标识符,然后是一个可选的冒号。接着必须有一行注释,解释要做什么。
# TODO(kl@gmail.com): Use a "*" here for string repetition.
# TODO(Zeke) Change this to use relations.
三、字符串
# 推荐写法
x = '%s, %s!' % (imperative, expletive)
x = '{}, {}!'.format(imperative, expletive)
x = 'name: %s; score: %d' % (name, n)
x = 'name: {}; score: {}'.format(name, n)
# 不推荐写法
x = '%s%s' % (a, b) # use + in this case
x = '{}{}'.format(a, b) # use + in this case
x = imperative + ', ' + expletive + '!'
x = 'name: ' + name + '; score: ' + str(n)
1、避免在循环中用+和+=操作符来累加字符串
由于字符串不可变的,这样做会创建不必要的临时对象,并且导致二次方而不是线性的运行时间。可以就每个子串加入列表,然后在循环结束后用.join连接列表。
# 推荐写法
items = ['<table>']
for last_name, first_name in employee_list:
items.append('<tr><td>%s, %s</td></tr>' % (last_name, first_name))
items.append('</table>')
employee_table = ''.join(items)
# 不推荐写法
items = '<table>'
for last_name, first_name in employee_list:
employee_table += '<tr><td>%s, %s</td></tr>' % (last_name, first_name)
employee_table += '</table>'
2、在同一个文件中, 保持使用字符串引号的一致性. 使用单引号'或者双引号"之一用以引用字符串, 并在同一文件中沿用. 在字符串内可以使用另外一种引号, 以避免在字符串中使用.
# 推荐写法
Python('Why are you hiding your eyes?')
Gollum("I'm scared of lint errors.")
Narrator('"Good!" thought a happy Python reviewer.')
# 不推荐写法
Python("Why are you hiding your eyes?")
Gollum('The lint. It burns. It burns us.')
Gollum("Always the great lint. Watching. Watching.")
3、为多行字符串使用三重双引号"""而非三重单引号'''. 当且仅当项目中使用单引号'来引用字符串时, 才可能会使用三重'''为非文档字符串的多行字符串来标识引用. 文档字符串必须使用三重双引号""".
四、导入格式
导入应该放在文件顶部,位于模块注释和文档字符串之后,模块全局变量和常量之前。导入应该按照从最通用到最不通用的顺序分组(各组的导入之间要有空行):
①标准库导入
②第三方库导入
③应用程序指定导入
import os
import sys
from PyPDF2 import PdfMerger
from mypkg.sibling import example
五、命名
1、应该避免的名称
(1)单字符名称,除了计数器和迭代器(例如i)
(2)包/模块名中的连字符(-)(例如study-id)
(3)双下划线开头并结尾的名称(Python保留,例如__init__)
2、命名约定
(1)所谓“内部(Internal)”表示仅模块内可用,或者在类内是保护或私有的
(2)用单下划线(_)开头表示模块变量或函数是protected的(使用import * from时不会包含)
(3)用双下划线(__)开头的实例变量或方法表示类内私有
(4)将相关的类和顶级函数放在同一个模块里
(5)对类名使用大写字母开头的单词(如CapWords, 即Pascal风格), 但是模块名应该用小写加下划线的方式(如lower_with_under.py)
3、Python之父Guido推荐的规范
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 |