前面介绍了Python基础和内置的数据类型,本文关注程序结构与控制流。
3. 流程控制
变量除了赋值语句,再加上条件判断和循环才有真正的使用价值。 条件判断用if、else和elif来控制,循环用while,这和许多高级语言一样,只是Python用空格而不是花括号来表示层次。
def debug: #Python参考手册中的例子 def square(x): if not isinstance(x,int): raise TypeError('应当是一个整数') return x * x else: def square(x): return x * x
在Python中,for是比while更强大的循环机制,while可能用得不多。for语句仅适用于可支持迭代的对象,如内置的序列类型和迭代器协议的对象。在for i in s中,变量i称为迭代变量,其并非for语句私有,它能改变相同名称的变量,也在循环结束后保留最后一个值。另外,许多简单的for循环都可以转换成列表解析。enumerate()函数可以帮助我们同时获取迭代和计数,其返回值是一个元组(0,s[0])、(1,s[1])等,例如在Django的model定义时,
STATUS_CHOICES = enumerate(s) class Name(models.Model): status = models.IntergerField(chices=STATUS_CHOICES) #s中元素顺序保存为0,1,……
用pass语句表示不执行任何操作,仅占位;break语句可跳出循环,例如读取文件;continue语句跳过本次循环,执行下一次循环;如果需要跳出多层嵌套循环,可以使用异常。Python中没有goto语句(谢天谢地!)。在for循环中也可以使用else,它只在循环结束后才执行,如果break终止了循环,则跳过else语句,这样就可以使用一些特征标志来记录这个状态。
for line in open('codesite.txt'): stripped = line.strip()#去除头尾空格换行等字符 if not stripped: break else: raise RuntimeError('Missing section separator')
4. 异常处理
异常主要意味着错误,但也可能只是警告,或者用于通知上层调用函数,如推出循环等。如果运行时发生异常,解释器会查找相应的处理语句,逐步向外层找。Python中用raise Exception([value])可以引发异常,用try和except捕捉异常。
try-except语句:
try: f = open('codesite', 'r') except IOError as e:#可选修饰符as var,提供给raise的异常类型实例 erro_log.write('Unable to open codesite: %s\n' % e) else: #else(可选)必须跟在最后一个except后面,如果无异常则执行else中代码 data = d.read() f.close() finally: #(可选)无论是否发生异常,都执行此操作 f.close
可以有多个except语句,处理不同异常下的操作。如果某些异常的操作相同,还可以用 except (IOError, TypeError, NameError) as e的形式。
raise抛出异常:例如在库里面创建的API调用需要传入一个正整数,这时候就可以检查并适时抛出异常,raise TypeError或ValueError.
常见的异常如下:
AssertionError | 由assert语句引发 |
AttributeError | 属性名称失效 |
IOError | I/O异常,一般是无法打开文件 |
ImportError | 无法导入模块或包,一般是路径问题 |
IndentationError | 语法错误,没有正确对齐 |
IndexError | 索引超出序列边界 |
KeyError | 访问不存在的字典键 |
KeyboardError | 按下了Ctrl+C |
NameError | 无法找到名称,即使用了一个还未赋予对象的变量 |
SyntaxError | 代码解析错误 |
TypeError | 传递错误的类型 |
UnboundLocalError | 未绑定的局域变量,一般是另一个同名全局变量在 |
ValueError | 传入了一个不期望的值 |
定义新异常:要定义新异常要以Exception为父类,还可以设计层次化的异常。但是Django中大多数异常都是内部处理的,只有少部分如HTTP404是直接使用的。
其他相关的控制流:上下文管理器with语句,程序调试assert语句