迭代器
迭代器:迭代取值的工具
2.更节省内存
缺点:1.不如索引取值灵活
2.取值一次性,只能往后取值不能取中间值
迭代器
可迭代的对象:但凡内置有_ _ iter_ _功能的方法都是可迭代对象(字符串/列表/元组/字典/集合/文件)
迭代器对象:既内置有_ _ iter_ _方法,又内置有next方法的对象称之为迭代器对象.(文件对象)
但调用可迭代对象下的iter方法,会有一个返回值,该返回值就是内置的迭代器对象.
#s='abcdf' #可迭代对象 #l=['a','b','c'] #可迭代对象 d={'k1':111, 'k2':222, 'k3':333} #字典d是一个可迭代对象 iter_d=d.__iter__() #利用可迭代对象的iter方法得到返回值为迭代器对象 try: print(iter_d.__next__()) #再利用迭代器对象的next方法取值 print(iter_d.__next__()) #第二个 print(iter_d.__next__()) #第三个 except StopInteration: # try excpet 剔除异常的方法 print('取值完毕') 可迭代对象的iter方法可以将其转化为迭代器对象 #用while,利用iter用法转换成迭代器对象取值 d={'k1':111, 'k2':222, 'k3':333} iter_d=d.__iter__() #iter_d = iter(d) 等价前面代码 while True: try: v = iter_d.__next__() #v = next(iter_d) 等价于前面内置方法 print(v) except StopInetration break #上述代码就是for循环的底层工作原理,故称for循环也叫迭代器循环 for k in d: print(k) #for循环的底层原理: #1.调用in 后面的那个值/对象的iter方法,拿到一个迭代器对象iter_obj #2.调用迭代器对象的next方法(iter.__next__())将得到的返回值赋值给变量名K,循环往复直到取值完毕抛出异常StopInteration #3.捕捉异常,结束循环
生成器
一种自定义的迭代器
如何得到函数的生成器?
但凡函数内出现yield关键字,在调用函数时,运行函数体代码会得到一个返回值,该返回值就是一个迭代器对象
def func(): print('first') yield 1 print('second') yield 2 print('third') yield 3 g = func() #func()运行结果是一个返回值,将返回值赋给了g res1 = next(g) #调用g的next方法 res2 = next(g) res3 = next(g) next(g) #此行代码会报错StopIntreation 总结:yield 与return的区别 1.yield提供一种自定义迭代器的解决办法 2.相同点:都可以得到返回值,返回值没有类型/个数限制 不同点:return只能返回一次值,yield 可以让函数暂停,返回多次
函数的递归调用和二分法
函数的递归调用:在调用一个函数的过程中又直接或者间接的调用该函数本身,称之为递归调用
#以下递归只是单纯的重复,没有意义 def foo(): print('这是函数foo') bar() def bar(): print('这是函数bar') foo() #递归必须满足的两个条件: #1.每进入下一次递归调用,问题规模都应该减少 #2.递归必须有一个明确的结束条件 #以下例子说明递归函数 age(5)=age(4)+2 age(4)=age(3)+2 age(3)=age(2)+2 age(2)=age(1)+2 age(1)=16 我们可以找到上述的等式关系为 age(n) = age(n-1)+2 age(1)=16 #我们可以 def age(n): #这就是一个递归函数 if n == 1: return 16 #当n=1时,返回16 return age(n-1)+2 #当n为其他时接着运行函数age(n-1),且加2 print(age(5)) # 求出n=5的age #递归有两个明确的阶段: 1.回溯:递归调用时问题规模减少,寻找线索规律阶段 2.递推:得到结束条件回推问题的结果
二分法与递归函数的关系
二分法是一种简单的算法思想
#例如我们有一列表nums, 现需要找列表中是否含有201 nums = [3, 5, 7, 11, 13, 23, 24, 76, 103, 111, 201, 202, 250, 303, 341] #我们之前的for循环可以解决问题 for num in nums: if num == 201: print('find it') break else: print('no exist') #我们在知道for循环的底层原理知道这段代码是通过循环取出列表中所有的值一次一次一个个比对的.如果数据较大时程序的运行就不简洁 #我们利用递归函数的特点采用以下方式: nums = [3, 5, 7, 11, 13, 23, 24, 76, 103, 111, 201, 202, 250, 303, 341] def num_search(list1,find_number): #定义一个递归函数 print(list1) if len(list1) == 0: print('no exist') return #如果分下去列表内没有值就说明没有该值 mid_index = len(list1)//2 #这一步我们计算长列表的长度一半 if find_number > list1[mid_index]: #判断要找的数是否大于列表中间数,如果该判断成立那么就在右边 num_search(list1[mid_index+1:], find_number) #再调用我们的函数,但此时列表切分成一半,这一半一定有我们要找的数 elif find_number < list1[mid_index]: #这个条件成立就是在列表的左边部分:按照一样的要求 num_search(list1[:mid_index], find_number) #一样调用,但新列表切分的终止位置为mid_index处 else: print('find it') #如果最终两个条件都不成立那只能是find_number==list[mid_index] num_search(nums, 201) #调用函数,传入列表,及要找的数字参数 [3, 5, 7, 11, 13, 23, 24, 76, 103, 111, 201, 202, 250, 303, 341] [103, 111, 201, 202, 250, 303, 341] [103, 111, 201] [201] find it #运行结果 #该过程就是一个二分法的体现,其中用了递归函数