小白學習之路,基礎四(函數的進階)
一,內置函數
前面已經認識了函數,對函數都有所了解了,其實呢,在Python中提供了很多內置的函數方便給我們調用。下面會給大家提到一些常用的常用內置函數的用法,當然還有一些其他沒講到的,你也可以看參考文檔,深入學習一波。咳咳咳,不多說了,直接進入裝逼的代碼環節。
更多的內置函數詳情請參考http://www.runoob.com/python3/python3-built-in-functions.html
1 abs(-3) #取絕對值 2 all([1,2,5,0]) #當全部為真或者全部不為0時,返回為真(一假全假) 3 any([0,1,0,]) #判斷是否有一個為真,存在就為真(一真全真)View Code4 type(‘123‘) #返回數據類型 5 bin(10) #把數字轉換為二進制 6 oct(10) #把數字轉換為8進制 7 hex(17) #數字轉換為16進制 8 chr(65) #裏面是ASCII碼的序號,然後轉化為相應的ASCII裏面的值,這個在做隨機驗證碼有用到哦 9 ord(‘A‘) #跟chr相反,是把ascii碼裏面的值轉化為對應的序號 10 a=dict() #生成字典 11 dir(a) #查看字典可以調用的方法 12 int(‘1‘) #轉換為整數類型 13 str(1) #轉換為字符串類型 14 divmod(5,3) #輸出商和余數 15 a=lambdan:n*n #匿名函數 16 #輸出0-19所有偶數 17 def calc(n): 18 return n%2==0 19 c=filter(calc,range(20))#根據前面的方法,在後面值中篩選正確的結果。 20 for i in c: 21 print(i) 22 locals() #打印局部變量 23 globals() #打印全局變量 24 pow(2,3) #2的三次方 25 __import__(‘time‘) #在記不住庫準確名字的時候使用 26 #eval()能把字符串轉化為字典或者列表 27 s1="[1,2,‘fa‘]" 28 l=eval(s1) #把字符串轉化為列表29 30 s2="{‘name‘:‘zzq‘,‘age‘:‘18‘}" 31 d=eval(s2) #把字符串轉化為字典
當然還有很多的內置函數,如果你感興趣,可以進一步去探索。
二,列表生成式
列表生成式,聽名字感覺是生成列表的一種式子嘛。其實列表生成式是快速生成一個列表的一些公式 ,比如當你需要生成一個1到50的所有偶數的列表,你會想我的天啊,這個好麻煩啊,不過你又仔細想了想不對,我學過for循環的嘛,於是,你忍不住寫了下面的代碼。
1 a=[] 2 for i in range(2,51,2): 3 a.append(i) 4 print(a)
當你想跟你周圍的女同學裝逼的時候,我給你了一個眼神暗示,告訴你還有更裝逼的方式。
1 a=[i*2 for i in range(1,26)] 2 print(a)
在寫列表生成式的時候,我看到還有一個叫列表生成器的騷操作,下面簡單介紹一下兩者的不同吧
- 列表生成式: 會將所有的結果全部計算出來,把結果存放到內存中,如果列表中數據比較多,會占用過多的內存空間,可能導致MemoryError內存錯誤或者導致程序在運行時出現卡頓的情況 。
- 列表生成器:會創建一個列表生成器對象,不會一次性的把所有結果都計算出來,如果需要序號獲取數據,可以使用next()函數來獲取,還可以使用 for循環遍歷生成器對象,獲取所有數據 。
臥槽,生成器又是什麽東西,別急,下面就講。
三,叠代器和生成器
1.生成器
我們知道,列表裏面的的數據是存在內存裏面的,萬一我需要存很多數據,那豈不是很占內存。而且有時候我們可能並不會用到裏面的所有數據,可能只會用到一部分,這樣就會造成極大的浪費。所以呢,我們就引入了一種叫生成器的東西。
在 Python 中,使用了 yield 的函數被稱為生成器(generator)。
在調用生成器運行的過程中,每次遇到 yield 時函數會暫停並保存當前所有的運行信息,返回 yield 的值, 並在下一次執行 next() 方法時從當前位置繼續運行。
在生成器中,我們使用的是next()來查看下一個數據,當然我們也可以通過for循環來查看,因為生成器也是一個可叠代對象。
下面是一個用生成器寫的斐波那契數列
1 #定義一個斐波那契函數 2 def fbi(x): 3 sum,a,b=0,0,1 4 while sum<x: 5 yield b 6 a,b=b,a+b 7 sum+=1 8 a=fbi(3) 9 10 #用next方法一條一條的取數據 11 print(a.__next__()) #取出第一個數 12 print(a.__next__()) 13 print(a.__next__()) 14 #如果當generator沒有值你再繼續調用next方法,會報一個StopIteration錯誤 15 16 #用for循環讀出裏面的數據 17 for i in a: 18 print(i)View Code
說到生成器,還有一種很厲害的用法,那就是生產者消費者模型,能夠讓人感覺在單線程下,實現事件的並發。如果想更好的理解流程,可以自己加上斷點看清楚執行的流程。
1 import time#導入time這個模塊 2 def buy(name): 3 print(‘%s準備購買商品了‘%(name)) 4 while True: 5 number=yield #暫停並記住程序運行狀態 6 print(‘%s購買了%s商品‘%(name,number)) 7 def protect(): 8 name=buy(‘zzq‘)#把生成器轉化為一種地址 9 name.__next__() #運行生成器,遇到yield就停止 10 print(‘準備生產商品了‘) 11 for i in range(5): 12 time.sleep(2) #休眠兩秒 13 print(‘生產了%s的商品‘ %(i)) 14 name.send(i) #傳值並運行 15 protect()View Code
流程的執行順序是在函數protect中調用buy函數,這裏只是把buy轉化成了一個generator地址,然後在執行next函數的時候就執行buy函數,但是遇到yield的時候要停止,接著繼續執行protect函數,到了send的時候,繼續執行buy函數,並且把send裏面的值,賦值給number。運行結果如下:
1 zzq準備購買商品了 2 準備生產商品了 3 生產了0的商品 4 zzq購買了0商品 5 生產了1的商品 6 zzq購買了1商品 7 生產了2的商品 8 zzq購買了2商品 9 生產了3的商品 10 zzq購買了3商品 11 生產了4的商品 12 zzq購買了4商品View Code
2.叠代器
在講叠代器之前,必須了解的是可叠代對象。簡單來講,所有可以直接用for循環的對象都叫可叠代對象(Iterable)。哪些又能直接用呢,有下面兩大類把。一類是集合類數據類型,比如一些列表(list),元組(tuple),字典(dict),字符串(str),集合(set),還有一類就是我們剛剛
學到的genertor,包括生成器和帶yield的generator function。
可以被next()
函數調用並不斷返回下一個值的對象稱為叠代器:Iterator
。
四,裝飾器
在講裝飾器之前,吹吹小牛。李嘉誠說過一句話(好像是他講的),其實我也沒得什麽特別的,只是我每天進步一點,然而我周圍的人卻停在了原地。學習也是一點一點積累起來的,差距也是一點一點拉開的。你堅持看到這裏,會發現臥槽,原來裝逼的在最後面。沒錯,前面我們講的什麽嵌套函數啊,高階函數啊都是為今天的裝飾器打下基礎。
裝飾器是一個很著名的設計模式,經常被用於有切面需求的場景,較為經典的應用有插入日誌、增加計時邏輯來檢測性能、加入事務處理等。裝飾器是解決這類問題的絕佳設計,有了裝飾器,我們就可以抽離出大量函數中與函數功能本身無關的雷同代碼並繼續重用。概括的講,裝飾器的作用就是為已經存在的對象添加額外的功能。
舉一個簡單的例子吧,比如現在有一個這樣的需求,我現在想知道你每個函數運行的時間,不要問我為什麽,我就是要你在每個函數加一個這樣的功能,你心裏此時估計一萬句問候祖輩的話就來了。哈哈哈,有的人就想那我在每個函數裏面加一個算運行時間的不就行了,但是我們寫代碼有兩個要求吧,一個就是封閉性:已實現的功能代碼塊不應該被修改,還有一個就是可擴展性:對現有功能的擴展開放。你想了想我不管,我就是要在原來的函數上面加,但是我又告訴你一共有幾百個函數,你當時就蒙了,臥槽,這該怎麽玩呢。。。這是肯定用到裝逼的裝飾器了啥。其實裝飾器就是在不改變函數的調用方式還有內部結構的基礎上,然後再給函數增加其他功能。
原來的函數
1 import time 2 def test(): 3 time.sleep(1) 4 print(‘this is test‘)
後面的代碼或許會引起部分讀者的不適,請謹慎讀取。
1 #計算函數花費時間 2 def times(f): #後面引用函數的內存地址 3 def internal(*args,**kwargs): 4 stime=time.time() 5 f(*args,**kwargs) #這裏是相當於運行引用函數裏面傳有參數 6 etime=time.time() 7 print(‘cost time is %s‘ %(etime-stime)) 8 return internal 9 10 import time 11 @times #加在需要裝飾的函數上面 12 def test(): 13 time.sleep(1) 14 print(‘this is test‘) 15 test() 16 17 #執行結果 18 #this is test 19 #cost time is 1.0007286071777344View Code
裝飾器具體的執行流程我在這裏也不好具體介紹,也講不太清楚,需要你自己去加斷點一步一步去理解。所以。。。我也只能幫你到這裏。但是這個裝飾你又會想,裝飾的這個函數沒有返回值啊,如果有返回值應該怎麽辦呢。emmm,居然還是讓你發現了,其實很簡單,在原來的裝飾器基礎上加上一個返回值就行了。
1 def times(f): #後面引用函數的內存地址 2 def internal(*args,**kwargs):#這裏是相當於運行引用函數裏面傳有參數 3 stime=time.time() 4 res=f(*args,**kwargs)#函數返回值賦值給res 5 etime=time.time() 6 print(‘cost time is %s‘ %(etime-stime)) 7 return res 8 return internal 9 10 import time 11 @times #加在需要裝飾的函數上面 12 def test(): 13 time.sleep(1) 14 print(‘this is test‘) 15 return ‘nb‘ 16 print(test()) 17 #執行結果 18 #this is test 19 #cost time is 1.0007147789001465 20 #nbView Code
今天大概內容就這麽多吧,後面就會講今天提到的一些模塊的具體用法。比如今天的time模塊。我也是最近才開始寫博客,前幾天看到第一個人跟我評論然後關註我的時候心情那個激動啊,感覺自己很興奮。最開始打算的是自己寫了以後,第一相當於知識點回顧把,然後還有一個作用是忘記的知識可以跟翻筆記一樣看看遺忘的知識點。現在發現居然有人看過我的博客,我很開心我這樣的小白也能幫助到別人。最後我希望每個在追逐自己夢想的道路上,能夠堅持走下去。
小白學習之路,基礎四(函數的進階)