日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

day13-递归函数、匿名函数、内置函数

發(fā)布時間:2025/3/15 编程问答 14 豆豆
生活随笔 收集整理的這篇文章主要介紹了 day13-递归函数、匿名函数、内置函数 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
一 什么是函數(shù)遞歸
  函數(shù)遞歸調(diào)用(是一種特殊的嵌套調(diào)用):在調(diào)用一個函數(shù)的過程中,又直接或間接地調(diào)用了該函數(shù)本身(也叫遞歸調(diào)用) 1 #直接調(diào)用本身 2 def f1(): 3 print('from f1') 4 f1() 5 f1() 6 7 #間接調(diào)用本身 8 def f1(): 9 print('from f1') 10 f2() 11 12 def f2(): 13 print('from f2') 14 f1() 15 f1() 16 17 # 調(diào)用函數(shù)會產(chǎn)生局部的名稱空間,占用內(nèi)存,因為上述這種調(diào)用會無需調(diào)用本身,python解釋器的內(nèi)存管理機(jī)制為了防止其無限制占用內(nèi)存,對函數(shù)的遞歸調(diào)用做了最大的層級限制 18 四 可以修改遞歸最大深度 19 20 import sys 21 sys.getrecursionlimit() 22 sys.setrecursionlimit(2000) 23 24 def f1(n): 25 print('from f1',n) 26 f1(n+1) 27 f1(1) 28 29 雖然可以設(shè)置,但是因為不是尾遞歸,仍然要保存棧,內(nèi)存大小一定,不可能無限遞歸,而且無限制地遞歸調(diào)用本身是毫無意義的,遞歸應(yīng)該分為兩個明確的階段,回溯與遞推 遞歸函數(shù)細(xì)節(jié)介紹 二 遞歸調(diào)用應(yīng)該分為兩個明確的階段:遞推,回溯?

  遞推:一層一層遞歸調(diào)用下去,強(qiáng)調(diào)每進(jìn)入下一層遞歸問題的規(guī)模都必須有所減少

  回溯:遞歸必須要有一個明確的結(jié)束條件,在滿足該條件時結(jié)束遞推開始一層一層回溯 1 示例+圖解。。。 2 # salary(5)=salary(4)+300 3 # salary(4)=salary(3)+300 4 # salary(3)=salary(2)+300 5 # salary(2)=salary(1)+300 6 # salary(1)=100 7 # 8 # salary(n)=salary(n-1)+300 n>1 9 # salary(1) =100 n=1 10 11 def salary(n): 12 if n == 1: 13 return 100 14 return salary(n-1)+300 15 16 print(salary(5)) 遞歸函數(shù)具體步驟程序執(zhí)行順序 三、python中的遞歸效率低且沒有尾遞歸優(yōu)化
#python中的遞歸 python中的遞歸效率低,需要在進(jìn)入下一次遞歸時保留當(dāng)前的狀態(tài),在其他語言中可以有解決方法:
尾遞歸優(yōu)化,即在函數(shù)的最后一步(而非最后一行)調(diào)用自己 但是python又沒有尾遞歸,且對遞歸層級做了限制#總結(jié)遞歸的使用: 1. 必須有一個明確的結(jié)束條件 2. 每次進(jìn)入更深一層遞歸時,問題規(guī)模相比上次遞歸都應(yīng)有所減少 3. 遞歸效率不高,遞歸層次過多會導(dǎo)致棧溢出(在計算機(jī)中,函數(shù)調(diào)用是通過棧(stack)
  這種數(shù)據(jù)結(jié)構(gòu)實現(xiàn)的,每當(dāng)進(jìn)入一個函數(shù)調(diào)用,棧就會加一層棧幀,每當(dāng)函數(shù)返回,
  棧就會減一層棧幀。由于棧的大小不是無限的,所以,遞歸調(diào)用的次數(shù)過多,會導(dǎo)致棧溢出)

 四 二分法

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

