python基础(15)——迭代器 & 生成器 & 字节串和字节数组
一、迭代器Iterator
什么是迭代器
迭代器是访问可迭代对象的工具
迭代器是指用iter(obj) 函数返回的对象(实例)
迭代器可以用next(it) 函数获取可迭代对象的数据
1、迭代器函数 iter和next
iter(iterable)
从可迭代对象中返回一个迭代器,iterable 必须是能提供一个迭代器的对象
next(iterator)
从迭代器iterator中获取下一个记录,如果无法获取下一条记录,则触发StopIterator异常
说明:
1. 迭代器只能往前取值,不会后退
2. 用iter函数可以返回一个可迭代对象的迭代器
示例:
L = [1, 3, 5, 7]
it = iter(L) # 让L提供一个能访问自己的迭代器
next(it) # 1 从迭代器中取值,让迭代器去获取L中的一个元素
next(it) # 3
next(it) # 5
next(it) # 7
next(it) # StopIteration 异常
it = iter(range(1, 10, 3))
next(it) # 1
next(it) # 4
next(it) # 7
next(it) # StopIteration

1 # L = [2, 3, 5, 7] 2 # for x in L: 3 # print(x) # 2 3 5 6 4 # 以下用迭代器来访问L列表中的元素 5 6 7 # L = [2, 3, 5, 7] 8 # it = iter(L) # 先拿到迭代器用iter绑定 9 # while True: 10 # try: 11 # x = next(it) # 获取一个数据并绑定到x 12 # print(x) # 2 3 5 7 13 # except StopIteration: 14 # break 15 16 17 L = [2, 3, 5, 7] 18 it = iter(L) # 先拿到迭代器用iter绑定 19 try: 20 while True: 21 x = next(it) # 获取一个数据并绑定到x 22 print(x) # 2 3 5 7 23 except StopIteration: 24 pass
2、迭代器的用途
用迭代器可以依次访问可迭代对象的数据
示例:
L = [2, 3, 5, 7]
for x in L:
print(x) # 2 3 5 6
# 以下用迭代器来访问L列表中的元素
L = [2, 3, 5, 7]
it = iter(L) # 先拿到迭代器用iter绑定
while True:
x = next(it) # 获取一个数据并绑定到x
print(x) # 2 3 5 7
练习:
有一个集合:
s = {'唐僧', '悟空', '八戒','沙僧'}
用for语句来遍历所有元素如下:
for x in s:
print(x)
else:
print('遍历结束')
将上面的for语句改写为while语句和迭代器实现

1 # 方法1 2 s = {'唐僧', '悟空', '八戒', '沙僧'} 3 myit = iter(s) 4 while True: 5 try: 6 x = next(myit) 7 print(x) 8 except StopIteration: 9 print("遍历结束") 10 break

1 # 方法2 2 s = {'唐僧', '悟空', '八戒', '沙僧'} 3 myit = iter(s) 4 try: 5 while True: 6 x = next(myit) 7 print(x) 8 except StopIteration: 9 print("遍历结束")
二、生成器 Generator
1、什么是生成器
生成器是能够动态提供数据的对象,生成器对象也是可迭代对象(实例)
2、生成器有两种
生成器函数
生成器表达式
3、生成器函数的定义:
含有yield语句的函数是生成器函数,此函数被调用将返回一个生成器对象
yield翻译为产生(或生成)
4、yield 语句
语法:
yield 表达式
说明:
yield 用于 def 函数中,目的是将此函数作用生成器函数使用
yield 用来生成数据,供迭代器和next(it) 函数使用
示例见:

1 # yield语句的函数为生成器函数,及用yield生成整数 2 def myyield(): 3 yield 2 4 yield 3 5 yield 5 6 yield 7 7 print("生成器生成结束") 8 9 10 for x in myyield(): 11 print(x) # 2 3 5 7 12 13 # 调用生成器函数来创建一个生成器,此生成器能生成 14 # 2 3 5 7 这样四个数 15 gen = myyield() 16 17 it = iter(gen) # 用生成器拿到对应的迭代器 18 print(next(it)) # 2 访问迭代器 19 print(next(it)) # 3 访问迭代器 20 print(next(it)) # 5 访问迭代器

