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
相關文章
相關標籤/搜索