PEP是Python Enhancement Proposal的缩写,一般翻译为“Python加强提案”。每一个PEP都是一份为Python社区提供的指导Python往更好的方向发展的技术文档,其中的第8号加强提案(PEP 8)是针对Python语言编订的代码风格指南。尽管咱们能够在保证语法没有问题的前提下随意书写Python代码,可是在实际开发中,采用一致的风格书写出可读性强的代码是每一个专业的程序员应该作到的事情,也是每一个公司的编程规范中会提出的要求,这些在多人协做开发一个项目(团队开发)的时候显得尤其重要。咱们能够从Python官方网站的PEP 8连接中找到该文档,下面咱们对该文档的关键部分作一个简单的总结。html
不要在行尾加分号, 也不要用分号将两条命令放在同一行。python
每行不超过80个字符。git
例外:程序员
Python会将圆括号,中括号和花括号中的行隐式的链接起来 , 你能够利用这个特色. 若是须要, 你能够在表达式外围增长一对额外的圆括号。github
Yes: foo_bar(self, width, height, color='black', design=None, x='foo', emphasis=None, highlight=0) if (width == 0 and height == 0 and color == 'red' and emphasis == 'strong'):
若是一个文本字符串在一行放不下, 可使用圆括号来实现隐式行链接:算法
x = ('This will build a very long long ' 'long long long long long long string')
在注释中,若是必要,将长的URL放在一行上。编程
Yes: # See details at # http://www.example.com/us/developer/documentation/api/content/v2.0/csv_file_name_extension_full_specification.html
No: # See details at # http://www.example.com/us/developer/documentation/api/content/\ # v2.0/csv_file_name_extension_full_specification.html
宁缺毋滥的使用括号。
除非是用于实现行链接, 不然不要在返回语句或条件语句中使用括号。 不过在元组两边使用括号是能够的。api
Yes: if foo: bar() while x: x = bar() if x and y: bar() if not x: bar() return foo for (x, y) in dict.items(): ...
No: if (x): bar() if not(x): bar() return (foo)
PEP 8倡导用不一样的命名风格来命名Python中不一样的标识符,以便在阅读代码时可以经过标识符的名称来肯定该标识符在Python中扮演了怎样的角色(在这一点上,Python本身的内置模块以及某些第三方模块都作得并非很好)。app
在Python之禅(可使用import this查看)中有这么一句名言:“There should be one-- and preferably only one --obvious way to do it.”,翻译成中文是“作一件事应该有并且最好只有一种确切的作法”,这句话传达的思想在PEP 8中也是无处不在的。编程语言
确保对模块, 函数, 方法和行内注释使用正确的风格。
最须要写注释的是代码中那些技巧性的部分。若是你在下次代码审查的时候必须解释一下,那么你应该如今就给它写注释。对于复杂的操做, 应该在其操做开始前写上若干行注释。对于不是一目了然的代码, 应在其行尾添加注释。
# 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 if i is 0 or a power of 2.
为了提升可读性,注释应该至少离开代码2个空格。
另外一方面, 毫不要描述代码。 假设阅读代码的人比你更懂Python, 他只是不知道你的代码要作什么。
Python有一种独一无二的的注释方式: 使用文档字符串。
文档字符串是包, 模块,类或函数里的第一个语句。
这些字符串能够经过对象的__doc__成员被自动提取, 而且被pydoc所用。(你能够在你的模块上运行pydoc试一把, 看看它长什么样)。
咱们对文档字符串的惯例是使用三重双引号"""( PEP-257 )。
一个文档字符串应该这样组织:
一个函数必需要有文档字符串,除非它知足如下条件:
文档字符串应该包含函数作什么以及输入和输出的详细描述。一般不该该描述“怎么作”,除非是一些复杂的算法。
文档字符串应该提供足够的信息,当别人编写代码调用该函数的时候,它不须要看一行代码,只要看文档字符串就够了。对于复杂的代码,在代码旁边加注释会比文档字符串更有意义。
函数的文档字符串格式,将函数按照参数、返回值、抛出异常等信息分小节进行描述,每小节应该以一个标题行开始,标题行以冒号结尾,除标题行外, 节的其余内容应被缩进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."""
“惯例”这个词指的是“习惯的作法,常规的办法,一向的作法”,与这个词对应的英文单词叫“idiom”。因为Python跟其余不少编程语言在语法和使用上仍是有比较显著的差异,所以做为一个Python开发者若是不能掌握这些惯例,就没法写出“Pythonic”的代码。下面咱们总结了一些在Python开发中的惯用的代码。
if __name__ == '__main__':
if x: if not x:
好的代码:
name = 'Safe' pets = ['Dog', 'Cat', 'Hamster'] owners = {'Safe': 'Cat', 'George': 'Dog'} if name and pets and owners: print('We have pets!')
很差的代码:
if name != '' and len(pets) > 0 and owners != {}: print('We have pets!')
if x in items: # 包含 for x in items: # 迭代
好的代码:
name = 'Safe Hammad' if 'H' in name: print('This name has an H in it!')
很差的代码:
name = 'Safe Hammad' if name.find('H') != -1: print('This name has an H in it!')
a, b = b, a
好的代码
chars = ['S', 'a', 'f', 'e'] name = ''.join(chars) print(name) # Safe
很差的代码
chars = ['S', 'a', 'f', 'e'] name = '' for char in chars: name += char print(name) # Safe
“It's Easier to Ask for Forgiveness than Permission.”
“Look Before You Leap”
好的代码
d = {'x': '5'} try: value = int(d['x']) except (KeyError, TypeError, ValueError): value = None
很差的代码
d = {'x': '5'} if 'x' in d and \ isinstance(d['x'], str) and \ d['x'].isdigit(): value = int(d['x']) else: value = None
好的代码
fruits = ['orange', 'grape', 'pitaya', 'blueberry'] for index, fruit in enumerate(fruits): print(index, ':', fruit)
很差的代码
fruits = ['orange', 'grape', 'pitaya', 'blueberry'] index = 0 for fruit in fruits: print(index, ':', fruit) index += 1
好的代码
data = [7, 20, 3, 15, 11] result = [num * 3 for num in data if num > 10] print(result) # [60, 45, 33]
很差的代码
data = [7, 20, 3, 15, 11] result = [] for i in data: if i > 10: result.append(i * 3) print(result) # [60, 45, 33]
好的代码
keys = ['Safe', 'Bob', 'Thomas'] values = ['Hammad', 'Builder', 'Engine'] d = dict(zip(keys, values)) print(d) # {'Bob': 'Builder', # 'Safe': 'Hammad', # 'Thomas': 'Engine'}
很差的代码
keys = ['Safe', 'Bob', 'Thomas'] values = ['Hammad', 'Builder', 'Engine'] d = {} for i, key in enumerate(keys): d[keys] = values[i] print(d) # {'Bob': 'Builder', # 'Safe': 'Hammad', # 'Thomas': 'Engine'}