函數進階

一、迭代器

1、迭代:是一個重複的過程,每一次重複,都是基於上一次的結果而來

l=['a','b','c','d']
count=0
while count < len(l):
    print(l[count])
    count+=1

對於列表可以依賴索引取到值,但是數據結構沒有索引,比如字典,就需要一種不依賴索引的取值方式,這就需要迭代器了

2、課迭代對象:凡是對象下有__iter__方法,該對象就是可迭代對象(如字符串,列表,字典,集合,元組,文件等)

  迭代器對象:內置有__iter__方法和__next__,得到的結果就是迭代器對象(如文件)


可迭代對象執行__iter__方法變成迭代器對象,執行__next__取到裏面的值,每次取一個值

dic={'name':'wang','sex':'m',"age":18}
dic_iter=dic.__iter__()
print(dic_iter.__next__())               #打印取到的name
print(dic_iter.__next__())               #打印取到的sex
print(dic_iter.__next__())             #打印取到的age
print(dic_iter.__next__())             #值取完了,拋出異常StopIteration
while True:
    try:                      #處理異常的用法
        print(next(dic_iter))
    except StopIteration:
        break


我們通過這種方式取到的值,用for循環就可以簡單做到,for循環的原理就是把數據變成迭代器對象執行,並加入處理異常

二、三元表達式和列表推導式

1、三元表達式

def my_max(x,y):
    return x if x > y else y         #判斷語句在中間,左邊寫執行語句,右邊寫else語句
print(my_max(1,3))


2、列表推導式

l=['egg%s' %i for i in range(10)]       #列表生成egg0到egg9共十個元素
print(l)
l=['egg%s' %i for i in range(10)  if i >=5]     #加上if判斷,只取egg5到egg9共五個元素
print(l)

3、列表推導式的優點

方便,改變了編程習慣,可稱之爲聲明式編程

三、生成器

1、生成器就是迭代器,只要在函數內部出現yield關鍵字,那麼再調用該函數,將不會立即執行函數體代碼,會得到一個結果,該結果就是生成器對象

2、yield與return比較

  相同點:都有返回值的功能

  不同點:return只能返回一次值,而yield可以返回多次值

3、實現range功能

def my_range(start,stop):
    while True:
        if start == stop:
            raise StopIteration
        yield start            #碰到yield,程序會暫停,執行next會得到返回值1,接着往下執行start變成2,接着循環,最後取到的值就是1和2
        start+=1
g=my_range(1,3)
for i in my_range(1,3):
    print(i)

4、實現 python3 tail.py -f access.log | grep 'error'功能

import time
def tail(filepath):
    with open(filepath, 'r') as f:
        f.seek(0, 2)
        while True:
            line = f.readline()
            if line:                #有新的內容,用yield返回,因爲yield可以多次返回值
                yield line
            else:
                time.sleep(0.2)
def grep(pattern,lines):
    for line in lines:                 #先查看所有的行,然後找出現error模式的行
        if pattern in line:
            print(line,end='')
grep('error',tail('access.log'))

四、面向過程的編程

1、編程思想:核心是過程,即解決問題的步驟,先做什麼再做什麼,是一種機械式的編程思想

2、優缺點

    優點:複雜問題流程化,進而簡單化

    缺點:可擴展性差


五、遞歸和二分法

1、遞歸調用:遞歸調用是函數嵌套調用的一種特殊形式,函數在調用時,直接或間接調用了自身

  遞歸分爲兩個階段:遞推,回溯

2、遞歸的使用:

 1. 必須有一個明確的結束條件

 2. 每次進入更深一層遞歸時,問題規模相比上次遞歸都應有所減少

 3. 遞歸效率不高,遞歸層次過多會導致棧溢出

補充:在計算機中,函數調用是通過棧(stack)這種數據結構實現的,每當進入一個函數調用,棧就會加一層棧幀,每當函數返回,棧就會減一層棧幀。由於棧的大小不是無限的,所以,遞歸調用的次數過多,會導致棧溢出)

def salary(n):
    if n == 1:
        return 100
    return salary(n-1)+300
print(salary(5))

分析:需要salary(5)的值,返回salary(4)+300,接着取salary(4)的值,一直遞推,直到遇到結束條件salary(1)返回值爲100,然後回溯,得到salary(5)的值1300

3、二分法

將整個列表切分爲兩份,取中間值和要找的數據作比較,判斷在哪一部分,然後再在那一部分切分,再次取值判斷,直到最終找到需要的數據

想從一個按照從小到大排列的數字列表中找到指定的數字,遍歷的效率太低,用二分法(算法的一種,算法是解決問題的方法)可以極大低縮小問題規模

六、匿名函數

1、lambda x,y,z=1:x+y+z      #與函數有相同的作用域,但是匿名意味着引用計數爲0,使用一次就釋放,除非讓其有名字

2、有名函數與匿名函數的對比

  有名函數:循環使用,保存了名字,通過名字就可以重複引用函數功能

  匿名函數:一次性使用,隨時隨時定義

