python函数2(递归、匿名)

python函数

一、递归(recursion)函数

       在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。

       递归函数的特征:

  • 必须有一个明确的结束条件
  • 每次进入更深一层递归时,问题规模相比上次递归都应有所减少
  • 相邻两次重复之间有紧密的联系,前一次要为后一次做准备(通常前一次的输出就作为后一次的输入)

 

       一般来说,使用递归的都可以用循环来解决,比如:

# 求10!用循环
factorial = 1 for i in range(1, 11): factorial *= i print(factorial) # 3628800

#求10!用递归
def factorial(n):
if n == 1:
return 1
return n * factorial(n - 1)

print(factorial(10)) # 3628800

  递归函数的优点是定义简单,逻辑清晰。

 

       递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)

print(factorial(1000))
#RecursionError: maximum recursion depth exceeded in comparison

  

       解决栈溢出的方案设置栈的最大深度

import sys

sys.getrecursionlimit()  # 显示栈的最大深度,默认是1000
sys.setrecursionlimit(10000)  # 设置栈的最大深度


def factorial(n):
    if n == 1:
        return 1
    return n * factorial(n - 1)


print(factorial(1000))
# 402387260077093773543702433923003985719374864210714632543799910429938512
# 398629020592044208486969404800479988610197196058631666872994808558901323
# 829669944590997424504087073759918823627727188732519779505950995276120874
# 9754624970436014182780946464962910563938874378864873371191810458257836478
# 4997701247663288983595573543251318532395846307555740911426241747434934755
# 3428646576611667797396668820291207379143853719588249808126867838374559731
# 7461360853795345242215865932019280908782973084313928444032812315586110369
# 76801357304216168747609675871348312025478589320767169132448426236131412508
# 78020800026168315102734182797770478463586817016436502415369139828126481021
# 30927612448963599287051149649754199093422215668325720808213331861168115536
# 15836546984046708975602900950537616475847728421889679646244945160765353408
# 19890138544248798495995331910172335555660213945039973628075013783761530712
# 77619268490343526252000158885351473316117021039681759215109077880193931781
# 14194545257223865541461062892187960223838971476088506276862967146674697562
# 91123408243920816015378088989396451826324367161676217916890977991190375403
# 127462228998800519544441428201218736174599264295658174662830295557029902432
# 415318161721046583203678690611726015878352075151628422554026517048330422614
# 397428693306169089796848259012545832716822645806652676995865268227280707578
# 139185817888965220816434834482599326604336766017699961283186078838615027946
# 595513115655203609398818061213855860030143569452722420634463179746059468257
# 3103790084024432438465657245014402821885252470935190620929023136493273497565
# 513958720559654228749774011413346962715422845862377387538230483865688976461927
# 3838149001407673104466402598994902222217659043399018860185665264850617997023
# 5619389701786004081188972991831102117122984590164192106888438712185564612496
# 079872290851929681937238864261483965738229112312502418664935314397013742853
# 1926649875337218940694281434118520158014123344828015051399694290153483077644
# 56909907315243327828826986460278986432113908350621709500259738986355427719674
# 28222487575867657523442202075736305694988250879689281627538488633969099598
# 26280956121450994871701244516461260379029309120889086942028510640182154399
# 4571568059418727489980942547421735824010636774045957417851608292301353580
# 81840096996372524230560855903700624271243416909004153690105933983835777939
# 4109700277534720000000000000000000000000000000000000000000000000000000000
# 0000000000000000000000000000000000000000000000000000000000000000000000000
# 00000000000000000000000000000000000000000000000000000000000000000000000000
# 00000000000000000000000000000000000000000000

  

       优化递归,使用尾递归

       尾递归是指,在函数返回的时候,调用自身本身,并且,return语句不能包含表达式。这样,编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况。

def factorial(n, fact):
    if n == 1:
        return fact
    return factorial(n - 1, n * fact)


print(factorial(20, 1))
# 2432902008176640000

  

       递归运用 斐波那契数列

       斐波那契数列,又称黄金分割数列,指的是这样一个数列:0、1、1、2、3、5、8、13、21、34、……。

       在数学上,费波那契数列是以递归的方法来定义:

F0 = 0     (n=0)
F1 = 1    (n=1)
Fn = F[n-1]+ F[n-2](n=>2)

  

       斐波那契数列可以使用循环或递归来实现

       1、循环

def fibonacci(n):
    a = 1
    b = 1
    for i in range(n - 1):
        a, b = b, a + b

    return a


print(fibonacci(10))

  2、递归

def fibonacci(n):
    if n==1 or n==2:
        return 1
    return fibonacci(n-1)+fibonacci(n-2)


print(fibonacci(10))

  

二、匿名函数

        1、匿名函数介绍

       在Python中,不通过def来声明函数名字,而是通过lambda关键字来定义的函数称为匿名函数。

       lambda函数能接收任何数量(可以是0个)的参数,但只能返回一个表达式的值,lambda函数是一个函数对象,直接赋值给一个变量,这个变量就成了一个函数对象。

        2、语法

        lambda 参数:表达式

       先写lambda关键字,然后依次写匿名函数的参数,多个参数中间用逗号连接,然后是一个冒号,冒号后面写返回的表达式。

sum=lambda x,y:x+y
sum(2,3)

  

       使用lambda函数可以省去函数的定义,不需要声明一个函数然后使用,而可以在写函数的同时直接使用函数。

 

        3、匿名函数使用场景

       a、需要将一个函数对象作为参数来传递时,可以直接定义一个lambda函数(作为函数的参数或返回值)

       b、要处理的业务符合lambda函数的情况(任意多个参数和一个返回值),并且只有一个地方会使用这个函数,不会在其他地方重用,可以使用lambda函数

       c、与一些Python的内置函数配合使用,提高代码的可读性

 

       4、匿名函数的使用

       a、sort排序:(字典value排序)

students=[
     {'name':'zhangsan','age':18},
     {'name':'lisi','age':20},
     {'name':'wangwu','age':19},
     {'name':'zhaoliu','age':17},
]
students.sort(key=lambda ele:ele['age'])
print(students)

  b、filter(函数,Iterable)

       过滤:对迭代对象进行过滤,得到的是一个filter对象
ages=[12,37,27,43,32]
x=list(filter(lambda ele:ele>30,ages))
print(x)   #[37,43,32]

  c、map(函数,Iterable)

       map()接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回。
li = [1,2,3,4,5]
print(list(map(lambda x:x*x,li)))   #[1,4,9,16,25]

  d、reduce(函数,Iterable)

       reduce()把一个函数作用在一个序列[x1, x2, x3, ...]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做运算,其效果就是:

       reduce(func([1,2,3])) 等同于 func(func(1,2),3)

from functools import reduce
li = [1,2,3,4,5,6,7,8,9]
print(reduce(lambda x,y:x * y,li))
# 结果=1*2*3*4*5*6*7*8*9 = 362880

  

       对字典里的Value值操作
students=[
    {'name':'zhangsan','age':18},
    {'name':'lisi','age':20},
    {'name':'wangwu','age':19},
    {'name':'zhaoliu','age':17},
]
reduce(lambda x,y:x+y['age'],students,0)   #求age累加和

   

posted @ 2021-02-20 21:01  wangshanglinju  阅读(106)  评论(0编辑  收藏  举报