[Advanced Python] 16 - Google style guide for programming

Ref: Python 风格指南 - 内容目录html

这里主要记录一下值得注意的地方。python

 

Python语言规范

Lint:vsCode自带api

导入:完整路径app

异常socket

  Ref: [Python] 07 - Statements --> Functionside

  首先,自定义异常,基于“异常基类” class Error(Exception);函数

  其次,except捕获全部异常过于鲁莽;post

  最后,鼓励使用finally执行“资源清理工做“。学习

全局变量:避免使用,考虑下”类变量“来代替。fetch

嵌套/局部/内部类或函数

  推荐使用!

  对“类中类”状况的序列化(pickled)带来问题。

列表推导(List Comprehensions):太复杂的仍是考虑map, reduce, filter。

默认迭代器和操做符:优先使用“省内存的迭代器方法";

生成器:”没有“缺点

Lambda函数

  适用于单行函数;

  对于常见的操做符,例如乘法操做符,使用 operator 模块中的函数以代替lambda函数。

条件表达式:适合单行,例如 if cond else 2

默认参数值

  默认参数只在模块加载时求值一次。若是参数是列表或字典之类的可变类型, 这可能会致使问题。

# 使用 None间接表达
def foo(a, b=None):
         if b is None:
             b = []

# 而不是直接用”可变类型“做为默认参数
def foo(a, b=[])

属性(properties):有必要替代setter getter。

True/False的求值

按直觉来说,就是全部的”空”值都被认为是false。  

”布尔量“ 使用 is 或者 is not。

空列表就是None。

注意 is 和 == 的区别,以下:

>>> a is []
False
>>> a == []
True
>>> a
[]

过期的语言特性:有新的就用新的

词法做用域(Lexical Scoping)

嵌套的Python函数能够引用外层函数中定义的变量,可是不可以对它们赋值。(鼓励使用)

i = 4
def foo(x):
    def bar():
        print i,
    # ...
    # A bunch of code here
    # ...
    for i in x:  # Ah, i *is* local to Foo, so this is what Bar sees
        print i,
    bar()

函数与方法装饰器

最多见的装饰器是@classmethod@staticmethod,用于将常规函数转换成类方法或静态方法。

实例方法(普通方法)—————————随着实例属性的改变而改变

类方法(不管是类调用仍是实例调用)——都是类属性的值,不随实例属性的变化而变化

静态方法———————————————不能够访问类属性,故直接输出传入方法的值

线程:不要依赖内建类型的原子性。

威力过大的特性

Python是一种异常灵活的语言, 它为你提供了不少花哨的特性, 诸如元类(metaclasses), 字节码访问, 任意编译(on-the-fly compilation), 动态继承, 对象父类重定义(object reparenting), 导入黑客(import hacks), 反射, 系统内修改(modification of system internals), 等等.

优势:强大的语言特性, 能让你的代码更紧凑;

缺点:使用这些很”酷”的特性十分诱人, 但不是绝对必要. 使用奇技淫巧的代码将更加难以阅读和调试. 开始可能还好(对原做者而言), 但当你回顾代码, 它们可能会比那些稍长一点可是很直接的代码更加难以理解;

结论:在你的代码中避免这些特性.

 

 

Python风格规范

分号:不要

行长度:80 chars at most;括号就有隐式链接属性。

括号:宁缺毋滥

缩进:四个空格

空行:两行和一行两种模式

空格:照旧便可

Shebang:main文件写 #/usr/bin/python3

若是一个类不继承自其它类,就显式的从object继承. 嵌套类也同样。

class OuterClass(object):
  class InnerClass(object):
    pass

字符串

免在循环中用+和+=操做符来累加字符串. 因为字符串是不可变的, 这样作会建立没必要要的临时对象, 而且致使二次方而不是线性的运行时间。

在循环结束后用 .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)

文件和sockets:使用with...as

导入格式:每一个导入应该独占一行;完整包路径按字典序排序, 忽略大小写。

语句:一般每一个语句应该独占一行

控制访问:可考虑属性(property)

命名

命名约定

    1. 所谓”内部(Internal)”表示仅模块内可用, 或者, 在类内是保护或私有的.
    2. 用单下划线(_)开头表示模块变量或函数是protected的(使用from module import *时不会包含).
    3. 用双下划线(__)开头的实例变量或方法表示类内私有.
    4. 将相关的类和顶级函数放在同一个模块里. 不像Java, 不必限制一个类一个模块.
    5. 对类名使用大写字母开头的单词(如CapWords, 即Pascal风格), 可是模块名应该用小写加下划线的方式(如lower_with_under.py). 尽管已经有不少现存的模块使用相似于CapWords.py这样的命名, 但如今已经不鼓励这样作, 由于若是模块名碰巧和类名一致, 这会让人困扰.
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  

Main函数

def main():
      ...

if __name__ == '__main__':
    main()

 

 

注释之美 

TODO注释

# TODO(kl@gmail.com): Use a "*" here for string repetition.
# TODO(Zeke) Change this to use relations.

 

文档字符串

毫不要描述代码。假设阅读代码的人比你更懂Python, 他只是不知道你的代码要作什么。

一个文档字符串应该这样组织:

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

Function

一个函数必需要有文档字符串, 除非它知足如下条件:

    1. 外部不可见
    2. 很是短小
    3. 简单明了
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

 

Class

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."""

 

End.

相关文章
相关标签/搜索