在编写函数时调用函数本身,则称该函数为递归函数。 使用递归函数一般需要有明确的规律,比如常说的数学中计算阶乘的算法就可以使用递归函数,func(n)= n * func(n-1)。
阶乘是基斯顿·卡曼(Christian Kramp,1760~1826)于 1808 年发明的运算符号,是数学术语。一个正整数的阶乘n!=1×2×3×...×n。阶乘可以递归方式定义:n!=(n-1)!×n。
下面编写一个递归函数:
def factorial(num:int):
if num == 1:
return 1
else:
print(f'{num} * factorial({num - 1})')
return num * factorial(num - 1)
编写递归函数要一定注意给函数一个停止递归的条件,比如上面当数字为1时直接返回1,而不是继续调用函数本身,防止当递归次数越多时会出现堆栈溢出问题。
我们传入数字5,打印5的阶乘的结果:5*4*3*2*1 = 120
print(f'递归结果:{factorial(5)}')
#打印内容如下
5 * factorial(4) #num=5时打印
4 * factorial(3) #num=4时打印
3 * factorial(2) #num=3时打印
2 * factorial(1) #num=2时打印
递归结果:120
解析过程如下:
factorial(5) = 5 * factorial(4) = 5 * 4 * factorial(3) = 5 * 4 * 3 * factorial(2) = 5 * 4 * 3 * 2 * factorial(1) = 5 * 4 * 3 * 2 * 1 = 120
在不同的行业,在使用递归函数时有不同的应用场景,下面以买股票的例子介绍使用递归计算卖出股票时赚了多少钱。
买卖股票的原则:先买进的股票优先卖出。比如周一到周五我们明天都以不同的价格买进了同一只股票,买进数量和价格放入一个列表中:
[[100,98.5],[200,99.2],[100,97.5],[300,98.1],[200,99.4]]
当下一个交易日我卖出n股时,我们用递归函数计算赚了多少钱。(浮点数计算我们采用decimal 模块解决计算精度问题)
from decimal import Decimal
stock_list= [[100,98.5],[200,99.2],[100,97.5],[300,98.1],[200,99.4]]
def stock_bs(stock_list,sell_stock_count,sell_stock_price,num=0):
"""
:param stock_list: 股票信息列表
:param sell_stock_count: 卖出股票的数量
:param sell_stock_price: 卖出股票的价格
:param num: 从列表的该切片开始计算
:return:
"""
#定义股票信息列表的长度
length = len(stock_list)
if num == length:
return 0
if stock_list[num][0] >= sell_stock_count:
# 当卖出的股票数量小于等于某切片的买进股票数量时 不在递归 直接返回计算结果 否则执行else开始递归
return (Decimal(str(sell_stock_price)) - Decimal(str(stock_list[num][1]))) * sell_stock_count
else:
#递归后 卖出的量要减少
sell_stock_count -= stock_list[num][0]
#打印每一次递归计算公式 num起始为0
print(f'第{num+1}次递归 : 计算公式:({sell_stock_price} - {stock_list[num][1]}) * {stock_list[num][0]}')
#递归后num每次加1
num += 1
return (Decimal(str(sell_stock_price)) - Decimal(str(stock_list[num-1][1]))) * stock_list[num-1][0] \
+ stock_bs(stock_list,sell_stock_count,sell_stock_price,num=num)
print(f'赚的钱: {stock_bs(stock_list,800,99.2)}')
打印结果:
第1次递归 : 计算公式:(99.2 - 98.5) * 100
第2次递归 : 计算公式:(99.2 - 99.2) * 200
第3次递归 : 计算公式:(99.2 - 97.5) * 100
第4次递归 : 计算公式:(99.2 - 98.1) * 300
赚的钱: 550.0
print(f'赚的钱: {stock_bs(stock_list,100,99.2)}')
打印结果: 本次执行并未走入递归过程
赚的钱: 70.0
总结:
在实际使用过程中,肯定还有各式各样的需求等着大家探索实现,有些功能其实使用for循环也可以实现,或者更简单方便,但学习的过程我们需要探索不同的方法来填充自己的知识盲区,做到学以致用,学无止境。
----感谢读者的阅读和学习,谢谢大家。
共勉: 东汉·班固《汉书·枚乘传》:“泰山之管穿石,单极之绠断干。水非石之钻,索非木之锯,渐靡使之然也。”
-----指水滴不断地滴,可以滴穿石头;
-----比喻坚持不懈,集细微的力量也能成就难能的功劳。