應用:max,min,sorted,map,reduce,filter

salaries={
    'wang':3000,
    'li':100000,
    'tom':10000,
    'jim':2000,
}
print(max(salaries))      #取到的結果是wang
print(min(salaries))      #取到的結果是jim
可以看到結果不是我們想要的,因爲max,min函數只是把字典的key做比較得到的最大值,最小值,而我們要的是後面的工資的最大值和最小值
print(max(salaries.values()))    #取到的結果是100000
print(min(salaries.values()))    #取到的結果是2000

3、用zip函數解決(zip函數也叫拉鍊函數)

a=[1,2,3]
b=['q','w','s','e']
res=zip(a,b)
print(list(res))     #得到的結果是[(1, 'q'), (2, 'w'), (3, 's')],就是把兩個列表的元素一一對應,多餘的元素不管
解決上面的問題:把上面字典的鍵值對調
res=zip(salaries.values(),salaries.keys())
print(max(res))                             #得到最大工資的鍵值對組成的元組(100000, 'li')
print(max(res)[1])                           #得到工資高的人li

4、通常我們都是想取出,工資最高的那個人名,即比較的是salaries的值,得到的是鍵

print(max(salaries,key=lambda k:salaries[k]))      #取到的結果是li,是我們需要的值
print(min(salaries,key=lambda k:salaries[k]))      #取到的結果是jim,是我們需要的值

5、按照薪資高低進行排序sorted

res=sorted(salaries,key=lambda k:salaries[k])
print(res)                     #得到從低到高的順序['jim', 'wang', 'tom', 'li'] 
如果要求反向排序,即實現從高到低排序
print(sorted(salaries,key=lambda k:salaries[k],reverse=True))     #得到從高到低的順序['li', 'tom', 'wang', 'jim']

6、map函數,做映射

l=['wang','li']
map(lambda x:x+'_man',l)                   #對列表的每個元素後面添加_man字符串
print(list(map(lambda x:x+'_man',l)))           #得到結果['wang_man', 'li_man']

7、reduce函數 :實現合併

from functools import reduce        #這個函數需要導入模塊
print(reduce(lambda x,y:x+y,range(1,101)))     #1到100的和,結果是5050

8、filter函數,實現過濾

l=['wang_man','li_man','tom']
res=filter(lambda name:name.endswith('man'),l)   #元素裏面以字符串man結尾的
print(list(res))             #過濾的結果['wang_man', 'li_man']

七、內置函數,要看到結果用print打印出來即可

1、數學運算

abs(-5)                          # 取絕對值,也就是5
round(2.6)                       # 四捨五入取整,也就是3.0
pow(2, 3)                        # 相當於2**3,如果是pow(2, 3, 5),相當於2**3 % 5 結果是3
divmod(9,2)                      # 返回除法結果和餘數,適用於判斷數據需要分多少頁
max([1,5,2,-2])                    # 求最大值
min([9,2,1,3])                    # 求最小值
sum([1,2,3])                     # 求和

2、類型轉換

ord("A")  # "A"字符對應的數值
chr(65)  # 數值65對應的字符
bool(0)  # 轉換爲相應的真假值,在Python中,0相當於False,下列對象都相當於False: [], (), {}, 0, None, 0.0, ''
bin(56)  # 返回一個字符串,表示56的二進制數
hex(56)  # 返回一個字符串,表示56的十六進制數
oct(56)  # 返回一個字符串,表示56的八進制數
list((1, 2, 3))   # 轉換爲列表[1, 2, 3]
tuple([2, 3, 4])  # 轉換爲(2, 3, 4)
dict(a=1, b="hello", c=[1, 2, 3])  # 構建字典{'a': 1, 'b': 'hello', 'c': [1, 2, 3]}

3、序列操作

all([True, 1, "hello!"])      # 所有的元素都相當於True值時返回True
any(["", 0, False, [], None])  # 有任意一個元素相當於True值時返回True
sorted([1, 5, 3])          # 序列進行排序,也就是[1,3,5]
reversed([1, 5, 3])         # 序列反轉,也就是[3,5,1]

4、其他常見內置函數

type([1,2,3])            #[1,2,3]是list類型
len([1,2,3])             #[1,2,3]的長度是3
range(1,5,2)             #快速生成序列,1到9,步長爲2,結果是1和3
enumerate函數:
l=['a','b']
for i in enumerate(l):
    print(i)           #得到結果是(0, 'a') (1, 'b'),這樣可以得到元素對應的索引
eval函數和exec函數
s='1+2+3'
print(eval(s))      #eval用來執行表達式,並返回表達式執行的結果,結果是6
print(exec(s))      #exec用來執行語句,不會返回任何值
print(eval('1+2+x',{'x':3},{'x':30}))       #返回33
print(exec('1+2+x',{'x':3},{'x':30}))      #返回None
print(eval('for i in range(10):print(i)'))   #語法錯誤,eval不能執行表達式
print(exec('for i in range(10):print(i)'))   #執行語句,得到語句的結果










發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章