• PEP8-python编码规范(下)


    1.结尾逗号

    结尾的逗号通常是可选的,除了在构成一个元素的元组时是强制性需要的(在Python 2 中,它们对 print 语句有语义)。为了清晰起见,建议将后者用括号括起来(在技术上是多余的)。

    Yes:
    FILES = ('setup.cfg',)
    下面的容易混淆:
    FILES = 'setup.cfg',

    模式是将每个值(等等)单独放在一行上,总是添加一个逗号,并在下一行添加右括号/括号/括号。然而,在同一行中使用逗号作为结束分隔符是没有意义的(除了在上面的单例元组

    中)。

    Yes:
    FILES = [
      'setup.cfg',
      'tox.ini',
      ]
    initialize(FILES,
         error=True,
            )
    No:
    FILES = ['setup.cfg', 'tox.ini',]
    initialize(FILES, error=True,)

    2.注释

    与代码功能相矛盾的注释比没有注释更糟糕。当代码发生变化时,一定要优先保证注释的更新!(尤其是函数中的参数和注释)

    注释应该是完整的句子。第一个单词应该大写,除非它是以小写字母开头的标识符(千万不要改变标识符的大小写!)

    块注释通常由完整句子组成的一个或多个段落组成,每个句子以句号结尾。

    在多句注释中,除了最后一句之外,在一个句子结束后应该使用两个空格。

    来自非英语国家的 Python 程序员:请用英语写你的注释,除非你有 120%的把握知道代码不会被不懂你语言的人读到。

    (1)块注释

    块注释通常适用于跟随它们的一些(或所有)代码,并且缩进到与代码相同的级别。块注释的每一行都以#和单个空格开头(除非它是注释内部缩进的文本)。

    (2)内联注释

    有节制的使用内联注释。

    内联注释是与语句同一行的注释。内联注释应该与语句至少分隔两个空格。它们应该从一个#和一个空格开始。

    如果代码陈述了明显的内容,那么内联注释是不必要的,实际上内联注释还会分散注意力。不要这样做:

    x = x + 1    # Increment x
    但有时候,这样也是有用的:
    x = x + 1    # Compensate for border

    (3)文档注释

    所有公共模块、函数、类和方法需要编写文档字符串。非公共方法不需要编写文档字符串,但是应该有一个注释来描述该方法的功能。这个注释应该出现在def 行之后。

    PEP 257 描述了良好的文档字符串约定。最重要的是,结束多行文档字符串的""" 应该单独在一行上

    """Return a foobang
    Optional plotz says to frobnicate the bizbaz first.
    """

     对于一个行文档字符串,请保持结束注释时的 """ 在同一行。

    3.命名约定

    Python 库的命名约定有点混乱,因此我们永远不会得到完全一致的命名约定——不过,下面是当前推荐的命名标准。应该根据这些标准编写新的模块和包(包括第三方框架),但如果现有库具有不同的风格,则首选内部一致性。

    以下命名风格通常是可以区分的:

    b (单个小写字母)
    B (单个大写字母)

    lowercase
    lower_case_with_underscores
    UPPERCASE
    UPPER_CASE_WITH_UNDERSCORES
    CapitalizedWords (或 CapWords, 或 CamelCase -- 之所以这样命名是因
    为它的字母看起来很凹凸不平)。这有时也被称为 StudlyCaps

    注意:当在 CapWords 中使用首字母缩略词时,需要将首字母缩略词大写。因此HTTPServerError 比 HttpServerError 好。

    mixedCase (与 CapitalizedWords 不同的是首字母小写!)
    Capitalized_Words_With_Underscores (不推荐)

    还有一种风格是使用一个简短的唯一前缀将相关名称组合在一起。这在 Python中并不常用,但为了完整起见,本文提到了这一点。例如,os.stat()函数返回一个元组,其项通常具有 st_mode、st_size、st_mtime 等名称。(这样做是为了强调与 POSIX 系统调用 struct 的字段的对应关系,这有助于程序员熟悉这些字段。)

    (1)需要避免的命名

    千万不要把“l”(小写字母 el)、“O”(大写字母 oh)或“I”(大写字母 eye)作为单个字符变量名。在某些字体中,这些字符与数字 1 和 0 没有区别。当你想用“l”的时候,用“L”代替

    模块应该用简短的、全小写的名称。如果能提高可读性,可以在模块名中使用下划线。Python 包也应该用简短的、全小写的名称,尽管不鼓励使用下划线。

    当用 C 或 c++编写的扩展模块有一个附带的 Python 模块,该模块提供更高级别的接口(例如,更面向对象的接口)时,C/ c++模块有一个前导下划线(例如_socket)。

    (2)异常命名

    因为异常应该是类,所以这里使用类命名约定。但是,您应该在异常名称上使用后缀“Error”(如果异常实际上是一个错误)。

    (3)全局变量命名

    具有 from M import * 设计的模块应该使用__all__机制来防止导出全局变量,或者使用旧的将这些全局变量加上下划线作为前缀的惯例(您可能希望这样做以表明这些全局变量是“模块非公共的”)。

    (4)函数和变量命名

    函数名应该是小写的,需要用下划线分隔单词以提高可读性。变量名与函数名遵循相同的约定。

    (5)函数和方法参数

    使用 self 作为第一个参数来实例化方法。

    使用 cls 作为类方法的第一个参数

    如果函数参数的名称与保留关键字冲突,通常最好是附加一个单后置下划线,而不是使用缩写或拼写错误。因此 class_比 clss 好。(最好是使用同义词来避免这种冲突。)

    (6)方法名和实例变量

     使用函数命名规则:必须用下划线分隔单词的小写字母来提高可读性。

    仅对非公共方法和实例变量使用一个前导下划线,如_name。 

    为了避免与子类的名称冲突,使用两个前导下划线来调用 Python 的名称管理规则,如__name。

    Python 用类名来处理这些名称:如果类 Foo 有一个名为__a 的属性,Foo.__a 就不能访问它。(坚持不懈的用户仍然可以通过调用 Foo._Foo__a 获得访问权限。)通常,双前导下划线应该仅用于避免名称与设计为子类的类中的属性冲突。一般而言,属性名或方法名有两个前导下划线,那么默认是希望自己内部调用,而外部不需要调用。 

    (7)常量

    常量通常在模块级别上定义,用所有大写字母和下划线分隔单词。示例包括MAX_OVERFLOW 和 TOTAL。 

    总结:

    公共属性应该没有前导下划线。

    如果公共属性名与保留关键字冲突,则在属性名后面附加一个下划线。这比缩写或错误的拼写更可取。(然而,尽管有这个规则,“cls”是任何已知为类的变量或参数的首选拼写,特别是类方法的第一个参数)。 

    如果您的类是要被子类化的,并且您有不希望子类使用的属性,请考虑使用双前导下划线和无尾随下划线来命名它们。 

    任何向后兼容保证只适用于公共接口。

    (8)公共和内部接口

    文档化的接口被认为是公共的,所有未文档化的接口都应该假定为内部接口。 

    为了更好地支持内省,模块应该使用__all__属性显式地声明其公共 API 中的名称。将__all__设置为空列表表示该模块没有公共 API。即使正确设置了__all__,内部接口(包、模块、类、函数、属性或其他名称)仍然应该以一个前导下划线作为前缀。

    如果任何包含名称空间(包、模块或类)被认为是内部的,那么接口也被认为是内部的。

    4.编程建议

    (1)不依赖 CPython 的高效实现就地字符串连接的语句形式+ = b 或 a = a +b。这种优化即使在 CPython 中也是脆弱的(它只适用于某些类型),并且在不使用 refcount 的实现中根本不存在。在库的性能敏感部分,应该使用.join()表单。这将确保连接在各个变量之间的线性时间内发生。 

    (2)像 None 这样的单例比较操作应该使用 is 或 not 来做,永远不要用等式运算符。 

    (3)注意写 if x ,当你真正的意思 if x is not None -- e.g 测试一个默认为 None 的变量或参数是否被设置为其他值时。另一个值可能有一个类型(比如容器),在布尔上下文中可能为 false ! 

    (4)使用 is not 操作,而不是 not ... is 是多少。虽然这两个表达式在功能上是相同的,但前者更易于阅读,更受青睐。 

    Yes:
    if foo is not None:
    No:
    if not foo is None:


    (5)在实现具有丰富比较的排序操作时,最好实现所有的六个操作(__eq__、__ne__、__lt__、__le__、__gt__、__ge__),而不是依赖其他代码来执行特定的比较操作。 

    (6)始终使用 def 语句,而不是将 lambda 表达式直接绑定到标识符的赋值语句

    Yes:

    def f(x): return 2*x
    No:
    f = lambda x: 2*x

    (7)当将捕获的异常绑定到名称时,最好使用 Python 2.6 中添加的显式名称绑定语法:

    try:
      process_data()
    except Exception as exc:
      raise DataProcessingFailedError(str(exc))

    (8)对于所有 try/except 子句,将 try 子句限制为所需代码的绝对最小数量。同样,这可以避免掩盖 bug。

    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) 

    (9)上下文管理器应该通过单独的函数或方法调用,只要它们做的不是获取和释放资源:

    Yes:

    with conn.begin_transaction():
      do_stuff_in_transaction(conn)
    No:
    with conn:
      do_stuff_in_transaction(conn) 

    后一个示例没有提供任何信息来表明__enter__和__exit__方法在执行事务后关闭连接之外的其他操作。在这种情况下,明确是很重要的。 

    (10)在返回语句中保持一致。函数中的所有返回语句都应该返回表达式,或者它们都不应该返回表达式。如果任何 return 语句返回一个表达式,任何没有返回值的 return 语句都应该显式地将其声明为 return None,并且在函数末尾应该显示显式的 return 语句(如果可达的话)。

    Yes:
    def foo(x):
      if x >= 0:
        return math.sqrt(x)
      else:
        return None
    def bar(x):
      if x < 0:
        return None
      return math.sqrt(x)
    No:
    def foo(x):
      if x >= 0:
        return math.sqrt(x)
    def bar(x):
    if x < 0:
      return
    return math.sqrt(x) 

    (11)使用.startswith()和.endswith()代替字符串切片检查前缀或后缀。startswith()和 endswith()更干净,更不容易出错: 


    Yes: if foo.startswith('bar'):
    No: if foo[:3] == 'bar':


    (12)对象类型比较应该始终使用 isinstance(),而不是直接比较类型。
    Yes: if isinstance(obj, int):
    No: if type(obj) is type(1): 

    (13)当检查对象是否为字符串时,请记住它可能也是 unicode 字符串!在 Python 2中,str 和 unicode 有一个公共基类 basestring,因此您可以这样做:

    if isinstance(obj, basestring): 

    注意,在 Python 3 中,unicode 和 basestring 不再存在(只有 str), bytes对象不再是某种字符串(而是整数序列)。 


    (14)对于序列(字符串、列表、元组),使用空序列为假的事实。
    Yes: if not seq:
    if seq:

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

    (15)不要使用==将布尔值与真值或假值进行比较。

    Yes:

    if greeting:

    No:

    if greeting==True:

    Worse:

    if greeting is True:


     

     



     

  • 相关阅读:
    查询中常用的扩展方法
    加载关联表的数据 显式加载
    加载关联表的数据 延迟加载
    加载关联表的数据 贪婪加载
    操作内存中的数据
    DBContext基础查询
    EF简单增删改查
    1- MySQL数据库基础快速入门
    1-3 Postman 注册账号与登录
    1-2 postman工具简介
  • 原文地址:https://www.cnblogs.com/cymx66688/p/11260903.html
Copyright © 2020-2023  润新知