20181203(迭代器,生成器,函数的递归调用和二分法)

 

一、迭代器

什么是迭代器:函数

迭代取值的工具。迭代是一个重复的过程,可是每次重复都是基于上一次重复的结果而继续。工具

为何要用迭代器:优化

迭代器的优势:ui

一、提供了一种不依赖索引的迭代取值方式spa

二、更节省内存对象

迭代器的缺点:递归

一、不如按照索引的取值方式灵活索引

二、取值是一次性的,只能日后去,没法预测值的个数内存

如何用迭代器:generator

可迭代的对象:str\list\tuple\dict\set\文件对象

但凡内置有__iter__方法的对象都称之为可迭代的对象。

迭代器的对象:文件对象

即内置有__iter__方法又内置有__next__方法的对象都称之为迭代器对象。

 

调用可迭代对象下__iter__方法,会有一个返回值,该返回值就是内置的迭代器对象。

 

for循环的底层工做原理

一、调用in后面的那个值/对象的__iter__方法,拿到一个迭代器对象iter_obj

二、调用迭代器对象iter_obj.__next__()将获得的返回值赋值变量名k,循环往复直到取值完毕抛出异常StopIterable

三、捕捉异常结束循环

k = {'egon' : '123', 'kevin' : '456'}
iter_k = k.__iter__()   #等同于iter(k)
while True:
   try:
       v=iter_k.__next__()  #等同于next(iter_k)
       print(v)
   except StopIteration   # 捕捉异常,而后跳出循环
  print('取值完毕')
       break
两种方法
for i in k:
   print(i)

 

迭代器下面的两个函数。iter()和next() 。

d={'k1':111,'k2':222,'k3':333}

print(d.__iter__().__next__())
print(d.__iter__().__next__())
print(d.__iter__().__next__())
此处三个结果都为:k1

d=iter(d)
print(d.__next__())
print(d.__next__())
print(d.__next__())
此时输出结果为:k1,k2,k3

 

二、生成器

生成器就是一种自定义的迭代器

如何获得生成器:

但凡函数内出现yield关键字,再去调用函数不会当即执行函数体代码,会获得一个返回值,该返回值就是生成器对象。

def func():
   print('first')
   yield 1
   print('second')
   yield 2
   print('third')
   yield 3


g=func()
print(g)

res1=next(g)
print(res1)

res2=next(g)
print(res2)

res3=next(g)
print(res3)
输出结果为:
<generator object func at 0x00000235ECE3DEB8>
first
1
second
2
third
3

 

总结yield:

一、提供一种自定义迭代器的解决方案

二、yield & return

相同点:均可以返回值,返回值没有类型限制\个数限制

不一样点:return只能返回一次值,yield却可让函数暂停在某一个位置,能够返回屡次值。

 

三、函数的递归调用和二分法

一、函数的递归调用:

在调用一个函数的过程又直接或间接调用了函数自己,称之为递归调用

递归必须知足两个条件:

一、每进入下一次递归调用,问题的规模都应该有所减小

二、递归必须有一个明确的结束条件

递归关键在于将问题分解为小部分,老是以最小可能性问题结束。

递归有两个明确的阶段:

一、回溯

二、递推

求阶乘的计算
def fake(n):
   if n==1:
       return 1
   return  n*fake(n-1)

print(fake(5))
输出结果为:
120

 

def age(n):
   if n == 1:
       return 18
   return age(n-1)+2

print(age(5))
输出结果为26

其内在逻辑为
# age(5)=age(4)+2
# age(4)=age(3)+2
# age(3)=age(2)+2
# age(2)=age(1)+2
# age(1)=18

# age(n)=age(n-1)+2 # n > 1
# age(1)=18         # n = 1

解决递归调用栈溢出的方法是经过尾递归优化,事实上尾递归和循环效果是同样的,把循环当作是一种特殊的尾递归函数也能够。

求阶乘的计算
def fact(n):
   return inner(n,1)

def inner(num1,num2):
   if num1==1:
       return num2
   return inner(num1-1,num2*num1)
print(fact(5))
输出结果为:
120

修改成也可
def inner(num1,num2):
   if num1==1:
       return num2
   return inner(num1-1,num2*num1)
print(inner(5,1))

 

递归调用与二分法的结合:

nums=[3,5,7,11,13,23,24,76,103,111,201,202,250,303,341]


def binary_search(list1,find_num):
   print(list1)
   if len(list1) == 0:
       print('not exist')
       return
   mid_index=len(list1) // 2
   if find_num > list1[mid_index]:
       # in the right
       binary_search(list1[mid_index + 1:],find_num)
   elif find_num < list1[mid_index]:
       # in the left
       binary_search(list1[:mid_index],find_num)
   else:
       print('find it')

binary_search(nums,203)

输出结果为:
[3, 5, 7, 11, 13, 23, 24, 76, 103, 111, 201, 202, 250, 303, 341]
[103, 111, 201, 202, 250, 303, 341]
[250, 303, 341]
[250]
[]
not exist
相关文章
相关标签/搜索