迭代器 Iterator 和 生成器 Generator
什么是迭代器:
迭代器是访问可迭代对象的一种方式,用迭代器可以访问可迭代对象迭代器是指iter(可迭代对象)返回的对象
迭代器可以用next(it)函数获取可迭代对象的数据
迭代器函数iter和next
iter(iterable) 从可迭代对象中返回一个迭代器,iterable必须是能提供一个迭代器的对象next(iterable) 从迭代器iterable中获取下一个记录.如果无法获取下一条记录,则触发StopIterator异常
迭代器说明:
迭代器只能往前取值,不会后退用iter函数可以返回一个可迭代对象的迭代器
示例:
L = [2, 3, 5, 7]
it = iter(L) # 用iter返回一个迭代器用it绑定
next(it) # 2 #用next(it)用迭代器来获取L中的元素
next(it) # 3
next(it) # 5
next(it) # 7
next(it) # StopIterator #通知next调用者,已无数据
#用迭代器获取range对象的数据
>>> it = iter(range(1, 10, 3))
>>> next(it)
1
>>> next(it)
4
>>> next(it)
7
>>> next(it)
StopIteration
示例:
L = [2, 3, 5, 7]
# 用for循环访问可迭代对象中的数据
for x in L:
print(x)
print('=*= ' * 10+'=*=')
# 用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语句实现上面同样的功能
s = ('工商银行', '建设银行', '中国银行', '农业银行')
for i in s:
print(i)
print('=*= ' * 10 + '=*=')
def iterator(s):
it=iter(s)
while True:
try:
i=next(it)
print(i)
except:
break
if __name__ == '__main__':
s = ('工商银行', '建设银行', '中国银行', '农业银行')
iterator(s)
生成器 generator(python2.5及之后版本)
什么是生成器:
生成器是能够动态提供数据的对象,生成器对象也是可迭代对象生成器有两种:
生成器函数生成器表达式
生成器函数定义:
含有yield语句的函数是生成器函数,此函数被调用将返回一个生成器对象yield 翻译为(产生或生成)
yield语句
语法:yield 表达式
说明:
yield 用于def函数中,目的是将此函数作为生成器函数使用
yield 用来生成数据,提供next(it)函数使用
示例:
写一个生成器函数my_integer(n)生成1到n的整数:
def my_integer(n):
i=1#先初始化变量i将其设置为起始数
while i <n:#循环判断是否已到终止点,如果未到则生成
yield i#生成整数
i+=1#控制循环条件
if __name__ == '__main__':
for i in my_integer(100):
print(i)
练习:
'''
写一个函数,myodd(start,stop)
用于生成start开始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
'''
def myodd(start, stop):
while start < stop:
if start % 2: # 等同于start%2==1
yield start
start += 1
if __name__ == '__main__':
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示例一
numbers = [10086, 10000, 10010, 95588]
name = ['中国移动', '中国电信', '中国联通']
for t in zip(numbers, name):
print(t)
# print(dict(zip(name,numbers )))
#zip示例二
# 此示例示意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)
#zip示例三
numbers = [10086, 10000, 10010, 95588]
name = ['中国移动', '中国电信', '中国联通']
for t in zip(range(1,1111),numbers, name):
print(t)
# print(dict(zip(name,numbers )))
#enumerate示例-1
# 此示例示意enumerate的用法
names = ['中国移动', '中国电信', '中国联通']
for t in enumerate(names):
print(t)
print('*'*20)
for t in enumerate(names,1):
print(t)
#enumerate示例-2
# 此示例示意enumerate的用法
names = ['中国移动', '中国电信', '中国联通']
for a,t in enumerate(names,1):
print('序号',a,'------>',t)
#等同于
it=iter(enumerate(names,1))
while True:
try:
k,n=next(it)
print('序号',k,'------>',n)
except StopIteration:
break
练习:
写一个程序,读入任意行的文字数据,当输入空行时结束输入
打印带行号的输入结果:
如:
请输入:hello<回车>
请输入:tarena<回车>
请输入:bye<回车>
请输入:<回车>
输出如下;
第1行:hello
第2行:tarena
第3行:bye
def input_text():
'''读入键盘输入的文本数据,形成列表后返回'''
L = []
while True:
str_ = input('请输入:')
if not str_:
break
L.append(str_)
return L
def output_text(L):
for t in enumerate(L, 1):
print('第%d行:%s' % t)
if __name__ == '__main__':
text_L = input_text()
output_text(text_L)
字节串和字节数组
字节串(也叫字节序列) bytes
作用:存储以字节为单位的数据
说明:
字节串是不可改变的序列
字节是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'
字节串的构造函数:
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 存储字符
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) # b'\xe4\xbd\xa0\xe5\xa5\xbd'
s=b.decode('utf-8')
print(s) # '你好'
字节数组 bytearray
可变的字节序列创建函数 bytearray
bytearray() 创建空字节数组bytearray(整数)
bytearray(整形可迭代对象)
bytearray(字符串,encoding='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为0~255的整数) |
BA.remove(value) | 删除第一个出现的字节,如果没有出现,则触发BalueError 错误 |
BA.reverse() | 字节的顺序反转 |
BA.decode(encoding='utf-8') | 将bytearray 转换为字符串 |
BA.find(sub[, start[, end]]) | 查找sub子字节数 |
>>> BA=bytearray(b'ABCD')
>>> BA.append('\x45')
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: an integer is required
>>> BA.append(0x45)
>>> BA
bytearray(b'ABCDE')
>>> BA.remove(0x41)
>>> BA
bytearray(b'BCDE')
练习:
1.用生成器函数生成斐波那契数列的前n个数
1 1 2 3 5 8 13 ...
def fibonacci(n):
...
yield ..
1) 输出前 20 个数
2) 求前 30 个数的和
2.写程序打印杨辉三角(只打印6层)