1 l=[1,2,10,30,33,99,101,200,301,311,402,403,500,900,1000] #從小到大排列的數(shù)字列表 2 3 def search(n,l): 4 print(l) 5 if len(l) == 0: 6 print('not exists') 7 return 8 mid_index=len(l) // 2 9 if n > l[mid_index]: 10 #in the right 11 l=l[mid_index+1:] 12 search(n,l) 13 elif n < l[mid_index]: 14 #in the left 15 l=l[:mid_index] 16 search(n,l) 17 else: 18 print('find it') 19 20 21 search(3,l) 實現(xiàn)類似于in效果 1 l=[1,2,10,30,33,99,101,200,301,402] 2 3 def search(num,l,start=0,stop=len(l)-1): 4 if start <= stop: 5 mid=start+(stop-start)//2 6 print('start:[%s] stop:[%s] mid:[%s] mid_val:[%s]' %(start,stop,mid,l[mid])) 7 if num > l[mid]: 8 start=mid+1 9 elif num < l[mid]: 10 stop=mid-1 11 else: 12 print('find it',mid) 13 return 14 search(num,l,start,stop) 15 else: #如果stop > start則意味著列表實際上已經(jīng)全部切完,即切為空 16 print('not exists') 17 return 18 19 search(301,l) 實現(xiàn)類似于i.index(30)的效果 五、匿名函數(shù)
(1)
  有名函數(shù):基于函數(shù)名重復(fù)使用
  匿名函數(shù):使用一次之后就被回收了 1 匿名就是沒有名字 2 def func(x,y,z=1): 3 return x+y+z 4 5 匿名 6 lambda x,y,z=1:x+y+z #與函數(shù)有相同的作用域,但是匿名意味著引用計數(shù)為0,使用一次就釋放,除非讓其有名字 7 func=lambda x,y,z=1:x+y+z 8 func(1,2,3) 9 #讓其有名字就沒有意義 匿名函數(shù)代碼解說 (2) #有名函數(shù)與匿名函數(shù)的對比 有名函數(shù):循環(huán)使用,保存了名字,通過名字就可以重復(fù)引用函數(shù)功能匿名函數(shù):一次性使用,隨時隨時定義應(yīng)用:max,min,sorted,map,reduce,filte

 六、內(nèi)置函數(shù)

#注意:內(nèi)置函數(shù)id()可以返回一個對象的身份,返回值為整數(shù)。這個整數(shù)通常對應(yīng)與該對象在內(nèi)存中的位置
    但這與python的具體實現(xiàn)有關(guān),不應(yīng)該作為對身份的定義,即不夠精準(zhǔn),最精準(zhǔn)的還是以內(nèi)存地址為準(zhǔn),
    is運(yùn)算符用于比較兩個對象的身份,等號比較兩個對象的值,內(nèi)置函數(shù)type()則返回一個對象的類型#更多內(nèi)置函數(shù):https://docs.python.org/3/library/functions.html?highlight=built#ascii

 常見的內(nèi)置的函數(shù)如下圖所示:  ? ? ?

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

1 字典的運(yùn)算:最小值,最大值,排序 2 salaries={ 3 'egon':3000, 4 'alex':100000000, 5 'wupeiqi':10000, 6 'yuanhao':2000 7 } 8 9 迭代字典,取得是key,因而比較的是key的最大和最小值 10 >>> max(salaries) 11 'yuanhao' 12 >>> min(salaries) 13 'alex' 14 15 可以取values,來比較 16 >>> max(salaries.values()) 17 >>> min(salaries.values()) 18 但通常我們都是想取出,工資最高的那個人名,即比較的是salaries的值,得到的是鍵 19 >>> max(salaries,key=lambda k:salary[k]) 20 'alex' 21 >>> min(salaries,key=lambda k:salary[k]) 22 'yuanhao' 23 24 25 也可以通過zip的方式實現(xiàn) 26 salaries_and_names=zip(salaries.values(),salaries.keys()) 27 28 先比較值,值相同則比較鍵 29 >>> max(salaries_and_names) 30 (100000000, 'alex') 31 32 33 salaries_and_names是迭代器,因而只能訪問一次 34 >>> min(salaries_and_names) 35 Traceback (most recent call last): 36 File "<stdin>", line 1, in <module> 37 ValueError: min() arg is an empty sequence 38 39 40 sorted(iterable,key=None,reverse=False) lambda與內(nèi)部函數(shù)結(jié)合使用 1 #1、語法 2 # eval(str,[,globasl[,locals]]) 3 # exec(str,[,globasl[,locals]]) 4 5 #2、區(qū)別 6 #示例一: 7 s='1+2+3' 8 print(eval(s)) #eval用來執(zhí)行表達(dá)式,并返回表達(dá)式執(zhí)行的結(jié)果 9 print(exec(s)) #exec用來執(zhí)行語句,不會返回任何值 10 ''' 11 6 12 None 13 ''' 14 15 #示例二: 16 print(eval('1+2+x',{'x':3},{'x':30})) #返回33 17 print(exec('1+2+x',{'x':3},{'x':30})) #返回None 18 19 # print(eval('for i in range(10):print(i)')) #語法錯誤,eval不能執(zhí)行表達(dá)式 20 print(exec('for i in range(10):print(i)')) eval與exac 1 max的工作原理 2 1 首先將可迭代對象變成迭代器對象 3 2 res=next(可迭代器對象),將res當(dāng)作參數(shù)傳給key指定的函數(shù),然后將該函數(shù)的返回值當(dāng)作判斷依據(jù) 4 salaries={ 5 'isetan':3000, 6 'wcl':100000000, 7 'wupeiqi':10000, 8 'yuanhao':2000 9 } #求年薪最高人的名字 10 print(max(salaries,key=lambda k:salaries[k])) #next(iter_s) 11 print(min(salaries,key=lambda k:salaries[k])) #next(iter_s) max工作原理 1 # map的工作原理 2 #1 首先將可迭代對象變成迭代器對象 3 #2 res=next(可迭代器對象),將res當(dāng)作參數(shù)傳給第一個參數(shù)指定的函數(shù),然后將該函數(shù)的返回值當(dāng)作map的結(jié)果之一 4 names=['wcl','isetan','gelln','alex'] 5 6 #列表生成式做法 7 print([name+"_haha" for name in names]) 8 9 #lambda做法 10 aaa=map(lambda x:x+"_haha",names) 11 print(aaa) map函數(shù)使用原理 1 # filter的工作原理 2 #1 首先將可迭代對象變成迭代器對象 3 #2 res=next(可迭代器對象),將res當(dāng)作參數(shù)傳給第一個參數(shù)指定的函數(shù),然后filter會判斷函數(shù)的返回值的真假,如果為真則留下res 4 aaa=filter(lambda x:x.endswith('SB'),names) 5 print(aaa) filter函數(shù)使用原理

