递归函数,匿名函数

先来看一下函数的执行流程:

http://pythontutor.com/visualize.html#mode=edit  #这个网站可以帮到你;

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()

全局帧中生成foo1,foo2,foo3,main函数对象;

main函数调用;查找内建函数print压栈,将常量字符串压栈,调用函数,执行完成后弹出栈顶;

main中全局查找函数foo1压栈,将常量100,101压栈,调用函数foo1,创建栈帧,print函数压栈,字符串和变量b,b1压栈,调用函数,执行完成后弹出栈顶;

main中全局查找foo2函数压栈,讲常量200压栈,调用foo2,创建栈帧,foo3函数压栈,变量c引用压栈,调用foo3,创建栈帧,foo3完成print函数调用完成后弹出;foo2恢复调用,print执行完成后弹出栈顶;main中foo2调用结束弹出栈顶;main继续执行print函数调用,弹出栈顶,main函数返回;

简单说下我的理解:

函数嵌套时,外层函数调用压栈,在调用内层函数时压栈外层函数的进度,创建新的栈帧,后续依然,执行完成以后一层一层弹出;

递归函数

函数直接或间接调用自身就是递归;

递归需要有退出条件;

递归调用深度不宜过深,python对递归调用深度做了限制,默认是1000,超过递归深度限制,抛出:RecursionError: maxinum recursion depth exceeded

可以通过sys模块下的sys.getrecursionlimit()来更改;

递归调用对比:

import datetime
# Fib Seq
start = datetime.datetime.now()
pre = 0
cur = 1 # No1
print(pre, cur, end=' ')
n = 35
# loop
for i in range(n-1):
    pre, cur = cur, pre + cur
    print(cur, end=' ')
delta = (datetime.datetime.now() - start).total_seconds()
print(delta)

# Fib Seq
start = datetime.datetime.now()
pre = 0
cur = 1 # No1
print(pre, cur, end=' ')
# recursion
def fib1(n, pre=0,cur=1):
    pre, cur = cur, pre + cur
    print(cur, end=' ')
    if n == 2:
        return
    fib1(n-1, pre, cur)

fib1(n)
delta = (datetime.datetime.now() - start
         ).total_seconds()
print(delta)

start = datetime.datetime.now()
def fib2(n):
    if n < 2:
        return 1
    return fib2(n-1) + fib2(n-2)

for i in range(n):
    print(fib2(i), end=' ')
delta = (datetime.datetime.now() - start).total_seconds()
print(delta)

递归性能(菲波那切数列):

递归:

import datetime
n = 35
start = datetime.datetime.now()
def fib(n):
    return 1 if n < 2 else fib(n-1) + fib(n-2)
for i in range(n):
    print(fib(i), end=' ')
delta = (datetime.datetime.now() -start).total_seconds()
print(delta)

for循环:

import datetime
start = datetime.datetime.now()
pre = 0
cur = 1 # No1
print(pre, cur, end=' ')
n = 35
for i in range(n-1):
    pre, cur = cur, pre + cur
    print(cur, end=' ')
delta = (datetime.datetime.now() -start).total_seconds()
print(delta)

递归改进:

pre = 0
cur = 1 # No1
print(pre, cur, end=' ')
def fib(n, pre=0,cur=1): # recursion
    pre, cur = cur, pre + cur
    print(cur, end=' ')
    if n == 2:
      return
    fib(n-1, pre, cur)
fib(n)

#fib函数和循环的思想类似,参数n是边界条件,用n来计算;上一次的计算结果直接作为函数实参.和循环比较,性能相近;

 

递归练习:

求n的阶乘

n = 10
def fac(n):
    if n == 1:
        return 1
    return n * fac(n-1)

print(fac(n))

n = 10
def fac1(n,p = 1):
    if n == 1:
        return p
    p *= n
    #print(p)
    fac1(n-1,p)
    return p
print(fac1(n))
 
n = 10 
def fac2(n,m = None):
    if m is None:
        m = [1]
    if n == 1:
        return m[0]
    m[0] *= n
    #print(m[0])
    fac2(n-1, m)
    return m
print(fac2(n))

将一个数逆序放入列表中,例如123=>[4,3,2,1]

def revert(x):
    if x == -1:
        return ''
    return data[x] + revert(x-1)

print(revert(len(data)-1))


def revert(n,lst=None):
    if lst is None:
        lst = []

    x,y = divmod(n,10)
    lst.append(y)
    if x == 0:
        return lst
    return  revert(x,lst)

print(revert(12345))


num = 123456
def revert(num,target=[]):
    if num:
        target.append(num[len(num)-1]) #target.append(num[-1:])
        revert(num[:len(num)-1])
    return target

print(revert(str(num)))

猴子吃桃:猴子第一天摘下若干个桃子,当即吃了一半,不过瘾,又多吃了一个,第二天早上又将剩下的桃子吃掉一半,又多吃一个,以后每天早上都吃前一天剩下的一半零一个,第十天时,只剩下一个桃子,问第一天一共摘下多少个桃子

假设猴子摘了x个桃子

d1  x//2 -1

d2  d1//2 -1

d3  d2//2 -1

...

d9  d8//2 -1

d10 = 1

 

def peach(days = 1):
    if days == 10:
        return 1
    return (peach(days+1)+1)*2
print(peach())

def peach(days = 10):
    if days == 1:
        return 1
    return (peach(days - 1)+1)*2

print(peach())

匿名函数:

匿名函数即没有名字的函数,python借助lambda表达式构建匿名函数;

格式:

lambda  参数列表:  表达式

lambda  x : x ** 2

(lambda  x : x ** 2)(4)   #调用

foo = lambda  x : x ** 2  #不推荐这么用

匿名函数参数列表不需要小括号;冒号用来分割参数列表和表达式;不需要使用return,表达式的值,就是匿名函数的返回值;lambda表达式(匿名函数)只能写在一行上,被称为单行函数,主要用于高阶函数传参数,可以简化代码;

 print((lambda :0)())
 print((lambda x, y=3: x + y)(5))
 print((lambda x, y=3: x + y)(5, 6))
 print((lambda x, *, y=30: x + y)(5))
 print((lambda x, *, y=30: x + y)(5, y=10))
 print((lambda *args: (x for x in args))(*range(5)))
 print((lambda *args: [x+1 for x in args])(*range(5)))
 print((lambda *args: {x+2 for x in args})(*range(5)))
 [x for x in (lambda *args: map(lambda x: x+1, args))(*range(5))] # 高阶函数
 [x for x in (lambda *args: map(lambda x: (x+1,args), args))(*range(5))]
posted @ 2017-10-19 12:20  客Ren  阅读(268)  评论(0编辑  收藏  举报