1 # 示意含有yield语句的生成器函数的调用顺序 2 # 生成器函数只有在next(it) 函数调用时才会执行,且遇到yield后 3 # 返回相应的值给next(it)函数 4 def myyield(): 5 print("即将生成2") 6 yield 2 7 print("即将生成3") 8 yield 3 9 print("即将生成5") 10 yield 5 11 print("即将生成7") 12 yield 7 13 print("生成器生成结束") 14 15 gen = myyield() 16 it = iter(gen) 17 print(next(it)) # 2 18 print(next(it)) # 3 19 print(next(it)) # 5 20 print(next(it)) # 7 21 print(next(it)) # StopIteration

1 # 此示例示意含有yield语句的生成器函数的调用顺序 2 # 生成器函数只有在next(it) 函数调用时才会执行,且遇到yield后 3 # 返回相应的值给next(it)函数 4 def myyield(): 5 print("即将生成2") 6 yield 2 7 print("即将生成3") 8 return "在生成3之前用return返回" 9 yield 3 10 print("即将生成5") 11 yield 5 12 print("即将生成7") 13 yield 7 14 print("生成器生成结束") 15 16 gen = myyield() 17 it = iter(gen) 18 print(next(it)) # 2 19 print(next(it)) # StopIteration异常

1 # 用生成器函数生成从0开始到n结束的一系列的整数 2 def myinteger(n): 3 i = 0 4 while i < n: 5 yield i 6 i += 1 7 8 for x in myinteger(30000000000): 9 print(x) # 0 1 2 10 11 12 L = [x for x in myinteger(100) if x % 2 == 1] 13 print("L =", L)
生成器函数说明:
生成器函数的调用将返回一个生成器对象,生成器对象是一个可迭代对象,通常用来动态生成数据
生成器函数调用 return 语句会触发一个StopIterator异常
练习:
1、写一个生成器函数 myeven(start, stop) 用来生成 start开始到stop结束(不包含stop)的偶数
如:
def myeven(start, stop):
....
for x in myeven(1, 10):
print(x) # 2 4 6 8
L = [x ** 2 for x in myeven(1, 20)]
print(L)

1 def myeven(start, stop): 2 while start < stop: 3 if start % 2 == 0: 4 yield start 5 start += 1 6 7 8 for x in myeven(1, 10): 9 print(x) # 2 4 6 8 10 L = [x ** 2 for x in myeven(2, 20)] 11 print(L)
2、写一个生成器函数myfactorial(n)此函数用来生成n个从1开始的阶乘
def myfactorial(n):
...
L = list(myfactorial(5)) # L = [1, 2, 6, 24, 120]
# 1! 2! 3! 4! 5!

1 def myfactorial(n): 2 s = 1 # 用来保存阶乘 3 for x in range(1, n + 1): 4 s *= x 5 yield s 6 7 8 L = list(myfactorial(5)) # L = [1, 2, 6, 24, 120] 9 print(L) 10 11 print(sum(myfactorial(5)))
三、生成器表达式
语法:
(表达式 for 变量 in 可迭代对象 [if 真值表达式])
作用:
用推导式形式创建一个新的生成器
说明:
if 子句可以省略
示例:
gen = (x**2 for x in range(1, 5))
it = iter(gen)
print(next(it)) # 1
print(next(it)) # 4
print(next(it)) # 9
print(next(it)) # 16
print(next(it)) # StopIteration
练习:
已知有列表:
L = [2, 3, 5, 7]
1) 写一个生成器函数,让此函数能够动态提供数据,数据为原列表的数字的平方加1
2) 写一个生成器表达式,让此表达式能够动态提供数据,数据为原列表的数字的平方加1
3) 生成一个列表,此列表内的数据是原列表数据的平方加1

