目录
2.每进行更深一步的递归,问题规模相比上一次递归都要有所减少
闭包
什么是闭包:
闭包是指在一个函数内部定义的函数,并且这个内部函数引用了外部函数的变量。即使外部函数已经执行完毕,内部函数仍然可以访问和操作这些变量
闭包的基本结构:
def outer_function(x):
def inner_function(y):
return x + y
return inner_function
closure = outer_function(10)
print(closure(5)) # 输出 15
接下来我为大家解释一下这段代码:
outer_function
是外部函数,它接受一个参数x
。inner_function
是内部函数,它接受一个参数y
,并且引用了外部函数的变量x
。outer_function
返回inner_function
,而不是调用它。当我们调用
outer_function(10)
时,它返回inner_function
,并且x
被设置为10
。然后我们调用
closure(5)
,实际上是在调用inner_function(5)
,此时x
仍然是10
,所以结果是15
实现闭包的条件:
1.嵌套函数
闭包必须在一个外部函数中定义一个内部函数。也就是说,函数内部再定义一个函数。
def outer_function():
def inner_function():
pass
return inner_function
2.内函数引用外部函数的变量
内部函数必须引用外部函数的变量(即自由变量)。这是闭包的核心,内部函数通过引用外部函数的变量来“记住”外部函数的环境。
def outer_function(x):
def inner_function(y):
return x + y # 内部函数引用了外部函数的变量 x
return inner_function
3.外部函数返回内部函数
外部函数必须返回内部函数(而不是调用它)。这样,内部函数可以在外部函数执行完毕后继续存在,并且仍然可以访问外部函数的变量。
def outer_function(x):
def inner_function(y):
return x + y
return inner_function # 返回内部函数,而不是调用它
closure = outer_function(10)
print(closure(5)) # 输出 15
4.外部函数已经执行完毕
闭包的特性在于,即使外部函数已经执行完毕,内部函数仍然可以访问外部函数的变量。这是因为闭包将外部函数的变量“捕获”并保存在内部函数的环境中。
def outer_function(x):
def inner_function(y):
return x + y
return inner_function
closure = outer_function(10) # 外部函数执行完毕,x 被设置为 10
print(closure(5)) # 内部函数仍然可以访问 x,输出 15
总结一下:
嵌套函数:在一个函数内部定义另一个函数。
内部函数引用外部函数的变量:内部函数必须引用外部函数的变量。
外部函数返回内部函数:外部函数返回内部函数,而不是调用它。
外部函数已经执行完毕:即使外部函数执行完毕,内部函数仍然可以访问外部函数的变量。
这些条件共同作用,使得闭包能够“记住”其定义时的环境,并在后续调用中继续使用这些环境中的变量。
递归函数
什么是递归函数:
递归函数(Recursive Function)是指在函数的定义中调用函数自身的函数。递归是一种强大的编程技术,特别适用于解决可以分解为相似子问题的问题。理解递归的概念和应用场景,可以帮助你编写更加简洁和优雅的代码。
递归函数条件
1.必须有个明确的结束条件 ———递归出口
2.每进行更深一步的递归,问题规模相比上一次递归都要有所减少
3.相邻两次重复之间有紧密联系
递归的基本结构
def recursive_function(parameters):
if base_case_condition(parameters): # 基准条件
return base_case_value
else:
# 递归条件
return recursive_function(modified_parameters)
分析一下这段代码
1.函数定义:
recursive_function
是一个递归函数,它接受一个或多个参数parameters
。参数
parameters
是递归函数的输入,通常用于表示当前问题的状态或规模。
2. 基准条件(Base Case)
if base_case_condition(parameters):
这是递归的终止条件。
base_case_condition(parameters)
是一个判断条件,用于检查当前参数是否满足递归终止的条件。如果满足基准条件,函数直接返回
base_case_value
,不再进行递归调用。基准条件的作用:防止无限递归,确保递归最终能够终止。
示例:
在这个例子中,n == 0
是基准条件,当 n
为 0
时,递归停止,函数返回 1
3. 递归条件(Recursive Case)
else:
如果基准条件不满足,函数进入递归条件。
在递归条件中,函数会调用自身(即
recursive_function
),但传入的参数会被修改(modified_parameters
)。修改参数的目的是将问题规模缩小,逐步逼近基准条件。
def factorial(n): if n == 0: # 基准条件 return 1 else: # 递归条件 return n * factorial(n - 1)
在这个例子中,
factorial(n - 1)
是递归调用,每次递归调用时,n
的值都会减小,逐步逼近基准条件n == 0
。
典型的递归函数的例子
1.
1到100的相加
(一般方法)
# def add():
# s=0
# for i in range(1,101):
# s +=i
# print(s)
# add()
采用递归
# def add(n):
# if n ==1:
# return 1
#
# return n +add(n-1)
# print(add(100))
2.斐波那契数列
def fibonacci(n):
if n == 0: # 基准条件
return 0
elif n == 1: # 基准条件
return 1
else:
return fibonacci(n - 1) + fibonacci(n - 2) # 递归条件
print(fibonacci(10)) # 输出 55
这个例子中:
当
n
为0
或1
时,函数返回相应的基准值。否则,函数返回
fibonacci(n - 1) + fibonacci(n - 2)
,即前两个斐波那契数的和。
递归的优缺点
优点
简洁性:递归代码通常比迭代代码更简洁和易读。
自然表达:对于某些问题(如树遍历、分治算法等),递归提供了一种自然的表达方式
缺点
性能问题:递归可能会导致大量的函数调用,增加栈的深度,从而影响性能。
栈溢出:如果递归深度过大,可能会导致栈溢出错误。
重复计算:在某些情况下(如斐波那契数列的简单递归实现),递归可能会导致大量的重复计算。
递归的应用场景
树和图的遍历:递归非常适合用于树和图的遍历(如深度优先搜索)。
分治算法:许多分治算法(如归并排序、快速排序)都使用递归来分解问题。
动态规划:递归常用于动态规划问题的初始实现,然后可以通过记忆化或迭代来优化。
递归的注意事项
确保基准条件正确:基准条件是递归终止的关键,必须确保它能够正确终止递归。
避免无限递归:如果递归条件没有正确地向基准条件靠近,可能会导致无限递归,最终导致栈溢出。
考虑性能问题:对于性能敏感的应用,可能需要将递归转换为迭代,或使用记忆化来优化递归。
总结一下: 递归函数是一种强大的编程工具,特别适用于解决可以分解为相似子问题的问题。理解递归的基本概念、优缺点和应用场景,可以帮助你编写更加简洁和优雅的代码。然而,递归也需要谨慎使用,特别是在性能敏感的应用中