- Preface 前言
- 第1章 引论
- 第2章 编程惯用法
- 第3章 基础语法
- 建议19:有节制地使用 from…import 语句
- 建议20:优先使用 absolute import 来导入模块
- 建议21:i+=1 不等于 ++i
- 建议22:使用 with 自动关闭资源
- 建议23:使用 else 子句简化循环(异常处理)
- 建议24:遵循异常处理的几点基本原则
- 建议25:避免 finally 中可能发生的陷阱
- 建议26:深入理解 None 正确判断对象是否为空
- 建议27:连接字符串应优先使用 join 而不是 +
- 建议28:格式化字符串时尽量使用 .format 方式而不是 %
- 建议29:区别对待可变对象和不可变对象
- 建议30:[]、() 和 {}:一致的容器初始化形式
- 建议31:记住函数传参既不是传值也不是传引用
- 建议32:警惕默认参数潜在的问题
- 建议33:慎用变长参数
- 建议34:深入理解 str() 和 repr() 的区别
- 建议35:分清 staticmethod 和 classmethod 的适用场景
- 第4章 库
- 建议36:掌握字符串的基本用法
- 建议37:按需选择 sort() 或者 sorted()
- 建议38:使用 copy 模块深拷贝对象
- 建议39:使用 Counter 进行计数统计
- 建议40:深入掌握 ConfigParser
- 建议41:使用 argparse 处理命令行参数
- 建议42:使用 pandas 处理大型 CSV 文件
- 建议43:一般情况使用 ElementTree 解析 XML
- 建议44:理解模块 pickle 优劣
- 建议45:序列化的另一个不错的选择 JSON
- 建议46:使用 traceback 获取栈信息
- 建议47:使用 logging 记录日志信息
- 建议48:使用 threading 模块编写多线程程序
- 建议49:使用 Queue 使多线程编程更安全
- 第5章 设计模式
- 第6章 内部机制
- 建议54:理解 built-in objects
- 建议55:init() 不是构造方法
- 建议56:理解名字查找机制
- 建议57:为什么需要 self 参数
- 建议58:理解 MRO 与多继承
- 建议59:理解描述符机制
- 建议60:区别 getattr() 和 getattribute() 方法
- 建议61:使用更为安全的 property
- 建议62:掌握 metaclass
- 建议63:熟悉 Python 对象协议
- 建议64:利用操作符重载实现中缀语法
- 建议65:熟悉 Python 的迭代器协议
- 建议66:熟悉 Python 的生成器
- 建议67:基于生成器的协程及 greenlet
- 建议68:理解 GIL 的局限性
- 建议69:对象的管理与垃圾回收
- 第7章 使用工具辅助项目开发
- 第8章 性能剖析与优化
建议23:使用 else 子句简化循环(异常处理)
有其他编程语言经验的程序员接触到Python时,对于它无所不在的else往往感到非常惊讶。在Python中,不仅分支语句有else子句,而且循环语句也有,甚至连异常处理也有。首先来看看循环语句中的else,看看它们的语法。
while_stmt ::= "while" expression ":" suite ["else" ":" suite] for_stmt ::= "for" target_list "in" expression_list ":" suite ["else" ":" suite]
从语法定义中可以看到如果没有["else" ":" suite]这一块,Python的循环语句跟大多数语言并无二致。要谈else子句,必须先从Python从其他语言中借鉴的语义相同的break语句说起,因为else子句提供了隐含的对循环是否由break语句引发循环结束的判断。先来看一个没有应用else子句的例子:
def print_prime(n): for i in xrange(2, n): found = True for j in xrange(2, i): if i % j == 0: found = False break if found: print '%d is a prime number'%i
这是一个查找素数的简单实现,可以看到我们借助了一个标志量found来判断是循环结束是不是由break语句引起的。如果对else善加利用,代码可以简洁得多。来看下面的具体实现:
def print_prime2(n): for i in xrange(2, n): for j in xrange(2, i): if i % j == 0: break else: print '%d is a prime number'%i
当循环“自然”终结(循环条件为假)时else从句会被执行一次,而当循环是由break语句中断时,else子句就不被执行。与for语句相似,while语句中的else子句的语意是一样的:else块在循环正常结束和循环条件不成立时被执行。
与C/C++等较为“老土”的语言相比,else子句使程序员的生产力和代码的可读性都得到了提高,所以建议大家多使用else,让程序变得更加Pythonic。
在Python的异常处理中,也提供了else子句语法,这颗“语法糖”的意义跟循环语句中的else是相似的:try块没有抛出任何异常时,执行else块。按惯例先看一下如下语法定义:
try_stmt ::= try1_stmt | try2_stmt try1_stmt ::= "try" ":" suite ("except" [expression [("as" | ",") target]] ":" suite)+ ["else" ":" suite] ["finally" ":" suite] try2_stmt ::= "try" ":" suite "finally" ":" suite
从try1_stmt的定义中可以看到,Python的异常处理中有一种try-except-else-finally形式。下面的例子是把数据写入文件中。
def save(db, obj): try: # save attr1 db.execute('a sql stmt', obj.attr1) # save attr2 db.execute('another sql stmt', obj.attr2) except DBError: db.rollback() else: db.commit()
如果没有else子句,就像前文中关于循环的例子一样,需要引入一个标志变量。
def save(db, obj): some_error_occurred = False try: # save attr1 db.execute('a sql stmt', obj.attr1) # save attr2 db.execute('another sql stmt', obj.attr2) except DBError: db.rollback() some_error_occurred = True if not some_error_occurred: db.commit()
这样代码就变得复杂了。在Python中还有不少语法都是致力于让程序员可以编写更加简明、更接近自然语言语义的代码,比如in和with语句(将在其他章中讲述相关用法),这也证明充分地学习手册中的Language Reference非常有必要。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论