函数(四)
一、迭代器
1.迭代:更新换代(重复)的过程,每次的迭代都必须基于上一次的结果
迭代器:迭代取值的工具
迭代器给你提供了一种不依赖于索引取值的方法
2.重复+每次迭代都是基于上一次的结果而来的
l = [1,2,3,4] a = 'hello' n = 0 while n < len(a): print(a[n]) n += 1
3.需要迭代取值的数据类型:
字符串、列表、元组、字典、集合
二、可迭代对象
1.只有内置有__iter__方法的都叫做可迭代对象
ps:针对双下划线开头双下划线结尾的方法,推荐读双下+方法名
2.基本数据类型中是可迭代对象的有:
str、list、tuple、dict、set
文件对象(执行内置的__iter__之后还是本身,没有任何变化):文件对象本身就是迭代器对象
三、迭代器对象
1.内置有__iter__方法
2.内置有__next__方法
ps:迭代器一定是可迭代对象,而可迭代对象不一定是迭代器对象
3.例子:
生成一个迭代器对象,将可迭代对象l转换成迭代器对象
l = [1,2,3,4] iter_l = l.__iter__()
迭代器取值,调用__next__,如果取完了,直接报错StopIteration
l = [1,2,3,4] iter_l = l.__iter__() print(iter_l.__next__()) print(iter_l.__next__()) print(iter_l.__next__()) print(iter_l.__next__()) # 如果取完了 直接报错
迭代器对象无论执行多少次__iter__方法得到的还是迭代器对象本身
f1 = open('test','r',encoding='utf-8') # 调用f1内置的__iter__方法 iter_f = f1.__iter__() print(iter_f is f1)
迭代器初始化
d = {'name':'jason','password':'123','hobby':'泡m'}
iter_d = d.__iter__()
print(d.__iter__().__next__()) # 迭代器初始化
print(d.__iter__().__next__()) # 迭代器初始化
异常处理
d = {'name':'jason','password':'123','hobby':'泡m'}
iter_d = d.__iter__()
while True:
try:
print(iter_d.__next__())
except StopIteration:
break
4.迭代器取值特点:只能往后依次取,不能往回取
优点:
(1)不依赖于索引取值
(2)内存中永远只占一份空间,不会导致内存溢出
缺点:
(1)不能够获取指定的元素
(2)取完之后会报StopIteration错
四、for循环内部原理
1.将in后面的可迭代对象调用__iter__转换成迭代器对象
2.调用__next__迭代取值
3.内部有异常捕获Stopiteration,当__next__报这个错,自动结束循环
五、生成器
1.生成器:用户自定义的迭代器,本质就是迭代器
2.函数内如果有yield关键字,那么加括号执行函数的时候并不会触发函数体代码的运行
def func(): print('first') yield 666 print('second') yield 777 g = func() # 生成器初始化:将函数变成迭代器 print(g) # <generator object func at 0x000002BF65103678> print(g.__next__()) # first 666 print(g.__next__()) # second 777
yield后面跟的值就是调用迭代器__next__方法你能得到的值
yield既可以返回一个值也可以返回多个值,并且多个值也是按照元组的形式返回
3.取范围内的值:
方法一:for循环
for i in range(1,10,2): print(i)
方法二:函数
def my_range(start,end,step): while start < end: yield start start += step for j in my_range(1,100,2): print(j)
4.yield表达式形式(了解):
yield支持外界为其传参
当函数内有yield关键字的时候,调用该函数不会执行函数体代码,而是将函数变成生成器
def dog(name): print('%s 准备开吃'%name) while True: food = yield print('%s 吃了 %s'%(name,food)) g = dog('egon') g.__next__() # 必须先将代码运行至yield 才能够为其传值 g.send('饺子') # 给yield左边的变量传参 触发了__next__方法
yield作用:
(1)帮你提供了一种自定义生成器方式
(2)会帮你将函数的运行状态暂停住
(3)可以返回值
与return之间的异同点:
相同点:都可以返回值,并且都可以返回多个
不同点:
yield可以返回多次值,而return只能返回一次函数立即结束
yield还可以接受外部传入的值
自定义range功能
def my_range(start,end,step=1): while start < end: yield start start += step for i in my_range(1,10,2): print(i)
六、面试题
def add(n,i): return n+i def test(): for i in range(4): yield i g=test() for n in [1,10]: g=(add(n,i) for i in g) # 10 print(n) res=list(g) #A. res=[10,11,12,13] #B. res=[11,12,13,14] #C. res=[20,21,22,23] 答案 #D. res=[21,22,23,24]
第一次for循环g=(add(n,i) for i in test())
第二次for循环g=(add(n,i) for i in (add(n,i) for i in test()))
for i in (add(10,i) for i in test()): 会执行所有的生成器内部的代码
add(n,1)
def multipliers(): return [lambda x, i=i: i*x for i in range(4)] # 0, 1, 2, 3 # [func(x): return 0*x, func(x): return 1*x, # func(x): return 2*x, func(x): return 3*x, ] print([m(2) for m in multipliers()]) # [0, 2, 4, 6] # [func(x): return 0*2, func(x): return 1*2, # func(x): return 2*2, func(x): return 3*2, ] # [0, 2, 4, 6] # [6, 6, 6, 6] def multipliers(): list1 = [] for i in range(4): def func(x): return x * i list1.append(func) return list1 print([m(2) for m in multipliers()]) # [6, 6, 6, 6] # 闭包函数的延迟绑定 # 在内层函数执行时才会绑定变量i def multipliers2(): list1 = [] for i in range(4): def func(x, i=i): return x * i list1.append(func) return list1 print([m(2) for m in multipliers2()]) # [0, 2, 4, 6]
读取一个文件并返回每行数据的长度
with open('test1.txt', 'w', encoding='utf-8') as f: for line in range(1000): f.write(f'www{line}aaa' * (line + 1) + '\n') # 列表推导式: 处理数据量大的文件会导致内存溢出. res = [len(line) for line in open('test1.txt', 'r', encoding='utf-8')] # print(res) # 生成器表达式: 处理数据量大的文件推荐使用. res2 = (len(line) for line in open('test1.txt', 'r', encoding='utf-8')) print(res2) # <generator object <genexpr> at 0x000002B3748FD0A0> print(next(res2)) # 8 print(next(res2)) * 15
def demo(): for i in range(4): yield i # <gen..>1 (0, 1, 2, 3) g = demo() g1 = (i for i in g) # <gen..>2 (0, 1, 2, 3) g2 = (i for i in list(g1)) # [] print(list(g)) # [] print(list(g1)) # [] print(list(g2)) # [0, 1, 2, 3] '''值 # g,g1,g2里面的值都是指向同一个内存地址. 真实结果: [0, 1, 2, 3] [] '''

