编程风格


13 编程风格

13.1 简介

为了编程的规范,我们一般约定一些编程规则、约定,这些都称为编程风格。

13.2 分号

不要在行尾加分号, 也不要用分号将两条命令放在同一行。

13.3 行长度

1)      每行不超过80个字符。当然也有例外的情况,比如:

长的导入模块语句或者注释里的URL

2)      不要使用反斜杠连接行.

Python会将 圆括号,中括号和花括号中的行隐式的连接起来 , 你可以利用这个特点. 如果需要, 你可以在表达式外围增加一对额外的圆括号.

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'):
3)      如果一个文本字符串在一行放不下, 可以使用圆括号来实现隐式行连接:
x = ('This will build a very long long '
     'long longlong long long long string')
4)      在注释中,如果必要,将长的URL放在一行上。
#http://www.example.com/us/developer/documentation/api/content/v2.0/csv_file_name_extension_full_specification.html

13.4 括号

除非是用于实现行连接, 否则不要在返回语句或条件语句中使用括号. 不过在元组两边使用括号是可以的。

推荐的代码风格:

if foo:
         bar()
     while x:
         x =bar()
     if x and y:
         bar()
     if not x:
         bar()
     return foo
     for (x, y)in dict.items(): ...
不建议的代码风格: 
if (x):
         bar()
     if not(x):
         bar()
     return (foo)

13.5 应用

用4个空格来或则tab来缩进代码绝不能tab和空格混用。

13.6 空格

按照标准的排版规范来使用标点两边的空格。

1)      括号内不要有空格.

推荐方式:

spam(ham[1], {eggs: 2}, [])

不建议方式: 

spam( ham[ 1 ], { eggs: 2 }, [ ] )

2)      不要在逗号, 分号, 冒号前面加空格, 但应该在它们后面加(除了在行尾).

推荐方式:

if x == 4:

         printx, y

     x, y = y, x

不建议方式: 

if x == 4 :

         print x, y

     x , y = y ,x

3)      参数列表, 索引或切片的左括号前不应加空格.

推荐方式:

spam(1)

不推荐:

spam (1)

推荐方式:

dict['key'] = list[index]

不推荐方式: 

dict ['key'] = list [index]

4)      在二元操作符两边都加上一个空格, 比如赋值(=), 比较(==,<, >, !=, <>, <=, >=, in, not in, is, is not), 布尔(and, or, not). 至于算术操作符两边的空格该如何使用, 需要你自己好好判断. 不过两侧务必要保持一致.

建议方式:

x == 1

不建议:

  x<1

5)      当'= '用于指示关键字参数或默认参数值时, 不要在其两侧使用空格.

推荐方式:

def complex(real, imag=0.0): return magic(r=real,i=imag)

不建议方式: 

def complex(real, imag = 0.0): return magic(r = real,i = imag)

6)      不要用空格来垂直对齐多行间的标记, 因为这会成为维护的负担(适用于:,#, =等):

推荐方式:

  

foo =1000  # comment
     long_name =2  # comment that should not be aligned
     dictionary= {
        "foo": 1,
        "long_name": 2,
         }
不建议方式:
     foo       = 1000 # comment
     long_name =2     # comment that should not bealigned
     dictionary= {
        "foo"      : 1,
        "long_name": 2,
         }

13.7 注释

1)      文档字符串

一般使用'''或则 """来实现文档字符串。 文档字符串是我们使用Python过程中一个很重要的工具,他对程序文档很有帮助,使程序很容易理解。甚至当程序运行的时候,我们可以从一个函数中返回文档字符串。

2)      函数和方法

下文所指的函数,包括函数, 方法, 以及生成器。一个函数必须要有文档字符串, 除非它外部不可见或者非常短小或者简单明了。

一般我们在函数或者方法里按照Args(参数)、Returns(返回)、Raises(异常抛出)3个方面声明文档字符串。详细解释见下:

Args:

列出每个参数的名字, 并在名字后使用一个冒号和一个空格, 分隔对该参数的描述.如果描述太长超过了单行80字符,使用2或者4个空格的悬挂缩进(与文件其他部分保持一致). 描述应该包括所需的类型和含义. 如果一个函数接受*foo(可变长度参数列表)或者**bar(任意关键字参数), 应该详细列出*foo和**bar.

Returns: (或者 Yields: 用于生成器)

描述返回值的类型和语义. 如果函数返回None, 这一部分可以省略.

Raises:

列出与接口有关的所有异常.

 

注释代码样例:

 

"""

def fetch_bigtable_rows(big_table, keys,other_silly_variable=None):

    Fetches rowsfrom a Bigtable.

    Retrievesrows pertaining to the given keys from the Table instance

    representedby big_table.  Silly things may happen if

   other_silly_variable is not None.

    Args:

        big_table:An open Bigtable Table instance.

        keys: Asequence of strings representing the key of each table row

            tofetch.

       other_silly_variable: Another optional variable, that has a much

           longer name than the other args, and which does nothing.

    Returns:

        A dictmapping 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 keyfrom the keys argument is missing from the dictionary,

        thenthat row was not found in the table.

    Raises:

        IOError:An error occurred accessing the bigtable.Table object.

"""

    pass

3)      块注释和行注释

最需要写注释的是代码中那些技巧性的部分,应该在实现前写上若干行注释. 对于那些不是一目了然的代码, 应在其行尾添加注释说明。

# We use a weighted dictionary search to find outwhere i is in

# the array.  Weextrapolate position based on the largest num

# in the array and the array size and then do binarysearch to

# get the exact number.

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

4)      为了提高可读性, 注释应该至少离开代码2个空格.

5)  注释里不需要加代码实现的详细描述性的信息,可适当描述实现过程和功能。

# 不建议的注释: COMMENT: Now go through the b array and make sure whenever i occurs

# the next element is i+1

13.8 命名

1)      应该避免的名称

a) 单字符名称, 除了计数器和迭代器.

b) 包/模块名中的连字符(-)

c) 双下划线开头并结尾的名称(Python保留, 例如__init__)

2)      命名约定

a)        所谓”内部(Internal)”表示仅模块内可用, 或者, 在类内是保护或私有的.

b)        用单下划线(_)开头表示模块变量或函数是protected的(使用import * from时不会包含).

c)        用双下划线(__)开头的实例变量或方法表示类内私有.

d)        将相关的类和顶级函数放在同一个模块里. 不像Java, 没必要限制一个类一个模块.

e)        对类名使用大写字母开头的单词(如CapWords, 即Pascal风格), 但是模块名应该用小写加下划线的方式(如lower_with_under.py). 尽管已经有很多现存的模块使用类似于CapWords.py这样的命名, 但现在已经不鼓励这样做, 因为如果模块名碰巧和类名一致, 这会让人困扰.

3)      Python之父Guido推荐的风格

类型

公用的

内部的

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


13.9 导入格式

1)      每个导入应该独占一行。

推荐方式:

import os

import sys

不建议方式: 

import os, sys

2)      导入总应该放在文件顶部, 位于模块注释和文档字符串之后, 模块全局变量和常量之前. 导入应该按照从最通用到最不通用的顺序分组:

标准库导入、

第三方库导入、

应用程序指定导入

3)      每种分组中, 应该根据每个模块的完整包路径按字典序排序, 忽略大小写.

导入示例:

import foo

from foo import bar

from foo.bar import baz

from foo.bar import Quux

from Foob import ar

13.10 总结

本章我们学习如何优雅的进行python编程,接下来我们一起熟悉下Python里的常用关键字.