迭代器、生成器、面向过程编程
一、迭代器
1.首先,器”,大家都已经了解,就是工具的意识,那么什么是迭代?
迭代:“迭代是一个重复的过程,并且每次的重复都是基于上一次的结果而来的
2.想要了解迭代器到底是什么?还必须先了解什么是“可迭代对象”?
可迭代对象:在python中,但凡内置有_iter_方法的对象,都是可迭代对象
例如以下都是可迭代对象
str1='hello' list1=[1,2,3] tup1=(1,2,3) dic={'x':1} s1={'a','b','c'} f=open('a.txt','w',encoding='utf-8')
3.迭代器
定义:迭代取值工具,可迭代的对象执行__iter__方法得到的返回值就是迭代器对象
dic={'x':1,'y':2,'z':3} # dic为可迭代对象 iter_dic= dic.__iter__() # iter_dic为迭代器对象 print(iter_dic.__next__()) print(iter_dic.__next__()) print(iter_dic.__next__()) 打印结果:x y z 会将键值打印出来 异常处理 如果循环取值,但是本身的值并没有那么多会出现什么情况呢? 当然会报错了,那么又有什么方法来控制呢 x=[1,2,3] iter_x=x.__iter__() while True: try: # try 就相当于与一个监督作用,如果取出的值超出了x的范围,那么就会停止取值 print(iter_x.__next__()) except StopIteration: break
4.可迭代对象与迭代器的比较
可迭代对象:
str,list,dict,tuple,set,file
获取可迭代对象方式:
无需获取,python内置str,list,dict,tuple,set,file都是可迭代对象
特点:
内置有__iter__方法的都叫可迭代的对象,执行该方法会拿到一个迭代器对象
迭代器对象:
文件对象本身就是迭代器对象
获取迭代器对象的方式:
执行可迭代对象的__iter__方法,拿到的返回值就是迭代器对象
特点:
内置有__next__方法,执行该方法会拿到迭代器对象中的一个值
内置有__iter__方法,执行该方法会拿到迭代器本身
5.迭代器优缺缺点
优点:
1.>可以不按照索引取值
因为它可以利用可迭代的对象执行__iter__方法直接得到的返回值
2.>节省内存
它可以将所有的值全部储存在一个空间,就是一个存储地址
缺点:
1.>取值麻烦
因为它取值只能一个一个取,取完前面才能取后面
2.>取值是一次性的,无法用len获取长度
6.for 循环原理分析
1.>for循环称之为迭代器循环,in后面跟的必须是可迭代对象
2.>for循环会执行in后面对象的__iter__方法,转成迭代器对象
3.>然后调用迭代器__next__方法,进行取值
4.>依次循环,直到取值完毕,检测到异常StopIteration,自动结束循环
二、生成器
1.生成器
生成器的本质就是迭代器
函数内包含yield关键字,在调用函数,
就不会执行函数体代码,拿到的返回值就是一个生成器
如果取值范围超过本身的数值范围会怎样呢?
既然会出现这种报错的情况,那么自然就有解决的方法
yield即可以返回一个值,也可以返回多个值,
并且多个值是以元组的形式返回,
如果yield后面没有数值,那么就会返回None
def func(): print('=====>first') yield 1 print('=====>second') yield 2 print('=====>third') yield 3,4 print('=====>forth') yield s = func() print(s) print(s.__next__()) print(s.__next__()) print(s.__next__()) print(s.__next__()) # 打印结果: =====>first 1 =====>second 2 =====>third (3, 4) =====>forth None
2.练习1:
自定义range功能
需要取出range里的值 平常是使用for循环来取值 for i in range(1,10): print(i) # 打印结果:1~9的值 这样就可以将其中的值全部取出,那么自定义生成器怎么取呢? def my_range(start,end,step=1): while start < end: yield start start += step for i in my_range(1,10): print(i) # 打印结果:1~9的值
3.yield表达形式
def eat(name): print('%s ready to eat' %name) food_list=[] while True: food=yield food_list # food='骨头' food_list.append(food) #food_list=['泔水','骨头'] print('%s start to eat %s' %(name,food)) dog1=eat('jack') 1、必须初始化一次,让函数停在yield的位置 res0=dog1.__next__() print(res0) 2、接下来的事,就是喂狗 send有两方面的功能 1、给yield传值 2、同__next__的功能 res1=dog1.send('泔水') print(res1) res2=dog1.send('骨头') print(res2) res3=dog1.send('shit') print(res3)
4.yield与returnd的区别
yield
1.>会提供一种自定义生成的方式
2.>会将函数的运行状态暂时停住
3.>可以返回值,并且可以返回多个
4.>可以接受外部传入的值
return
1.>可以返回值,并且可以返回多个
2.>返回值后会将函数立即结束
5.生成器表达式
生成器不会主动执行任何一行代码,必须通过__next__触发代码的运行
6.练习2:
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) # 第一次for循环g=(add(n,i) for i in test()) # 第二次for循环g=(add(n,i) for i in (add(n,i) for i in test())) print(n) res=list(g) """ for i in (add(10,i) for i in test()): 会执行所有的生成器内部的代码 add(n,i) """
三、常用内置函数方法
1.abs() # 求绝对值
2.all() # 只要有一个为False就返回False
3.any() # 只要有一个位True就返回True
4.callabe() # 可调用的
5.chr() # 将数字转换成ascii码表对应的字符
6.ord() # 将字符按照ascii表转成对应的数字
7.dir() # 获取当前对象名称空间里面的名字
8.divmod() # 分页器
9.enumerate() # 枚举
10.eval() # 不支持逻辑代码,只支持一些简单的python代码
11.exec()
12.format #三种玩法 #{}占位 {index} 索引 {name} 指名道姓
13.isinstance # 后面统一改方法判断对象是否属于某个数据类型
四、面向过程编程
1.定义
核心是'过程'二字,过程即解决问题的步骤,即先干什么,再干什么。。。。
基于面向过程编写程序就好比在设计一条流水线,是一种机械式的思维方式。
2.优缺点
优点:
将复杂的问题流程化 从而简单化
缺点:
可扩展性较差 一旦需要修改 整体都会受到影响
3.示范
#1、步骤一:拿到用户输入的合法的信息:用户名、密码、余额、年龄 db_path='db.txt' def get_uname(): while True: uname=input('用户名>>:').strip() if not uname.isalpha(): print('\033[45m用户名必须为英文字母...\033[0m') continue with open(r'%s' %db_path,'r',encoding='utf-8') as f: for line in f: uinfo=line.strip('\n').split(',') if uname == uinfo[0]: print('\033[45m用户名已存在...\033[0m') break else: return uname def get_pwd(): while True: pwd1=input('请输入密码>>: ').strip() pwd2=input('再次输入密码>>: ').strip() if pwd1 == pwd2: return pwd1 else: print('\033[45m两次输入的密码不一致,请重新输入...\033[0m') def get_bal(): while True: bal=input('请输入余额: ').strip() if bal.isdigit(): # bal=int(bal) return bal else: print('\033[45m钱必须是数字,傻叉...\033[0m') def get_age(): pass #2、步骤二:写入文件 def file_hanle(uname,pwd,bal,age): with open(r'%s' %db_path,'a',encoding='utf-8') as f: f.write('%s,%s,%s,%s\n' %(uname,pwd,bal,age)) # 注册功能 def register(): #步骤1: uname=get_uname() #拿到合法的用户名 pwd=get_pwd() #拿到合法的密码 bal=get_bal() #拿到合法的余额 #步骤2: file_hanle(uname,pwd,bal) #写入文件