Python 编码风格指南(收藏)

发布时间:2020-05-12编辑:脚本学堂
这是一篇有关python编程风格的指南性文章,介绍了一些规范的、良好的python编码风格,有需要的朋友参考下。
本节是 Python 编码风格指南 第三部分的内容,请大家继续阅读。
 如果确定你的类会被子类化,并且你有不希望子类使用的属性,考虑用两个前导下划线、但没有后置下划线命名它们。这将触发 Python 的名字重整算法,把类名整合进属性名中。当子类无意中包含了相同名字的属性时,这有助于避免属性名冲突。

        注1:注意仅使用简单类名来重整名字,因此,如果子类使用相同的类名和属性名,你仍然会名字冲突。

        注2:名字重整使一些应用稍有不便,例如调试和 __getattr__()。然而名字重整算法有良好的文档,也容易手工执行。

        注3:不是每个人都喜欢名字重整。尝试在避免意外的名字冲突需求和高级调用者的可能应用之间平衡。


设计建议 (Programming Recommendations)

    - 某种程度上,代码不应该不利于其他 Python 实现 (PyPy, Jython, IronPython,
      Pyrex, Psyco, 等等)。

      例如,对 a+=b or a=a+b 形式的语句,不要依赖 CPython 对就地 (in-place) 字符串连接的高效实现。那些语句在 Jython 中运行很慢。对库的性能敏感部分,应该改用  ''.join() 语句。这将保证对不同的实现,字符串连接表现为线性时间。

    - 与 None 之类的单件比较,应该总是用 'is' or 'is not',绝不要用等号操作符。

      同样,当你本意是 "if x is not None" 时,对写成 "if x" 要小心 -- 例如,当测试一个默认为 None 的变量或参数是否被设置为其他值时,这个其他值可能是一种在布尔上下文中为假的类型 (例如容器)!

    - 使用基于类的异常。

      在新代码中,禁止使用字符串异常 (String exceptions),因为这一语言特征将在Python 2.6 中被移除。

      模块和包应该定义它们自己的特定域的异常基类,该异常基类应该是内建异常类的子类。还始终包含一个类的文档字符串。
      例如:
        class MessageError(Exception):
            """Base class for errors in the email package."""

      类命名约定也适用于这里,尽管当异常是错误时,你应该添加 "Error" 后缀到你的异常类。非错误类异常不需要特殊后缀。

    - 当 raise 一个异常时,使用 "raise ValueError('message')" 代替旧的 "raise ValueError, 'message'"。

      首选采用使用圆括号的形式,因为当异常参数很长或者包括格式化字符串时,你不需要使用行延续符,感谢包含的圆括号。在 Python 3000 中将移除旧的形式。

    - 在捕获异常时,尽可能写出明确的异常,而不是使用空的 'except:' 子句。

      例如使用:
          try:
              import platform_specific_module
          except ImportError:
              platform_specific_module = None

      空的 'except:' 子句将捕获 SystemExit and KeyboardInterrupt 异常,这使得用Control-C 中断程序变得困难,也会掩饰其他问题。如果你想捕获全部导致程序错误的异常,就使用 'except StandardError:'。

      一个好的经验方法是把空的 'except' 子句限制用在两种情况:

         1) 如果异常处理器将打印出或者日志记录 traceback,至少用户将知道有错误发生。

         2) 如果代码需要做一些清除工作,但然后用 'raise' 来向上传播异常。对这种情况,'try...finally' 是一种更好的处理方法。

    - 另外,对所有 try/except 子句,把 'try' 子句限制在有需要的绝对最少量代码。
      这再次避免掩饰 bugs。
     

复制代码 代码示例:
Yes:
          try:
              value = collection[key]
          except KeyError:
              return key_not_found(key)
          else:
              return handle_value(value)
      No:
          try:
              # Too broad!
              return handle_value(collection[key])
          except KeyError:
              # Will also catch KeyError raised by handle_value()
              return key_not_found(key)

    - 使用字符串方法代替 string 模块。

      字符串方法总是很快,而且和 unicode 字符串共用同样的 API。如果必须向后兼容Python 2.0 以前的版本,可不考虑此规则。

    - 使用 ''.startswith() and ''.endswith() 代替字符串切片,来检查前缀和后缀。

      startswith() and endswith() 更清晰易读,也倾向于减少错误。例如:
       

复制代码 代码示例:
Yes: if foo.startswith('bar'):
        No:  if foo[:3] == 'bar':

      如你的代码必须工作在 Python 1.5.2 (希望不是!),则除外。

    - 对象类型的比较应该始终用 isinstance() 代替直接比较类型。
  

复制代码 代码示例:
      Yes: if isinstance(obj, int):
        No:  if type(obj) is type(1):

      检查一个对象是否是字符串时,紧记它也可能是 unicode 字符串!在 Python 2.3中,str 和 unicode 有公共的基类 basestring,所以你可以这样做:
        if isinstance(obj, basestring):

      在 Python 2.2 中,types 模块为此定义了 StringTypes 类型,例如:
    

复制代码 代码示例:
  from types import StringTypes
        if isinstance(obj, StringTypes):

      在 Python 2.0 和 2.1 中,你应该这样做:
  

复制代码 代码示例:
    from types import StringType, UnicodeType
        if isinstance(obj, StringType) or
           isinstance(obj, UnicodeType) :

    - 对序列 (字符串 (strings),列表 (lists),元组 (tuples)),使用空序列为假这个事实。
   

复制代码 代码示例:

   Yes: if not seq:
           if seq:

      No: if len(seq)
          if not len(seq)

    - 不要书写依赖于有意义的后置空白字符的文本字符串。这种后置空白字符在视觉上不可区分,并且有些编辑器 (或者最近,reindent.py) 会将它们裁剪掉。

    - 不要用 == 来把布尔值与 True 或 False 进行比较。
     

复制代码 代码示例:
   Yes:   if greeting:
        No:    if greeting == True:
        Worse: if greeting is True:

References
    [1] PEP 7, Style Guide for C Code, van Rossum
    [2] http://www.python.org/doc/essays/styleguide.html
    [3] PEP 257, Docstring Conventions, Goodger, van Rossum
    [4] http://www.wikipedia.com/wiki/CamelCase
    [5] Barry's GNU Mailman style guide
        http://barry.warsaw.us/software/STYLEGUIDE.txt
    [6] PEP 20, The Zen of Python
    [7] PEP 328, Imports: Multi-Line and Absolute/Relative

Copyright
    This document has been placed in the public domain.