1 L = [2, 3, 5, 7] 2 # 1) 写一个生成器函数,让此函数能够动态提供数据,数据为原列表的数字的平方加1 3 def mygen(L): 4 for x in L: 5 yield x ** 2 + 1 6 7 8 gen = mygen(L) 9 for a in gen: 10 print(a) # 5 10 26 50 11 print('------------') 12 # 生成器函数生成的数据已经被取完,再次遍历将拿不到数据 13 for a in gen: 14 print(a) # 5 10 .... 15 print('++++++++++++') 16 # 2) 写一个生成器表达式,让此表达式能够动态提供数据,数据为原列表的数字的平方加1 17 for a in (x ** 2 + 1 for x in L): 18 print(a) 19 # 3) 生成一个列表,此列表内的数据是原列表数据的平方加1 20 L = [x ** 2 + 1 for x in L] 21 print(L)
生成器表达式和列表推导式的区别:
生成器表达式是现用现生成,列表推导式是一次性生成静态数据

1 # 生成器表达式和列表推导式区别 2 3 # 列表推导式 4 L = [2, 3, 5, 7] 5 L2 = [x ** 2 + 1 for x in L] 6 it = iter(L2) 7 print(next(it)) # 5 8 L[1] = 30 9 print(next(it)) # 10 10 11 # 生成器表达式 12 L = [2, 3, 5, 7] 13 gen = (x ** 2 + 1 for x in L) 14 it = iter(gen) 15 print(next(it)) # 5 16 L[1] = 30 17 print(next(it)) # 901
四、迭代工具函数:
作用是生成一个个性化的可迭代对象
函数:
zip(iter1 [, iter2[....]])
返回一个zip对象,此对象用于生成元组,此元组的每个数据来源于参数中的可迭代对象,当最小的可迭代对象不再提供数据时迭代结束
enumerate(iterable [, start])
生成带索引的枚举对象,返回的迭代类型为索引-值对(index-value)对,默认索引从零开始,也可以用start指定
zip示例:

1 numbers=[10086,10000,10010,95588] 2 names = ['中国移动','中国电信','中国联通'] 3 4 for t in zip(numbers,names): 5 print(t) 6 7 for No, number, name in zip(range(1, 100),numbers,names): 8 print("序号",No, name, '的客服电话是:', number)

1 def myzip(iter1, iter2): 2 it1 = iter(iter1) # 拿到两个对象的迭代器 3 it2 = iter(iter2) 4 while True: 5 try: 6 t = (next(it1), next(it2)) # StopIteration 7 yield t 8 except StopIteration: 9 break 10 11 numbers = [10086, 10000, 10010, 95588] 12 names = ['中国移动', '中国电信', '中国联通'] 13 14 for t in myzip(numbers, names): 15 print(t)
enumerate示例:

1 names = ['中国移动','中国电信','中国联通'] 2 3 for t in enumerate(names): 4 print(t) #(0, '中国移动')(1, '中国电信')(2, '中国联通') 5 for t in enumerate(names, 101): 6 print(t) #(101, '中国移动')(102, '中国电信')
练习:
写一个程序,读入任意行文字,当输入空行时结束输入
打印带有行号的输入结果
如:
请输入: abcde<回车>
请输入: hello<回车>
请输入: bye<回车>
请输入: <回车>
输出如下:
第1行: abcde
第2行: hello
第3行: bye