七、生成器表达式
生成器不会主动执行任何一行代码,必须通过__next__触发代码的运行
生成器表达式
res = (i for i in range(1,100000000) if i != 4) # 生成器表达式 print(res)
统计文件中内容的长度
方法一:for循环
with open('test','r',encoding='utf-8') as f: n = 0 for line in f: n += len(line) print(n)
方法二:函数
with open('test','r',encoding='utf-8') as f: g = (len(line) for line in f) print(sum(g))
八、内置函数
1.abs():求绝对值
print(abs(-11.11)) # 11.11
2.all():只要有一个为False就返回False
l = [0,1,2] print(all(l)) # False 因为0为False
3.any():只要有一个为True就返回True
l = [0,1,2] print(any(l)) # True
4.globals():无论在哪,查看的都是全局名称空间
5.locals():当前语句在哪个位置,就会返回哪个位置所存储的所有的变量值
6.bin():十进制转二进制
7.oct():十进制转八进制
8.hex():十进制转十六进制
9.int():二进制转其他进制,将一个字符串或数值转换为一个普通整数
10.bool():测试一个对象是True还是False
11.encode():编码
s = 'hello' print(s.encode('utf-8')) # b'hello print(bytes(s,encoding='utf-8')) # b'hello
12.callable():可调用的(可以加括号执行相应功能的)
l = [1,2,3] def index(): pass print(callable(l)) # False print(callable(index)) # True
13.chr():将数字转换成ascii码表对应的字符
14.ord():将字符按照ascii码表转成对应的数字
15.dir():获取当前对象名称空间里面的名字
16.divmod:分别取商和余数,分页器
print(divmod(101,10)) # (10,1) total_num,more = divmod(900,11) if more: total_num += 1 print('总页数:',total_num) # 总页数:82
17.enumerate():枚举
l = ['a','b'] for i,j in enumerate(l,1): print(i,j)
18.eval():不支持逻辑代码,只支持一些简单的python代码
19.exec():执行字符串或complie方法编译过的字符串,没有返回值,可执行多行
20.format:(1){}占位(2){index}索引(3){name}指名道姓
21.help():返回对象的帮助文档
22.isinstance:后面统一该方法判断对象是否属于某个数据类型
n = 1 print(type(n)) # <class 'int'> print(isinstance(n,list)) # False
23.pow():幂函数
print(pow(2,3)) # 8
24.round():四舍五入
print(round(3.4)) # 3
九、面向过程编程
1.面向过程编程就类似于设计一条流水线
(1)好处:
将复杂的问题流程化,从而简单化
(2)坏处:
可扩展性较差,一旦需要修改,整体都会受到影响
2.例子
# 注册功能 # 1.获取用户输入 def get_info(): while True: username = input(">>>:").strip() if not username.isalpha(): # 判断字符串不能包含数字 print('不能包含数字') continue password = input('>>>:').strip() confirm_password = input("confirm>>>:").strip() if password == confirm_password: d = { '1':'user', '2':'admin' } while True: print(""" 1 普通用户 2 管理员 """) choice = input('please choice user type to register>>>:').strip() if choice not in d:continue user_type = d.get(choice) operate_data(username,password,user_type) break else: print('两次密码不一致') # 2.处理用户信息 def operate_data(username,password,user_type): # jason|123 res = '%s|%s|%s\n'%(username,password,user_type) save_data(res,'userinfo.txt') # 3.存储到文件中 def save_data(res,file_name): with open(file_name,'a',encoding='utf-8') as f: f.write(res) def register(): get_info() register()

浙公网安备 33010602011771号