目录:
异常(基础) 、 迭代器 Iterator 和 生成器 Generator 、 生成器 Generator (python 2.5及之后)
异常(基础) exception
什么是错误
错误是指由于逻辑或语法等导致一个程序无法正常执行的问题
错误的特点:
有些错误无法预知
什么是异常
异常是程序出错时标识的一种状态
当异常发生时,程序不会再向下执行,而转去调用此函数的地方待处理此错误并恢复为正常状态
异常的作用:
通知上层调用者有错误产生需要处理
用作信号
try语句的两种语法:
- try-except 语句
- try-finally 语句
try-except语句的语法:
- 例子:
try:
可能触发异常的语句
except 错误类型1 [as 变量1]:
异常处理语句1
except 错误类型2 [as 变量2]:
异常处理语句2
except (错误类型3, 错误类型4,…):
异常处理语句3
…
except:
异常处理语句other
else:
末发生异常的语句
finally:
最终语句 - 作用:
偿试捕获异常,将程序转为正常状态并继续执行 示例见:
try_except1.py:
# 此示例示意用try-except语句来捕获异常 def div_apple(n): """此示例用分苹果来示意捕获异常""" print("%d个苹果你想要分给几个人?" % n) s = input("请输入人数: ") cnt = int(s) # <-此处可能会引起ValueError类型的错误 result = n / cnt print("每个人分了", result, "个苹果") try: div_apple(10) except ValueError: print("发生了值错误,已转为正常状态") except ZeroDivisionError: print("发生了被零除的错误,苹果收回办公室") print("程序正常退出")
try_except2.py:
# 此示例示意用try-except语句来捕获异常 def div_apple(n): """此示例用分苹果来示意捕获异常""" print("%d个苹果你想要分给几个人?" % n) s = input("请输入人数: ") cnt = int(s) # <-此处可能会引起ValueError类型的错误 result = n / cnt print("每个人分了", result, "个苹果") try: div_apple(10) except (ValueError, ZeroDivisionError): # 以上两个类型的错误都会用相同的方法来处理 print("发生了错误,苹果被收回") print("程序正常退出")
try_except3.py:
# 此示例示意用try-except语句来捕获异常 def div_apple(n): """此示例用分苹果来示意捕获异常""" print("%d个苹果你想要分给几个人?" % n) s = input("请输入人数: ") cnt = int(s) # <-此处可能会引起ValueError类型的错误 result = n / cnt print("每个人分了", result, "个苹果") try: div_apple(10) except ValueError: print("发生了值错误,苹果被收回") except: print("发生了除了值错误以外的错误,在此处处理") print("程序正常退出")
try_except_as.py:
# 此示例示意用try-except语句来捕获异常 def div_apple(n): """此示例用分苹果来示意捕获异常""" print("%d个苹果你想要分给几个人?" % n) s = input("请输入人数: ") cnt = int(s) # <-此处可能会引起ValueError类型的错误 result = n / cnt print("每个人分了", result, "个苹果") try: div_apple(10) except ValueError as err: print("发生了值错误,苹果被收回") print("错误的值是:", err) print("程序正常退出")
try_except_else.py:
# 此示例示意用try-except语句来捕获异常 def div_apple(n): """此示例用分苹果来示意捕获异常""" print("%d个苹果你想要分给几个人?" % n) s = input("请输入人数: ") cnt = int(s) # <-此处可能会引起ValueError类型的错误 result = n / cnt print("每个人分了", result, "个苹果") try: div_apple(10) except ValueError: print("发生了值错误,苹果被收回") else: # 此处语句只在没有发生异常时才会执行 print("没有发生错误,苹果分完了") print("程序正常退出")
try_except_else_finally.py:
此示例示意用try-except语句来捕获异常 def div_apple(n): """此示例用分苹果来示意捕获异常""" print("%d个苹果你想要分给几个人?" % n) s = input("请输入人数: ") cnt = int(s) # <-此处可能会引起ValueError类型的错误 result = n / cnt print("每个人分了", result, "个苹果") try: div_apple(10) except ValueError: print("发生了值错误,苹果被收回") else: # 此处语句只在没有发生异常时才会执行 print("没有发生错误,苹果分完了") finally: # 此子句内的语句无论是否发生异常都一定会执行 print("我一定会执行的!!!!") print("程序正常退出")
练习:
写一个函数 get_score() 来获取用户输入的学生成绩(0~100的整数),如果输入出现错误,则此函数返回0,如果用户输入的数是0~100之间的数,返回这个数def get_score():
…score = get_score()
print(‘学生的成绩是:’, score)
5, try-except语句语法说明:
1. as 子句是用于绑定错误对象的变量,可以省略
2. except 子句可以有一个或多个,但至少要有一个
3. else子句最多只能有一个,也可以省略
4. finally子句最多只能有一个,也可以省略
try-finally 语句
语法:
try:
可能触发异常的语句
finally:
最终语句语法说明:
finally 子句不可以省略
一定不存在except 子句作用:
通常用try-finally 语句来做触发异常时必须要处理的事件,无论异常是否发生,finally 子句都会被执行
注:
try-finally 语句不会改变程序的(正常/异常)状态
raise 语句(类似java throw 向上抛出错误):
- 作用:
触发一个错误,让程序进入异常状态 - 语法:
raise 异常类型
或
raise 异常对象 示例见:
没有使用raise示例:
# 此示例示意raise语句的用法 # 以下示意其它语言中不用异常机制,用返回值方式返回错误问题 def make_except(n): # 假设n必须是 0~100之间的数 print("begin...") if n > 100: # 传过的来参数无效,怎么告诉调用者呢? return -1 if n < 0: return -2 print("end") return 0 value = int(input("请输入一个整数:")) r = make_except(value) if r < 0: print("发生错误") else: print("程序正常完成")
使用raise示例:
# 此示例示意raise语句的用法 def make_except(n): # 假设n必须是 0~100之间的数 print("begin...") if n > 100: # 传过的来参数无效,怎么告诉调用者呢? raise ValueError if n < 0: raise ValueError("参数小于零错误:%d" % n) print("end") value = int(input("请输入一个整数:")) try: make_except(value) except ValueError as e: # print("make_except 抛出了错误,此异常状态已处理") # print("错误的值是:", e) print("发生错误") print("程序正常完成")
assert 语句(断言语句) 类似java抛出runtimeException 简化版本
- 语法
assert 真值表达式, 错误数据(通常是字符串) - 作用:
当真值表达式为False时,用错误数据创建一个AssertionError类型的错误,并进入异常状态
等同于:
if 真值表达式 == False:
raise AssertionError(错误数据) 示例见:
def get_age(): a = input("请输入年龄:") a = int(a) assert a < 140, "年龄不可能大于140!!!" assert a >= 0, "年龄不可能出现负数!!!" return a try: age = get_age() except AssertionError as err: print("发生了断言错误!错误对象是:", err) age = 0 # 做相应的处理 print("您输入的年龄是: ", age)
为什么要用异常处理机制:
在程序调用层数较深时,向主调函数传递错误信息需要层层的 return 返回比较麻烦,所以用异常处理机制
示例:
def f1(): print("开始盖房子打地基...") return -1 # -1 代表挖出文物 print("地基完工") return 0 def f2(): print("开始盖房子地面以上部分") return -2 # -2 代表要建高压线 print("房子完工") def f3(): """第二承包商打人干活""" r = f1() if r < 0: return r else: r2 = f2() return r2 def build_house(): r = f3() if r < 0: return r return 0 r = build_house() if r == 0: print("房子盖好了") elif r == -1: print("房子没盖成,因为文物问题") elif r == -2: print("房子没盖成,因为高压线问题")
def f1():
print("开始盖房子打地基...")
raise ValueError("挖出文物")
print("地基完工")
def f2():
print("开始盖房子地面以上部分")
raise ZeroDivisionError("要建高压线")
print("房子完工")
def f3():
"""第二承包商打人干活"""
f1()
f2()
def build_house():
f3()
try:
build_house()
except ValueError as err:
print("房子没盖成,因为", err)
except ZeroDivisionError as err:
print("房子没盖成,因为", err)
else:
print("房子盖好了")
练习:
一个球从100米高度落下,每次落地后反弹高度为原高度的一半,再落下,
1) 写程序算出皮球从第10次落地后反弹高度是多少?
2) 球共经过多少米路径?打印九九乘法表:
1x1=1
1x2=2 2x2=4
1x3=3 2x3=6 3x3=9
…..
1x9=9 2x9=18 …….. 9x9=81分解质因数:
输入一个正整数,分解质因数:
如输入: 90 则打印:
90 = 2*3*3*5
(质因数是指最小能被原数整除的素数(不包含1))
迭代器 Iterator
什么是迭代器:
- 迭代器是访问可迭代对象的一种方式,用迭代器可以访问可迭代对象
- 迭代器是指iter(可迭代对象) 返回的对象
- 迭代器可以用next(it) 函数获取可迭代对象的数据
迭代器函数iter和next
- iter(iterable) 从可迭代对象中返回一个迭代器,iterable必须是能提供一个迭代器的对象
- next(iterator) 从迭代器iterator中获取下一个记录。如果无法获取下一条记录,则触发StopIterator异常
迭代器说明:
- 迭代器只能往前取值,不会后退
- 用iter函数可以返回一个可迭代对象的迭代器
示例:
# iterator.py L = [2, 3, 5, 7] # 用for循环来访问可迭代对象中的数据 for x in L: print(x) print('-------------------------') # 用while循环能否访问可迭代对象中的数据? # 第一步,让L给我们一个迭代器 it = iter(L) # 第二步,循环用it迭代器去获取L中的数据, # 直到StopIteration为止 while True: try: x = next(it) print(x) except StopIteration: break
练习:
已知有一个集合:
s = {“工商银行”, “建设银行”, “中国银行”, “农业银行”}
1. 用for 语句遍历集合中的元素并打印
2. 将上面的for 语句改写为while语句实现上面同样的功能
提示: 用iter和next 函数实现
生成器 generator (python 2.5及之后版本)
什么是生成器:
- 生成器是能够动态提供数据的对象,生成器对象也是可迭代对象
生成器有两种:
- 生成器函数
- 生成器表达式
生成器函数定义:
- 含有yield语句的函数是生成器函数,此函数被调用将返回一个生成器对象
yield 翻译为(产生或生成) yield语句
- 语法:
yield 表达式 - 说明:
- yield 用于def函数中,目的是将此函数作为生成器函数使用
- yield 用来生成数据,供next(it)函数使用
- 语法:
示例见:
def myyield(): yield 2 yield 3 yield 5 yield 7 print("生成器函数调用结束") gen = myyield() print(gen) # gen绑定生成器对象,此对象为可迭代对象 for x in gen: print(x) # it = iter(gen) # 返回迭代器 # x = next(it) # print(x) # print(next(it))
def myyield(): print("即将生成2") yield 2 print("即将生成3") yield 3 print("即将生成5") yield 5 print("即将生成7") yield 7 print("生成器函数调用结束") gen = myyield() it = iter(gen) print(next(it)) print(next(it)) # myyield将从上一次停止的位置开始执行
高级示例:
# 写一个生成器函数my_integer(n)生成 1 到 n的整数: def my_integer(n): i = 1 # 先初始化变量i将其设置为起始数 while i < n:#循环判断是否已到终止点,如果未到则生成 yield i # 生成整数 i += 1 # 控制循环条件 for x in my_integer(5): print(x) # 1 2 3 4
练习:
写入一个生成器函数, myodd(start, stop) 用于生成start开始到stop结束(不包含stop)的所有奇数L = [x for x in myodd(1, 10)]
print(L) # [1,3,5,7,9]
for x in myodd(10, 20):
print(x) # 11, 13, 15, 17, 19
生成器表达式:
语法:
(表达式 for 变量 in 可迭代对象 [if 真值表达式])
注: [] 内的if部分可以省略作用:
用推导式形式生成一个新的生成器- 示例:
gen = (x**2 for x in range(1, 5))
it = iter(gen)
next(it) # 1
next(it) # 4
next(it) # 9
next(it) # 16
next(it) # StopIteration
迭代工具函数:
- 迭代工具函数的作用是生成一个个性化的可迭代对象
- zip(iter1[, iter2, …]) 返回一个zip对象,此对象用于生成一个元组,此元组的个数是由最小的可迭代对象决定,元组内容是可迭代对象iter1和iter2中元素的组合
- enumerate(iterable[,start]) 生成带索引的枚举对象,返回的迭代类型为索引-值对(index-value)对,默认索引从零开始,也可以用start指定
示例见:
zip.py:
# 此示例示意zip函数的用法: numbers = [10086, 10000, 10010, 95588] name = ['中国移动', '中国电信', '中国联通'] for t in zip(numbers, name): print(t)
myzip.py:
# 此示例来示意zip函数的内部实现方法 def myzip(iter1, iter2): it1 = iter(iter1) it2 = iter(iter2) try: while True: a = next(it1) b = next(it2) yield (a, b) except: pass numbers = [10086, 10000, 10010, 95588] name = ['中国移动', '中国电信', '中国联通'] for t in myzip(numbers, name): print(t)
zip2.py:
# 此示例示意zip函数的用法: numbers = [10086, 10000, 10010, 95588] name = ['中国移动', '中国电信', '中国联通'] for t in zip(range(1, 10000), numbers, name): print(t)
enumerate.py:
# 此示例示意enumerate的用法 names = ['中国移动', '中国电信', '中国联通'] for t in enumerate(names, 10): print(t)
练习:
写一个程序,读入任意行的文字数据,当输入空行时结束输入
打印带有行号的输入结果:
如:
请输入: hello<回车>
请输入: home<回车>
请输入: bye<回车>
请输入: <回车>
输出如下:
第1行: hello
第2行: home
第3行: bye
字节串
作用:
存储以字节为单位的数据
说明:
字节串是不可改变的序列
字节是 0~255之间的整数
使用:
- 创建空的字节串的字面值
b”
b””
b”””
b”“”“”“ - 创建非空的字节串的字面值:
B = b’hello’
B = b”Hello”
B = b”’abcd”’
B = b”“”abcd”“”
B = b’abc\n123’
B = b’\x41\x42’
b’\x16\x0d\x0d\x0a’
字节串的构造函数 bytes
bytes() 生成一个空的字节串 等同于b”
bytes(整数可迭代对象) 用可迭代对象初始化一个字节串
bytes(整数n) 生成n个值为0的字节串
bytes(字符串, encoding=’utf-8’) 用字符串的转换编码生成一个字节串
bytes 的运算:
+ += * *=
< <= > >= == !=
in / not in
索引和切片
in / not in 示例:
B = b’ABCDE’
0x41 in B # True
用于序列的函数:
len, max, min, sum, any, all 都可用于字节串
序列的方法:
详见:
>>> help(bytes)
bytes与 str的区别:
bytes 存储字节(0~255)
str 存储字符(Unicode值)
bytes 与 str转换
编码(encode)
str ----> bytes
b = s.encode(encoding='utf-8')
解码(decode)
bytes ----> str
s = b.decode(encoding='utf-8')
- 例:
b = "你好".encode('utf-8')
print(b)
s = b.decode('utf-8')
print(s)
字节数组 bytearray
可变的字节序列
创建函数 bytearray
- bytearray() 创建空的字节串
- bytearray(整数)
- bytearray(整型可迭代对象)
- bytearray(字符串, encode=’utf-8’)
操作:
- 常规操作
+ += * *=
< <= > >= == !=
in / not in
索引 index / 切片 slice
(字节数组可以索引和切片赋值,赋值规则同列表的索引和切片赋值相同) 例:
ba = bytearray(b’abcdefg’)
ba[0] = 0x41 # ba = bytearray(b’Abcdefg’)
ba[1::2] = bytearray(b’BDF’) # 修改bdf为大写bytearray 的方法:
BA代表bytearray
BA.clear() 清空字节数组
BA.append(n) 追加一个字节(n为0~255的整数)
BA.remove(value) 删除第1个出现的字节,如果没有出现,则触发ValueError错误
BA.reverse() 字节的顺序反转
BA.decode(encoding=’utf-8’) 将bytearray转换为字符串
BA.find(sub[, start[, end]]) 查找sub 子节数数组练习:
用生成器函数生成斐波那契数列的前n个数:
1 1 2 3 5 8 13 ….def fibonacci(n):
…
yield ..
1) 输出前 20 个数
2) 求前 30 个数的和写程序打印杨辉三角(只打印6层)
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1