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=):4)再解決一下猴子怎麼吃桃x=n%10
n=n//10
if n//10 == 0:
print(lst)
return
fnc(n,lst)
方式一:
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...