面向对象技术简介
- 类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
- 类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
- 数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。
- 方法重载:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重载。
- 实例变量:定义在方法中的变量,只作用于当前实例的类。
- 继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。
- 实例化:创建一个类的实例,类的具体对象。
- 方法:类中定义的函数。
- 对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
基本数据类型
数字:直接赋值 a,b,c,d = 20,5.5,true,complex
>>> 5 + 4 # 加法
9
>>> 4.3 - 2 # 减法
2.3
>>> 3 * 7 # 乘法
21
>>> 2 / 4 # 除法,得到一个浮点数
0.5
>>> 2 // 4 # 除法,得到一个整数
0
>>> 17 % 3 # 取余
2
>>> 2 ** 5 # 乘方
32
字符串: s = ' '
如果你不想让反斜杠发生转义,可以在字符串前面添加一个r,表示原始字符串:s = r ' '
列表: a = [ , ,' ', ]
列表中插入元素( + 其他列表) |
【list.insert(i, x)】 |
元组: a = ( , ,' ', )
虽然tuple的元素不可改变,但它可以包含可变的对象,比如list列表。
构造包含0个或1个元素的tuple是个特殊的问题,所以有一些额外的语法规则:
tup1 = () # 空元组
tup2 = (20 , ) # 一个元素,需要在元素后添加逗号
删除元祖:del a
元组索引,截取
因为元组也是一个序列,所以我们可以访问元组中的指定位置的元素,也可以截取索引中的一段元素,如下所示:
元组:
L = ('Google', 'Taobao', 'W3CSchool')
Python 表达式 |
结果 |
描述 |
L[2] |
'W3CSchool!' |
读取第三个元素 |
L[-2] |
'Taobao' |
反向读取;读取倒数第二个元素 |
L[1:] |
('Taobao', 'W3CSchool!') |
截取元素,从第二个开始后的所有元素。 |
len(tuple)
计算元组元素个数。
max(tuple)
返回元组中元素最大值。
min(tuple)
返回元组中元素最小值。
tuple(seq)
将列表转换为元组。
集合: a = { , ,' ', }
集合(set)是一个无序不重复元素的集。
基本功能是进行成员关系测试和消除重复元素。
可以使用大括号 或者 set()函数创建set集合,注意:创建一个空集合必须用 set() 而不是 { },因为{ }是用来创建一个空字典。
字典 : dic = {} 创建空字典
dic = { , ,' ': , }
字典的每个键值(key=>value)对用冒号(:)分割,每个对之间用逗号(,)分割,整个字典包括在花括号({})中 ,格式如下所示:
d = {key1 : value1, key2 : value2 }
键必须是唯一的,但值则不必。创建时如果同一个键被赋值两次,后一个值会被记住
值可以取任何数据类型,但键必须是不可变的,如字符串,数字或元组。
python运算符
Python语言支持以下类型的运算符:
Python赋值运算符
以下假设变量a为10,变量b为20:
运算符 |
描述 |
实例 |
= |
简单的赋值运算符 |
c = a + b 将 a + b 的运算结果赋值为 c |
+= |
加法赋值运算符 |
c += a 等效于 c = c + a |
-= |
减法赋值运算符 |
c -= a 等效于 c = c - a |
*= |
乘法赋值运算符 |
c *= a 等效于 c = c * a |
/= |
除法赋值运算符 |
c /= a 等效于 c = c / a |
%= |
取模赋值运算符 |
c %= a 等效于 c = c % a |
**= |
幂赋值运算符 |
c **= a 等效于 c = c ** a |
//= |
取整除赋值运算符 |
c //= a 等效于 c = c // a |
Python位运算符
& 与
| 或
^ 异或
~ 取反
<< 向左移动两位 高位丢弃,低位补0
>> 向右移动两位 高位丢弃,低位补0
Python逻辑运算(布尔运算)
and or not
Python成员运算符(在指定序列中查找数值)
in
not in
Python身份运算符(用于比较两个对象的存储单元)(是否具有相同的标识)
Is
Is not
Python运算符优先级
运算符 |
描述 |
** |
指数 (最高优先级) |
~ + - |
按位翻转, 一元加号和减号 (最后两个的方法名为 +@ 和 -@) |
* / % // |
乘,除,取模和取整除 |
+ - |
加法减法 |
>> << |
右移,左移运算符 |
& |
位 'AND' |
^ | |
位运算符 |
<= < > >= |
比较运算符 |
<> == != |
等于运算符 |
= %= /= //= -= += *= **= |
赋值运算符 |
is is not |
身份运算符 |
in not in |
成员运算符 |
not or and |
逻辑运算符 |
Python条件控制
if语句
Python中if语句的一般形式如下所示:
if condition_1:
statement_block_1
elif condition_2: 别忘记每个条件后面的冒号
statement_block_2
else:
statement_block_3
如果 "condition_1" 为 True 将执行 "statement_block_1" 块语句,如果 "condition_1" 为False,将判断 "condition_2",如果"condition_2" 为 True 将执行 "statement_block_2" 块语句,如果 "condition_2" 为False,将执行"statement_block_3"块语句。
在Python中没有switch – case语句。
循环语句格式必须严格要求整齐划一
Python循环
while 循环
Python中while语句的一般形式:
while 判断条件:
statements
continue,break 来跳过循环
continue 用于跳过该次循环,break 则是用于退出循环
For循环
for循环可以遍历任何序列的项目,如一个 列表 或者一个 字符串。
此处的序列主要指 列表 元组 字符串 文件
for <变量> in <序列>:
<statements>
else:
<statements>
break语句用于跳出当前循环体:
range() 函数
for i in range(5):
print(i)
0
1
2
3
4
指定区间:
for i in range(5,9) :
print(i)
5
6
7
8
也可以使range以指定数字开始并指定不同的增量(甚至可以是负数;有时这也叫做'步长'):
for i in range(0, 10, 3) :
print(i)
0
3
6
9
您可以结合range()和len()函数以遍历一个序列的索引,如下所示:
>>> a = ['Mary', 'had', 'a', 'little', 'lamb']
>>> for i in range(len(a)):
... print(i, a[i])
...
0 Mary
1 had
2 a
3 little
4 lamb
还可以使用range()函数来创建一个列表:
>>> list(range(5))
[0, 1, 2, 3, 4]
>>>
用len()和range()函数创造出一个统计列表字符长度的函数
a = ['Mary', 'had', 'a', 'little', 'lamb']
sum = 0
for i in range(len(a)):
sum += len(a[i])
print(sum)
Python迭代器与生成器
迭代器
迭代是Python最强大的功能之一,是访问集合元素的一种方式。。
迭代器是一个可以记住遍历的位置的对象。
迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
迭代器有两个基本的方法:iter() 和 next()。
字符串,列表或元组对象都可用于创建迭代器:
迭代器对象可以使用常规for语句进行遍历:
#!/usr/bin/python3
list=[1,2,3,4]
it = iter(list) # 创建迭代器对象
for x in it:
print (x, end=" ")
1,2,3,4
生成器
在 Python 中,使用了 yield 的函数被称为生成器(generator)。
跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。
在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回yield的值。并在下一次执行 next()方法时从当前位置继续运行。
以下实例使用 yield 实现斐波那契数列:
#!/usr/bin/python3
import sys
def fibonacci(n): # 生成器函数 - 斐波那契 n控制斐波那契数列长度
a, b, counter = 0, 1, 0
while True:
if (counter > n):
return
yield a
a, b = b, a + b
counter += 1
f = fibonacci(10) # f 是一个迭代器,由生成器返回生成
while True:
try:
print (next(f), end=" ")
except StopIteration:
sys.exit()
执行以上程序,输出结果如下:
0 1 1 2 3 5 8 13 21 34 55
Python3的函数
Python函数
def 函数名 (参数列表):
函数体
函数变量作用域
定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。
通过以下实例,你可以清楚了解Python函数变量的作用域:
关键字参数
???
返回值
Python的函数的返回值使用return语句,可以将函数作为一个值赋值给指定变量:
Return ; 即为返回空值:None
Python的数据结构
列表
Python中列表是可变的,这是它区别于字符串和元组的最重要的特点,一句话概括即:列表可以修改,而字符串和元组不能。
以下是 Python 中列表的方法:
方法 |
描述 |
list.append(x) |
把一个元素添加到列表的结尾,相当于 a[len(a):] = [x]。 |
list.extend(L) |
通过添加指定列表的所有元素来扩充列表,相当于 a[len(a):] = L。 |
list.insert(i, x) |
在指定位置插入一个元素。第一个参数是准备插入到其前面的那个元素的索引,例如 a.insert(0, x) 会插入到整个列表之前,而 a.insert(len(a), x) 相当于 a.append(x) 。 |
list.remove(x) |
删除列表中值为 x 的第一个元素。如果没有这样的元素,就会返回一个错误。 |
list.pop([i]) |
从列表的指定位置删除元素,并将其返回。如果没有指定索引,a.pop()返回最后一个元素。元素随即从列表中被删除。(方法中 i 两边的方括号表示这个参数是可选的,而不是要求你输入一对方括号,你会经常在 Python 库参考手册中遇到这样的标记。) |
list.clear() |
移除列表中的所有项,等于del a[:]。 |
list.index(x) |
返回列表中第一个值为 x 的元素的索引。如果没有匹配的元素就会返回一个错误。 |
list.count(x) |
返回 x 在列表中出现的次数。 |
list.sort() |
对列表中的元素进行排序。 |
list.reverse() |
倒排列表中的元素。 |
list.copy() |
返回列表的浅复制,等于a[:]。 |
将列表当做堆栈使用(也可以当队列实用,不过效率略低,因为在列表的最后添加或者弹出元素速度快,然而在列表里插入或者从头部弹出速度却不快(因为所有其他的元素都得一个一个地移动)
列表方法使得列表可以很方便的作为一个堆栈来使用,堆栈作为特定的数据结构,最先进入的元素最后一个被释放(后进先出)。用 append() 方法可以把一个元素添加到堆栈顶。用不指定索引的 pop() 方法可以把一个元素从堆栈顶释放出来。例如:
>>> stack = [3, 4, 5]
>>> stack.append(6)
>>> stack.append(7)
>>> stack
[3, 4, 5, 6, 7]
>>> stack.pop()
7
>>> stack
[3, 4, 5, 6]
>>> stack.pop()
6
>>> stack.pop()
5
>>> stack
[3, 4]
列表推导式
即列表内可加入for if语句进行筛选或重新计算,生成新的列表
>>> vec = [2, 4, 6]
>>> [3*x for x in vec]
[6, 12, 18]
>>> [[x, x**2] for x in vec]
[[2, 4], [4, 16], [6, 36]]
我们可以用 if 子句作为过滤器:
>>> [3*x for x in vec if x > 3]
[12, 18]
>>> [3*x for x in vec if x < 2] []
以下是一些关于循环和其它技巧的演示:
>>> vec1 = [2, 4, 6]
>>> vec2 = [4, 3, -9]
>>> [x*y for x in vec1 for y in vec2]
[8, 6, -18, 16, 12, -36, 24, 18, -54]
>>> [x+y for x in vec1 for y in vec2]
[6, 5, -7, 8, 7, -5, 10, 9, -3]
>>> [vec1[i]*vec2[i] for i in range(len(vec1))]
[8, 12, -54]
del 语句
使用 del 语句可以从一个列表中依索引而不是值来删除一个元素。这与使用 pop() 返回一个值不同。可以用 del 语句从列表中删除一个切割,或清空整个列表(我们以前介绍的方法是给该切割赋一个空列表)。例如:
>>> a = [-1, 1, 66.25, 333, 333, 1234.5]
>>> del a[0]
>>> a
[1, 66.25, 333, 333, 1234.5]
>>> del a[2:4]
>>> a
[1, 66.25, 1234.5]
>>> del a[ : ]
>>> a
[ ]
也可以用 del 删除实体变量:
>>> del a
元组和序列
元组由若干逗号分隔的值组成,例如:
>>> t = 12345, 54321, 'hello!'
>>> t[0]
12345
>>> t
(12345, 54321, 'hello!')
>>> # Tuples may be nested:
... u = t, (1, 2, 3, 4, 5)
>>> u
((12345, 54321, 'hello!'), (1, 2, 3, 4, 5))
如你所见,元组在输出时总是有括号的,以便于正确表达嵌套结构。在输入时可能有或没有括号, 不过括号通常是必须的(如果元组是更大的表达式的一部分)。
字典
另一个非常有用的 Python 内建数据类型是字典。
序列是以连续的整数为索引,与此不同的是,字典以关键字为索引,关键字可以是任意不可变类型,通常用字符串或数值。
理解字典的最佳方式是把它看做无序的键=>值对集合。在同一个字典之内,关键字必须是互不相同。
一对大括号创建一个空的字典:{ }
构造函数 dict() 直接从键值对元组列表中构建字典。如果有固定的模式,列表推导式指定特定的键值对:
>>> dict([('sape', 4139), ('guido', 4127), ('jack', 4098)])
{'sape': 4139, 'jack': 4098, 'guido': 4127}
此外,字典推导可以用来创建任意键和值的表达式词典:
>>> {x: x**2 for x in (2, 4, 6)}
{2: 4, 4: 16, 6: 36}
如果关键字只是简单的字符串,使用关键字参数指定键值对有时候更方便:
>>> dict(sape=4139, guido=4127, jack=4098)
{'sape': 4139, 'jack': 4098, 'guido': 4127}
遍历
遍历技巧
在字典中遍历时,关键字和对应的值可以使用 items() 方法同时解读出来:
>>> knights = {'gallahad': 'the pure', 'robin': 'the brave'}
>>> for k, v in knights.items():
... print(k, v)
...
gallahad the pure
robin the brave
在序列中遍历时,索引位置和对应值可以使用 enumerate() 函数同时得到:
>>> for i, v in enumerate(['tic', 'tac', 'toe']):
... print(i, v)
...
0 tic
1 tac
2 toe
同时遍历两个或更多的序列,可以使用 zip() 组合:
>>> questions = ['name', 'quest', 'favorite color']
>>> answers = ['lancelot', 'the holy grail', 'blue']
>>> for q, a in zip(questions, answers):
... print('What is your {0}? It is {1}.'.format(q, a))
...
What is your name? It is lancelot.
What is your quest? It is the holy grail.
What is your favorite color? It is blue.
要反向遍历一个序列,首先指定这个序列,然后调用 reversesd() 函数:
>>> for i in reversed(range(1, 10, 2)):
... print(i)
...
9
7
5
3
1
要按顺序遍历一个序列,使用 sorted() 函数返回一个已排序的序列,并不修改原值:
>>> basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
>>> for f in sorted(set(basket)):
... print(f)
...
apple
banana
orange
pear
Python模块
Python 模块
在前面的几个章节中我们脚本上是用python解释器来编程,如果你从Python解释器退出再进入,那么你定义的所有的方法和变量就都消失了。
为此 Python 提供了一个办法,把这些定义存放在文件中,为一些脚本或者交互式的解释器实例使用,这个文件被称为模块。
模块是一个包含所有你定义的函数和变量的文件,其后缀名是.py。模块可以被别的程序引入,以使用该模块中的函数等功能。这也是使用python标准库的方法。
Import sys
- 1、import sys引入python标准库中的sys.py模块;这是引入某一模块的方法。
- 2、sys.argv是一个包含命令行参数的列表。
- 3、sys.path包含了一个Python解释器自动查找所需模块的路径的列表。
import语句
如果要使用Python源文件,只需在另一个源文件里执行import语句,import语句语法如下:
import module1[,module2[, ... moduleN]
一个模块只会被导入一次,不管你执行了多少次import。这样可以防止导入模块被一遍又一遍地执行。
如果你打算经常使用一个函数,你可以把它赋给一个本地的名称:
>>> fib = fibo.fib
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377
from ... import语句
Python的from语句让你从模块中导入一个指定的部分到当前命名空间中,语法如下:
from modname import name1[, name2[, ... nameN]
例如,要导入模块fibo的fib函数,使用如下语句:
>>> from fibo import fib, fib2
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377
这个声明不会把整个fibo模块导入到当前的命名空间中,它只会将fibo里的fib函数引入进来。
__name__属性
一个模块被另一个程序第一次引入时,其主程序将运行。如果我们想在模块被引入时,模块中的某一程序块不执行,我们可以用__name__属性来使该程序块仅在该模块自身运行时执行。
- 每个模块都有一个__name__属性,当其值是'__main__'时,表明该模块自身在运行,否则是被引入。
- __name__ 与 __main__ 底下是双下划线,是“_ _”去掉中间的空格。
标准模块
Python 本身带着一些标准的模块库,在 Python 库参考文档中将会介绍到(就是后面的"库参考文档")。
有些模块直接被构建在解析器里,这些虽然不是一些语言内置的功能,但是他却能很高效的使用,甚至是系统级调用也没问题。
这些组件会根据不同的操作系统进行不同形式的配置,比如 winreg 这个模块就只会提供给 Windows 系统。
应该注意到这有一个特别的模块 sys ,它内置在每一个 Python 解析器中。变量 sys.ps1 和 sys.ps2 定义了主提示符和副提示符所对应的字符串:
包
包是一种管理 Python 模块命名空间的形式,采用"点模块名称"。
比如一个模块的名称是 A.B, 那么他表示一个包 A中的子模块 B 。
用户可以每次只导入一个包里面的特定模块,比如:
import sound.effects.echo
Python的输入和输出
字符串对象的 rjust() 方法, 它可以将字符串靠右, 并在左边填充空格。
str.format()
>>> print('We are the {} who say "{}!"'.format('knights', 'Ni'))
We are the knights who say "Ni!"
括号及其里面的字符 (称作格式化字段) 将会被 format() 中的参数替换。
在括号中的数字用于指向传入对象在 format() 中的位置,如下所示:
>>> print('{0} and {1}'.format('spam', 'eggs'))
spam and eggs
>>> print('{1} and {0}'.format('spam', 'eggs'))
eggs and spam
如果在 format() 中使用了关键字参数, 那么它们的值会指向使用该名字的参数。
>>> print('This {food} is {adjective}.'.format(food='spam', adjective='absolutely horrible'))
This spam is absolutely horrible.
位置及关键字参数可以任意的结合:
>>> print('The story of {0}, {1}, and {other}.'.format('Bill', 'Manfred', other='Georg'))
The story of Bill, Manfred, and Georg.
可选项 ':' 和格式标识符可以跟着字段名。 这就允许对值进行更好的格式化。 下面的例子将 Pi 保留到小数点后三位:
>>> import math
>>> print('The value of PI is approximately {0:.3f}.'.format(math.pi))
The value of PI is approximately 3.142.
在 ':' 后传入一个整数, 可以保证该域至少有这么多的宽度。 用于美化表格时很有用。
>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 7678}
>>> for name, phone in table.items():
... print('{0:10} ==> {1:10d}'.format(name, phone))
...
Jack ==> 4098
Dcab ==> 7678
Sjoerd ==> 4127
读和写文件
open() 将会返回一个 file 对象,基本语法格式如下:
open(filename, mode)
实例:
>>> f = open('/tmp/workfile', 'w')
第一个参数为要打开的文件名。
第二个参数描述文件如何使用的字符。 mode 可以是 'r' 如果文件只读, 'w' 只用于写 (如果存在同名文件则将被删除), 和 'a' 用于追加文件内容; 所写的任何数据都会被自动增加到末尾. 'r+' 同时用于读写。 mode 参数是可选的; 'r' 将是默认值。
类似于迭代,读完之后继续读会出现‘’ 重新读取应该再次open一遍
f.read()
为了读取一个文件的内容,调用 f.read(size), 这将读取一定数目的数据, 然后作为字符串或字节对象返回。
size 是一个可选的数字类型的参数。 当 size 被忽略了或者为负, 那么该文件的所有内容都将被读取并且返回。
f.readline()
f.readline() 会从文件中读取单独的一行。换行符为 '\n'。f.readline() 如果返回一个空字符串, 说明已经已经读取到最后一行。
f.readlines()
f.readlines() 将返回该文件中包含的所有行。
如果设置可选参数 sizehint, 则读取指定长度的字节, 并且将这些字节按行分割。
另一种方式是迭代一个文件对象然后读取每行:
这个方法很简单, 但是并没有提供一个很好的控制。 因为两者的处理机制不同, 最好不要混用。
f.write()
f.write(string) 将 string 写入到文件中, 然后返回写入的字符数。
如果要写入一些不是字符串的东西, 那么将需要先进行转换:
f.tell()
f.tell() 返回文件对象当前所处的位置, 它是从文件开头开始算起的字节数。
f.seek()
如果要改变文件当前的位置, 可以使用 f.seek(offset, from_what) 函数。
from_what 的值, 如果是 0 表示开头, 如果是 1 表示当前位置, 2 表示文件的结尾,例如:
- seek(x,0) : 从起始位置即文件首行首字符开始移动 x 个字符
- seek(x,1) : 表示从当前位置往后移动x个字符
- seek(-x,2):表示从文件的结尾往前移动x个字符
from_what 值为默认为0,即文件开头。下面给出一个完整的例子:
f.close()
在文本文件中 (那些打开文件的模式下没有 b 的), 只会相对于文件起始位置进行定位。
当你处理完一个文件后, 调用 f.close() 来关闭文件并释放系统的资源,如果尝试再调用该文件,则会抛出异常。
文件对象还有其他方法, 如 isatty() 和 trucate(), 但这些通常比较少用。
Python的错误和异常
语法错误
Python 的语法错误或者称之为解析错,是初学者经常碰到的,如下实例
>>> while True print('Hello world')
File "<stdin>", line 1, in ?
while True print('Hello world')
^
SyntaxError: invalid syntax
这个例子中,函数 print() 被检查到有错误,是它前面缺少了一个冒号(:)。
语法分析器指出了出错的一行,并且在最先找到的错误的位置标记了一个小小的箭头。
异常
即便Python程序的语法是正确的,在运行它的时候,也有可能发生错误。运行期检测到的错误被称为异常。
大多数的异常都不会被程序处理,都以错误信息的形式展现在这里:
>>> 10 * (1/0)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
ZeroDivisionError: division by zero
>>> 4 + spam*3
Traceback (most recent call last):
File "<stdin>", line 1, in ?
NameError: name 'spam' is not defined
>>> '2' + 2
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: Can't convert 'int' object to str implicitly
异常以不同的类型出现,这些类型都作为信息的一部分打印出来: 例子中的类型有 ZeroDivisionError,NameError 和 TypeError。
错误信息的前面部分显示了异常发生的上下文,并以调用栈的形式显示具体信息。
异常处理 try .. Expect 语句
以下例子中,让用户输入一个合法的整数,但是允许用户中断这个程序(使用 Control-C 或者操作系统提供的方法)。用户中断的信息会引发一个 KeyboardInterrupt 异常。
>>> while True:
try:
x = int(input("Please enter a number: "))
break
except ValueError:
print("Oops! That was no valid number. Try again ")
try语句按照如下方式工作;
- 首先,执行try子句(在关键字try和关键字except之间的语句)
- 如果没有异常发生,忽略except子句,try子句执行后结束。
- 如果在执行try子句的过程中发生了异常,那么try子句余下的部分将被忽略。如果异常的类型和 except 之后的名称相符,那么对应的except子句将被执行。最后执行 try 语句之后的代码。
- 如果一个异常没有与任何的except匹配,那么这个异常将会传递给上层的try中。
一个 try 语句可能包含多个except子句,分别来处理不同的特定的异常。最多只有一个分支会被执行。
处理程序将只针对对应的try子句中的异常进行处理,而不是其他的 try 的处理程序中的异常。
一个except子句可以同时处理多个异常,这些异常将被放在一个括号里成为一个元组,例如:
except (RuntimeError, TypeError, NameError):
pass
最后一个except子句可以忽略异常的名称,它将被当作通配符使用。你可以使用这种方法打印一个错误信息,然后再次把异常抛出。
import sys
try:
f = open('myfile.txt')
s = f.readline()
i = int(s.strip())
except OSError as err:
print("OS error: {0}".format(err))
except ValueError:
print("Could not convert data to an integer.")
except:
print("Unexpected error:", sys.exc_info()[0])
raise
try except 语句还有一个可选的else子句,如果使用这个子句,那么必须放在所有的except子句之后。这个子句将在try子句没有发生任何异常的时候执行。例如:
for arg in sys.argv[1:]:
try:
f = open(arg, 'r')
except IOError:
print('cannot open', arg)
else:
print(arg, 'has', len(f.readlines()), 'lines')
f.close()
使用 else 子句比把所有的语句都放在 try 子句里面要好,这样可以避免一些意想不到的、而except又没有捕获的异常。
异常处理并不仅仅处理那些直接发生在try子句中的异常,而且还能处理子句中调用的函数(甚至间接调用的函数)里抛出的异常。