2018.7.20
day14回顾
异常:
- 错误
- 异常
四条语句:
- try-except 语句
- try-finally 语句
- raise 语句
- assert 语句
day15
迭代器 Iterator
什么是迭代器
1,迭代器是访问可迭代对象的工具
2,迭代器是指用iter(obj)函数 返回的对象(实例)
3,迭代器可以用next(it)函数获取可迭代对象的数据
迭代器函数iter iter和next
1,iter(iterable)从可迭代对象中返回一个迭代器,iterable必须是能提供一个迭代器的对象
2,next(iterator)从迭代器iterator中获取下一个记录,如果无法获取下一条记录,则触发StopIterator异常
说明:
1,迭代器只能向前取值,不会后退
2,用iter 函数可以返回一个可迭代对象的迭代器
作用:
迭代器对象能用next函数获取下一个元素
示例:
L = [2, 3, 5, 7]
it = iter(L) # 用L对象返回能访问L的迭代器, it绑定迭代器
next(it) # 2
next(it) # 3
next(it) # 5
next(it) # 7
next(it) # StopIteration 通知(没有数据)
it = iter(range(1, 10, 30))
next(it) # 1
next(it) # 4
next(it) # 7
next(it) # StopIteration
用迭代器访问可迭代对象示例:
L = [2, 3, 5, 7]
# 用for循环来访问可迭代对象中的数据
# for x in L:
# print(x)
# else:
# print('循环结束')
# 用while循环能否访问可迭代对象中的数据?
# 第一步,让L给我们一个迭代器
it = iter(L)
# # 第二步,循环用it迭代器去获取L中的数据,
# # 直到StopIteration为止
while True:
try:
x = next(it)
print(x)
except StopIteration:
print('循环结束')
break
练习:
有一个集合:s={'唐僧','悟空','八戒','沙僧'}
用for语句和while语句来遍历:
s={'唐僧','悟空','八戒','沙僧'}
# for x in s:
# print(x)
# else:
# print('遍历结束')
it=iter(s)
#把try语句放在while前面,当触发try直接结束,无需break
try:
while True:
b=next(it)
print(b)
except StopIteration:
print('遍历结束')
生成器 generator (python 2.5及之后版本)
什么是生成器:
生成器是能够动态提供数据的对象,生成器对象也是可迭代对象(实例)
生成器有两种:
1,生成器函数
2,生成器表达式
生成器函数的定义:
含有yield语句的函数是生成器函数,此函数被调用将返回一个生成器对象,yield 翻译为(产生或生成) yield语句
语法:
yield 表达式
说明:
yield 用于def函数中,目的是将此函数作为生成器函数使用
yield 用来生成数据,供next(it)函数使用
示例1:
def myyield():
yield 2
yield 3
yield 5
yield 7
print("生成结束")
for x in myyield():
print(x) # 请问打印什么?
示例2:
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将从上一次停止的位置开始执行
生成器函数说明:
生成器函数的调用将返回一个生成器对象,生成器对象是一个可迭代对象
在生成器函数调用return 会触发一个StopIteration异常
高级示例:
def my_integer(n):
i = 0 # 先初始化变量i将其设置为起始数
while i < n:#循环判断是否已到终止点,如果未到则生成
yield i # 生成整数
i += 1 # 控制循环条件
for x in my_integer(5):
print(x) # 0 1 2 3 4
练习:
写一个生成器函数 myeven(start,stop)
此函数用来生成从start开始到stop结束(不包含)区间内的一系列偶数
答案:
def myeven(start, stop):
# L = [x for x in range(start, stop) if x % 2 == 0]
# return L #可以用生成器表达式,直接就ok
x = start
while x < stop:
if x % 2 == 0:
yield x
x += 1
evens = list(myeven(10, 20))
print(evens) # [10, 12, 14, 16, 18]
for x in myeven(21, 30):
print(x) # 22, 24, 26, 28
L = [x**2 for x in myeven(3, 10)]
print(L) # 16 36 64
生成器表达式:
语法:
(表达式 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
练习:
已知有一个列表L,L=[2,3,5,7]
用生成器表达式从此列表中拿到数据,生成列表中数据的平方
L = [2, 3, 5, 7]
# gen = (x ** 2 for x in L)
def mygen(lst):
for x in lst:
yield x ** 2
gen = mygen(L)
L2 = list(gen) # L2 = [4, 9, 25, 49]
print(L2)
思考:
L = [2, 3, 5, 7]
L2 = [x ** 2 for x in L] # 列表推导式
it = iter(L2)
print(next(it)) # 4
L[1] = 10
print(next(it)) # 9
L = [2, 3, 5, 7]
G3 = (x ** 2 for x in L) # 生成器表达式
it = iter(G3)
print(next(it)) # 4
L[1] = 10
print(next(it)) # 100
迭代工具函数:
迭代工具函数的作用是生成一个个性化的可迭代对象
函数:
- zip(iter1[, iter2, …]) 返回一个zip对象,此对象用于生成一个元组,此元组的个数是由最小的可迭代对象决定,元组内容是可迭代对象iter1和iter2中元素的组合
- enumerate(iterable[,start]) 生成带索引的枚举对象,返回的迭代类型为索引-值对(index-value)对,默认索引从零开始,也可以用start指定
示例:
1, zip.py:
numbers = [10086, 10000, 10010, 9558]
names = ['中国移动', '中国电信', '中国联通']
for t in zip(numbers, names):
print(t)
for x, y in zip(numbers, names):
print(y, '的客服电话是:', x)
x, y = (10086, '中国移动') # 序列
2,myzip.py:
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)
3,zip2.py:
numbers = [10086, 10000, 10010, 95588]
name = ['中国移动', '中国电信', '中国联通']
for t in zip(range(1, 10000), numbers, name):
print(t)
4,enumerate.py:
# 此示例示意enumerate的用法
names = ['中国移动', '中国电信', '中国联通']
for t in enumerate(names, 10):
print(t)
5,enumerate 实现方法示意:
def myenum(iterable):
t = iter(iterable)
i = 0
while True:
a = next(it)
yield (i, a)
i += 1
练习:
写一个程序,读入任意行的文字,当输入空行时结束输入,打印带有行号的输入结果:
如:
请输入: hello<回车>
请输入: world<回车>
请输入: tarena<回车>
请输入: <回车>
输出如下:
第1行: hello
第2行: world
第3行: tarena
答案:
def get_text():
'''获取终端数据形成列表并返回列表'''
L = []
while True:
s = input("请输入: ")
if not s:
break
L.append(s)
return L
def output_text(L):
'''打印带有行号的结果 '''
for t in enumerate(L, 1):
print("第%d行: %s" % t) # (1, 'hello')
if __name__ == '__main__':
output_text(get_text())
字节串和字节数组
字节串bytes(也叫字节序列)
作用:
存储以字节为单位的数据
字节串是不可变的字节序列
字节:
字节是由8个位(bit)组成的数据单位,是计算进行数据管理的单位
字节是用0-255范围内的整数表示
创建空字节串的字面值
B = b''
B = b""
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 = b’\x16\x0d\x0d\x0a’
字节串的构造函数 bytes
bytes() 生成一个字的字节串 等同于b''
bytes(整数可迭代对象) #用可迭代对象初始化一个字节串
bytes(整数n) 生成n个值为0的字符串
bytes(字符串, encoding=’utf-8’) 用字符串的转换编码生成一个字节串
示例:
b = bytes() # b = b''
b = bytes(range(65, 69)) # b = b'ABCD'
b = bytes(5) # b = b'\x00\x00\x00\x00\x00'
b = bytes('abc中文') # b=b'ABC\xe4\xb8\xad\xe6\x96\x87'
bytes 的运算:
+ += * *=
< <= > >= == !=
in / not in
索引和切片
- len(x)
- max(x)
- min(x)
- sum(x)
- any(x)
- all(x)
bytes与 str的区别:
bytes存储字节(通常值在 range(0,256))
str 存储Unicode字符(通常值在0-65535)
bytes 与 str 的转换
编码(encode)
str--------------------->bytes
b = s.encode(encoding='utf-8')
解码(decode) bytes --------------> str
s = b.decode(encoding='utf-8')
练习:
写一个程序,从键盘输入一段字符串存入s变量
1,将此字符串转为字节串用变量b绑定,并打印此b
2,打印字符串s的长度和字节串b的长度
3,将b字节串再转换为字符串用变量s2绑定,判断s2和s1是否相同?
解析:
s=str(input('输入一段字符串: '))
b = s.encode('utf-8')
print(b)
print(len(s))
print(len(b))
s2 = b.decode('utf-8')
print(s2==s)
字节数组 bytearray
可变的字节序列
字节数组的构造函数:bytearray
- bytearray() 创建空的字节串
- bytearray(整数)
- bytearray(整型可迭代对象)
- bytearray(字符串, encode=’utf-8’)
bytearray 的运算:
+ += * *=
< <= > >= == !=
in / not in
索引 index / 切片 slice
- (字节数组可以索引和切片赋值,赋值规则同列表的索引和切片赋值相同)
示例:
ba = bytearray(b'aBCDEfG')
ba[0] = 65
ba[-2] = 70
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 子节数数组
练习:
1. 写一个生成器函数primes生成素数,
此生成器函数为 primes(begin, end)
如: [x for x in primes(10, 20)] 将得到列表
[11, 13, 17, 19]
2. 写一个生成器函数,生成斐波那契数列的前n个数
1 1 2 3 5 8 13
def fibonacci(n):
...
yield...
1) 输出前20个数:
for x in fibonacci(20):
print(x)
2) 打印前40个数的和:
print(sum(fibonacci(40)))
3. 写程序打印杨辉三角(只打印6层)
- 1
- 1 1
- 1 2 1
- 1 3 3 1
- 1 4 6 4 1
- 1 5 10 10 5 1