【Python】递归与匿名函数

137 阅读4分钟

先来聊一下匿名函数的概念: Python 中使用 lambda 来创建匿名函数。

所谓的匿名:即不再使用 def 语句这样的标准形式来定义一个函数。

匿名函数的语法格式:

"""语法格式:
lambda [arg1 [, arg2, ...argn]]:expression

语法说明:
lambda:Python 预留的关键字,类似普通函数中 def
[arg…]:是参数列表,它的结构与 Python 中函数(function)的参数列表是一样的,
       需要注意的是,普通函数不同,这里不需要用括号将 lambda 函数的参数括起来;
       如果 lambda 函数有两个或更多参数,用逗号列出它们。
expression:一个参数表达式,表达式中出现的参数需要在[arg......]中有定义,并且表达式只能是单行的,只能有一个表达式。
"""

实例:

add = lambda x, y: x + y
print(add(11, 22))

等同于:

def add(x, y):
    return x + y


print(add(11, 22))

lambda 参数实例:

import random

# 无参数时
sdds = lambda: random.random()
print(sdds())
# 一个参数时:
func1 = lambda x: x
print(func1('hello'))
# 默认参数(缺省参数),实参的值覆盖形参的值
func2 = lambda a, b, c=100: a + b + c
print(func2(10, 20, 1000))
# 可变参数之args
func3 = lambda *args: args
print(func3(1, 2, 3, 4, 5))
# 带判断的 lambda 表达式
func4 = lambda x: x if (x > 10) else 10
print(func4(6))  # 10

"""它是以下带有def 和 return 关键字的普通函数的更简单的版本:"""


def func5(x):
    if x > 10:
        return x
    else:
        return 10


print(func5(6))

列表中字典数据排序:

# 需求:假设我们需要对字典中的年龄进行排序

userList = [
    {"name": 'zhangsan1', 'age': 18},
    {"name": 'lisi1', "age": 19},
    {"name": 'wangwu1', "age": 17}
]


def getAge(element):
    return element['age']


# 传递给key参数的是一个函数,它指定可迭代对象中的每一个元素来按照该函数进行排序
userList.sort(key=getAge, reverse=True)
print(userList)

# 使用匿名函数时,使用sort函数中的key这个参数,来指定字典比大小的方法
# reverse参数控制升序与降序排列
userList.sort(key=lambda x: x['age'], reverse=True)
print(userList)

递归:

在函数内部,可以调用其他函数。

如果一个函数在内部调用自身,那么这个函数就是递归函数。

注意: 在函数内部调用其他函数不是函数的嵌套,而在函数内部定义子函数才是函数嵌套。

image.png

(图片源自网络侵删)

image.png

(图片源自网络侵删)

image.png

(图片源自网络侵删)

递归函数的特点:

  • 是一个函数
  • 函数执行过程中,自己调用自己
  • 一定有结束调用自己的条件
  • 效率不高

代码的特点:

函数内部的代码是相同的,只是针对参数不同,处理的结果不同;
当参数满足一个条件时,函数不再执行(即:函数的出口);

应用场景:

image.png

(图片源自网络侵删)

重复的去执行某个动作(递推)
递推+回归 = 递归
实例:
def printStr(n):
    if n == 0:
        return
    print('*', n)
    printStr(n - 1)  # 执行过程中,自己调用自己


printStr(5)

image.png

(图片源自网络侵删)

"""阶乘"""

def func(n):
    result = 1
    for i in range(1, n + 1):
        print(i)
        result *= i
    print(f'5的阶乘为:{result}')


func(5)
阶乘:
# 1、用正向递推的方式计算阶乘
def factorial(n):
    fact = 1
    for i in range(1, n + 1):
        fact *= i
    return fact


print(factorial(5))
# 2、递归实现阶乘
def factorial(n):
    if n == 1:
        return 1
    else:
        return n * factorial(n - 1)


result = factorial(5)
print(result)   # 120
"""
总结果: factorial(5)
第一次调用     factorial(5) =  5 * factorial(4)
第二次调用     factorial(4) =  4 * factorial(3)
第三次调用     factorial(3) =  3 * factorial(2)
第四次调用     factorial(2) =  2 * factorial(1)
第五次调用     factorial(1) =  1 
表达式:  5 * 4 * 3 * 2 *  1 
"""

factorial(5)  # 第 1 次调用使用 5
5 * factorial(4)  # 第 2 次调用使用 4
5 * (4 * factorial(3))  # 第 3 次调用使用 3
5 * (4 * (3 * factorial(2)))  # 第 4 次调用使用 2
5 * (4 * (3 * (2 * factorial(1))))  # 第 5 次调用使用 1
5 * (4 * (3 * (2 * 1)))  # 从第 5 次调用返回
5 * (4 * (3 * 2))  # 从第 4 次调用返回
5 * (4 * 6)  # 从第 3 次调用返回
5 * 24  # 从第 2 次调用返回
120  # 从第 1 次调用返回
"""阶乘:f(n) = n! = n * (n-1) * (n-2) * ... * 1"""


def fact(n):
    if n == 1:
        return 1
    else:
        return n * fact(n - 1)  # 递归调用"下家"完成f(n-1)的计算


print(fact(5))
斐波那契数列:
"""斐波那契数列:1,1,2,3,5,8,13,21,34,55,89..."""
"""f(0) = 1,f(1) = 1,f(n) = f(n-1) + f(n-2)"""

fib_mem = {1: 1, 2: 1, 3: 2, 4: 3, 5: 5, 6: 8, 7: 13, 8: 21}


def fibonacci(n):
    if n in fib_mem:
        return fib_mem[n]
    fib_mem[n] = fibonacci(n - 1) + fibonacci(n - 2)
    return fib_mem[n]


print(fibonacci(3))
"""递归打印 Fibonacci 数列
    1,1,2,3,5,8,13"""
"""方法1:非递归的写法"""


def fib(n):
    if n == 1 or n == 2:
        return 1
    a = 1
    b = 1
    for i in range(n - 2):
        temp = a + b
        a = b
        b = temp
    return b


print(fib(4))
"""方法2:使用递归"""


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


print(fbi(10))

image.png

(图片源自网络侵删)

image.png

(图片源自网络侵删)

image.png

(图片源自网络侵删)