当前位置 : 主页 > 编程语言 > python >

编写高质量代码——改善Python程序的91个建议(Ⅲ)

来源:互联网 收集:自由互联 发布时间:2022-06-24
建议19:有节制地使用from…import语句 一般情况下尽量优先使用imort a形式。 有节制使用from a import B形式。 尽量避免使用from a import *,因为这回污染命名空间。 当只需要导入部分属性或
  • 建议19:有节制地使用from…import语句
  • 一般情况下尽量优先使用imort a形式。
  • 有节制使用from a import B形式。
  • 尽量避免使用from a import *,因为这回污染命名空间。
  • 当只需要导入部分属性或者方法时。
  • 模块中的这些属性和方法访问效率较高导致使用“模块名.名称”的形式进行访问过于繁琐时。
  • 模块的文档明确说明需要使用from…import形式,导入的是一个包下面的子模块,且使用from…import形式能够更为简单和便利时。

  • 建议20:优先使用absolute import来导入模块(忽略)
    relative improt 在python3中已经移除。
  • 建议21:i+=1 不等于 ++i
  • “+”仅代表符号为正。
    编写高质量代码——改善Python程序的91个建议(Ⅲ)_默认参数
  • 建议22:使用with自动关闭资源
  • with语句支持嵌套。
with expr1 as e1:
with expr2 as e2:
pass
  • with语句能够保证当写操作执行完毕后自动关闭文件。
  • 含有with语句的代码块的执行过程如下:
  • 计算表达式的值,返回一个上下文管理器对象。
  • 加载上下文管理器对象的__exit__()方法以备后用。
  • 调用上下文管理器对象的__enter__()方法。
  • 如果with语句中设置了目标对象,则将__enter__()方法的返回值赋值给目标对象。
  • 执行with中的代码块。
  • 如果步骤5中的代码正常结束,调用上下文管理器对象的__exit__()方法,其返回值直接忽略。
  • 如果步骤5中的代码执行过程中发生异常,调用上下文管理器对象的__exit__()方法,并将异常类型、值及traceback信息作为参数传递给__exit__() 方法。如果__exit__() 返回值为false,则异常会被重新抛出;如果其返回值为true,异常会被挂起,程序继续执行。
  • 因为上下文管理器主要作用是资源共享,因此在实际应用中__enter__()和__exit__()方法基本用于资源分配以及释放相关的工作,如打开/关闭文件、异常处理、断开流的连接、锁分配等。
  • 建议23:使用else子句简化循环(异常处理)
  • 循环:当循环是自然终结时else从句会被执行一次,而当循环是由break语句中断时,else语句不会执行。
  • 异常处理:try块没有抛出任何异常时,执行else块。
  • 建议24:遵循异常处理的几点基本原则
  • 注意异常的粒度不推荐在try中放置过多的代码。
  • 谨慎使用单独的except语句处理所有异常。
  • 注意异常捕获的顺序。
  • 使用更为友好的异常信息,遵守异常参数的规范。
  • 建议25:避免finally中肯发生的陷阱
  • 当try块中发生异常的时候,如果在except中找不到对应的异常处理,异常将被临时保存起来,当finally执行完毕时,临时保存的异常将会再次被抛出来,但如果finally语句中产生了新的异常或者执行了return或者break语句,那么临时保存的异常将会被丢失。
  • 建议26:深入理解None,正确判断对象是否为空
  • python中以下数据会当做空来处理:
  • None(NoneType)
  • False
  • 任何形式的数值类型零
  • 空的序列
  • 空的字典
  • [] 不为 None
  • if list is not None:会调用内部方法__nonzero__()来判断变量list是否为空。
  • 建议27:连接字符串优先使用join而不是+
>>> str1, str2, str3 = "a", "b", "c"
>>> ''.join([str1, str2, str3])
>>> abc
  • join()效率高于"+"
  • 建议28:格式化字符串时尽量使用.format方式而不是%
  • %[ 转换标记][ 宽度][ .精确度] 转换类型。
  • .format方式格式化字符串的基本语法为:[[ 填充符] 对齐方式[ 符号][ #][ 0][ 宽度][ ,][ .精确度][ 转换类型]]
  • format方式在使用上较%操作符更为灵活。使用format方式时,参数的顺序与格式化的顺序不必完全相同。
  • format方式可以方便地作为参数传递。
  • %最终会被.format方式所代替。
  • %方法在某些特殊情况下使用时需要特别小心(比如输出元组时)
  • 建议29:区别对待可变对象和不可变对象
  • 数字、字符串、元组属于不可变对象。
  • 字典以及列表、字节数组属于可变对象。
  • 可变对象作为函数默认参数的时候要特别警惕可变对象的更改会直接影响原对象。
  • 注意深拷贝和浅拷贝(切片操作属于浅拷贝)
  • 建议30:列表解析式
  • [ expr for iter_item in iterable if cond_expr] 它迭代iterable中的每一个元素当条件满足的时候便根据表达式expr计算的内容生成一个元素并放入新的列表中,以此类推,并最终返回整个列表,expr可以是复杂表达式、函数,iterable可以是任意可迭代对象。
  • 使用列表解析更为直观清晰,代码更为简洁。
  • 列表解析的效率更高。
  • 建议31:函数传参既不是传值也不是传引用
    给数据贴上标签
  • 建议32:警惕默认参数潜在的问题
  • 如果不想默认参数所指向的对象在所有的函数调用中被共享,而是在函数调用的过程中动态生成,可以在定义的时候使用None对象作为占位符。
  • 建议33:慎用变长参数
  • 使用过于灵活。function(*args, **kwargs)调用方式过于灵活。
  • 如果一个函数的参数列表很长,虽然可以通过*args, **kwargs来简化函数定义,但是通常都可以被重构。比如先用一个序列来整合参数,在函数定义中传入这个序列即可。
  • 建议34:深入理解str()和repr()的区别
    详细请看《编写高质量代码 改善Python程序的91个建议》P80内容
  • 两者的目标不同。str()主要面向用户,其目的是可读性,返回形式用户友好性和可读性都较强的字符串类型;repr()面向的是python解释器,其目的是准确性,通常为编程人员debug用途。
  • 在解释器中直接输入a时默认调用repr()函数,而print(a)则调用str()函数。
  • repr()的返回值一般可以用eval()函数来还原对象。
  • 建议35:分清staticmethod和classmethod的使用场景
    *看不懂,忽略

- 《编写高质量代码 改善Python程序的91个建议》张颖 赖勇浩 著。


网友评论