python中函式的執行流程和遞迴

2021-08-18 20:12:35 字數 4089 閱讀 7370

def foo1(b,b1=3):

print('foo1 called',b,b1)

def foo2(c):

foo3(c)

print('foo2 called',c)

def foo3(d):

print('foo3 called',d)

def main():

print('main called')

foo1(100,101)

foo2(200)

print('main ending')

main()

1) 全域性幀中生成foo1,foo2,foo3,main函式物件

2) main函式呼叫

3)main中查詢內建函式print壓棧,將常量字串壓棧,呼叫函式,彈出棧頂

4)main中全域性查詢函式foo1壓棧,將常量100,101壓棧,呼叫函式foo1,建立棧幀.print函式壓棧,字串和變數b,b1壓棧,呼叫函式,彈出棧頂,返回值.

5)main中全域性查詢foo2函式壓棧,將常量200壓棧,呼叫foo2,建立棧幀.foo3函式壓棧,變數c引用壓棧,呼叫foo3,建立棧幀.foo3完成print函式呼叫後返回.foo2恢復呼叫,執行print後,返回值.main中foo2呼叫結束彈出棧頂,main繼續執行print函式呼叫,彈出棧頂.main函式返回.

1.定義: 函式直接或者間接呼叫自身就是遞迴;它需要有邊界條件,遞迴前進段,遞迴返回段;遞迴一定要有邊界條件,當邊界條件不滿足的時候,遞迴前進,當邊界條件滿足的時候,遞迴返回.

要求:遞迴一定要有退出條件,遞迴呼叫一定要執行到這個退出條件.沒有退出條件的遞迴呼叫,就是無限呼叫;遞迴呼叫的深度不宜過身,但python對遞迴呼叫的深度做了限制,以保護直譯器;超過遞迴呼叫的深度,丟擲recursionerror : maxinum recursion depth exceeded 超出最大深度,用sys.getrecursionlimit()可以更改最大深度,但最好別動它啊.

效能:迴圈稍微複雜一些,但只要不是死迴圈便可以多次迭代直至算出結果;fib函式**極簡易懂,但是只能獲取到最外層的函式呼叫,內部遞迴結果都是中間結果,而且給定乙個n都要進行近2n次遞迴,深度越深,效率越低,為獲取斐波納挈數列需要外面再套乙個n次的迴圈,效率更低了.並且它還有深度限制,如果遞迴負載,函式反覆壓棧,棧記憶體很快就溢位了.

間接遞迴:通過別的函式呼叫了函式自身,但如果構成了迴圈遞迴呼叫是非常危險的,往往這種情況出現在**複雜的情況下,所以要規範**來避免這種遞迴.

總結:遞迴是一種很自然的表達,符合邏輯思維,其相對執行效率低,每一次呼叫函式都要開闢桟幀,遞迴有深度限制,如果遞迴層次太深,函式反覆壓棧,棧記憶體很快就溢位了;如果是有限次數的遞迴,可以使用遞迴呼叫,或者使用迴圈代替,迴圈**稍微複雜一些,但是只要不是死迴圈都可以多次迭代直至計算出結果,且絕大多數遞迴都可以使用迴圈實現;即使遞迴**很簡潔,但是能不用則不用遞迴.

def foo1():

foo2()

def foo2():

foo1()

foo1()

2.遞迴的實踐:

1)斐波納挈數列的列印:

pre = 0

cur = 1

print(pre,cur,end=' ')

n = 4

for i in range(n-1):

pre,cur=cur,pre + cur

print(cur,end=' ')

利用遞迴的列印:

方式一:

def fib(n):

return 1 if n < 2 else fib(n-1)+fib(n-2)

for i in range(5):

print(fib(i),end = ' ')

解析:fib(3)+fib(2)   

fib(3)呼叫fib(3),fib(2),fib(1)

fib(2)呼叫fib(2),fib(1)

fib(1)是邊界

說通俗點就是return多少次1的問題

每一次都要從頭開始計算

效率低下

方式二:

def num(x=0,y=1,n=1):

n += 1

x,y = y,x + y

print(x,end = ' ')

if n == 6:

return

num(x,y,n)

利用函式的預設值,將每次改變的預設值儲存下來供下次使用,效率稍高

2)求n的階乘:

方式一:

def func(n=1,x=1):

n += 1

x = x*n

if n == 5:

print(x)

return

func(n,x)

方式二:

def fac(n):

if n == 1:

return 1

return n*fac(n-1)

方式三:

def fac1(n, p = 1):

if n == 1:

return p

p *= n

print(p)

fac1(n-1,p)

return p

方式四:

def fac1(n, p = 1):

if n == 1:

return p

p *= n

print(p)

fac1(n-1,p)

return p

方式五:

def fac2(n,p=none):

if p is none:

p=[1]

if n == 1:

return p[0]

p[0] *= n

print(p[0])

fac2(n-1,p)

return p

比較一下這幾種方式的效能

3)將乙個數逆序放到列表中,例如1234:

方式一:

str1='1234'

lst=

length=len(str1)

for i in range(len(str1)):

方式二:

def fnc(n,lst=):

x=n%10

n=n//10

if n//10 == 0:

print(lst)

return

fnc(n,lst)

4)再解決一下猴子怎麼吃桃

方式一:

x=1

for _ in range(1,10):

x=2*(x+1)

print(x)

方式二:

def num(n=1,x=1):

x = (x+1)*2

n += 1

if n == 10:

print(x)

return

num(n,x)

num(n=1,x=1)

方式三:
def peach(days=1):

if days == 10:

return 1

return (peach(days+1)+1)*2 #返回值

print(peach())

swift中KVC建構函式,和執行流程

kvc 執行流程 1.物件呼叫 setvaluesforkeyswithdictionary 遍歷鍵值 給物件傳送setvalue forkey 2.在 setvalue forkey 會根據鍵值 檢測 物件是否存在對應的屬性 3.如果屬性存在 就直接完成賦值的操作 4.如果屬性不存在 就 給 se...

HashMap put函式執行流程

put函式執行思路public v put k key,v value 如果key為null,則hash為0,否則key的hashcode值高位與低16位異或,使hash更加分散。static final inthash object key final v putval int hash,k ke...

python學習之 流程和函式

簡要介紹python的流程和函式 python裡面是沒有switch的,其實switch是有乙個hash表通過表來查詢對應的跳轉 例如 switch s 1,2,3,4 for i in range 1,5 print switch.get i 條件判斷 a 1 if a 0 print 1 eli...