?七、函數(shù)的面向過程編程

1 #1、首先強(qiáng)調(diào):面向過程編程絕對不是用函數(shù)編程這么簡單,面向過程是一種編程思路、思想,而編程思路是不依賴于具體的語言或語法的。言外之意是即使我們不依賴于函數(shù),也可以基于面向過程的思想編寫程序 2 3 #2、定義 4 面向過程的核心是過程二字,過程指的是解決問題的步驟,即先干什么再干什么 5 6 基于面向過程設(shè)計程序就好比在設(shè)計一條流水線,是一種機(jī)械式的思維方式 7 8 #3、優(yōu)點(diǎn):復(fù)雜的問題流程化,進(jìn)而簡單化 9 10 #4、缺點(diǎn):可擴(kuò)展性差,修改流水線的任意一個階段,都會牽一發(fā)而動全身 11 12 #5、應(yīng)用:擴(kuò)展性要求不高的場景,典型案例如linux內(nèi)核,git,httpd 13 14 #6、舉例 15 流水線1: 16 用戶輸入用戶名、密碼--->用戶驗證--->歡迎界面 17 18 流水線2: 19 用戶輸入sql--->sql解析--->執(zhí)行功能 面向過程變成思想 1 # 接收用戶輸入用戶名,進(jìn)行用戶名合法性校驗,拿到合法的用戶名 2 def check_user(): 3 while True: 4 name = input('username>>').strip() 5 if name.isalpha(): 6 return name 7 else: 8 print('用戶名必須為字母,傻叉') 9 10 # 接收用戶輸入密碼,進(jìn)行密碼合法性校驗,拿到合法的密碼 11 def check_pwd(): 12 while True: 13 pwd1=input('password>>: ').strip() 14 if len(pwd1) < 5: 15 print('密碼的長度至少5位') 16 continue 17 pwd2=input('again>>: ').strip() 18 if pwd1 == pwd2: 19 return pwd1 20 else: 21 print('兩次輸入的密碼不一致') 22 23 def check_age(): 24 pass 25 26 # pwd=check_pwd() 27 # print(pwd) 28 # 將合法的用戶名與密碼寫入文件 29 def insert(user,pwd,age,path='db.txt'): 30 with open(path,mode='a',encoding='utf-8') as f: 31 f.write('%s:%s:%s\n' %(user,pwd,age)) 32 33 def register(): 34 user=check_user() 35 pwd=check_pwd() 36 age=check_age() 37 insert(user,pwd,age) 38 print('register successfull') 39 40 register() 41 42 43 #ps:將原先的復(fù)雜的代碼分塊寫,清晰,易讀 將復(fù)雜的注冊功能按照面向過程思路編寫,代碼塊有條理,清晰

?

?

?

?

?


轉(zhuǎn)載于:https://www.cnblogs.com/wcl0517/p/9183127.html

總結(jié)

以上是生活随笔為你收集整理的day13-递归函数、匿名函数、内置函数的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。