一、迭代器
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)')) #執行語句,得到語句的結果