1 def get_lines(): 2 L = [] 3 while True: 4 s = input("请输入: ") 5 if not s: 6 break 7 L.append(s) 8 return L 9 10 11 def print_lines(L): 12 for t in enumerate(L, 1): 13 print("第%d行: %s" % t) 14 15 16 L = get_lines() 17 print(L) 18 print_lines(L)
五、字节串和字节数组
序列的种类:
字符串 str
列表 list
元组 tuple
字节串 bytes
字节数组 bytearray
1、字节串(也叫字节序列) bytes
1、作用:
存储以字节为单位的数据
字节串是不可变的字节序列
2、字节:
字节是0~255之间的整数,字节是数据传输和数据存储的基本单位
(例如:中国移动的流量...,文件大小等)
3、创建空字节串的字面值
b''
b""
b""""""
b''''''
4、创建非空的字节串的字面值
b'ABCD'
b"ABCD"
b'\x41\x42'
5、字节串的构造函数:
bytes() # 生成一个字的字节串,等同于 b''
bytes(整型可迭代对象) 用可迭代对象创建一个字节串
bytes(整数n) 生成n个值为0的字节串
bytes(字符串, encoding='utf-8') 用字符串的转换编码生成一个字节串
示例:
b = bytes()
b = bytes(range(65, 90))
b = bytes(10)
b = bytes('hello', 'utf-8')
b = bytes('中文', 'utf-8')
6、bytes 的运算:
与其它序列的运算规则完全相同
+ += * *=
< <= > >= == !=
in / not in
索引和切片
len(x), max(x), min(x), sum(x), any(x), all(x)
7、bytes 与 str的区别
bytes 存储字节(0~255)
str 存储字符(用来表示文字信息,值为0~65535或更大)
8、bytes与 str转换
编码(encode)
str ----------> bytes
b = s.encode(encoding='utf-8')
解码(decode)
bytes ---------> str
s = b.decode(encoding='utf-8')
2、字节数组 bytearray
可变的字节序列
1、构造函数:
bytearray(b'')
bytearray() # 生成一个字的字节串
bytearray(整型可迭代对象) 用可迭代对象创建一个字节数组
bytearray(整数n) 生成n个值为0的字节数组
bytearray(字符串, encoding='utf-8') 用字符串的转换编码生成一个字节数组
2、运算和字节串完全相同
* *= + +=
< <= > >= == !=
in / not in
索引 index / 切片 slice
字节数组支持索引和切片赋值(重要)
3、bytearray的方法:
方法 | 说明 |
---|---|
B.clear() | 清空 |
B.append(n) | 追加一个字节(n为0-255的整数) |
B.remove(value) | 删除第一个出现的字节,如果没有出现,则产生ValueError错误 |
B.reverse() | 字节的顺序进行反转 |
B.decode(encoding='utf-8') | |
B.find(sub[, start[, end]]) |
4、序列:
str(不可变)
list(可变) ----> tuple(不可变)
bytearray(可变) ----> bytes(不可变)
练习:
1. 用生成器函数,生成素数,给出起始值begin和终止值 end, 生成begin到end范围内的素数
如:
def prime(begin, end):
...
L=[x for x in prime(10, 20)] #L=[11,13,17,19]

1 def is_prime(x): 2 if x < 2: 3 return False 4 for i in range(2, x): 5 if x % i == 0: 6 return False 7 return True 8 9 10 def prime(begin, end): 11 for i in range(begin, end): 12 # 如果i是素数 13 if is_prime(i): 14 yield i 15 16 L = [x for x in prime(10, 20)] # L=[11,13,17,19] 17 print(L)
2. 写一个生成器函数myxrange([start, ], stop[, step]) 来生成一系列整数
要求:
myxrange功能与range功能相同(不允许调用range函数)
用自己写的myxrange函数结合生成器表达式求1~10内奇数的平方和

1 def myxrange(start, stop=None, step=1): 2 if stop is None: 3 stop = start 4 start = 0 5 if step > 0: 6 while start < stop: 7 yield start # 生成当前数送回给迭代器next函数 8 start += step 9 elif step < 0: 10 while start > stop: 11 yield start 12 start += step 13 else: 14 raise ValueError("步长不允许为0") 15 16 for x in myxrange(1, 10, 3): 17 print(x) 18 19 for x in myxrange(10, 0, -3): 20 print(x) # 10, 7, 4, 1
posted on 2018-10-12 17:35 破天荒的谎言、谈敷衍 阅读(517) 评论(0) 收藏 举报