python生成器,递归调用

生成器

什么是生成器:只要在函数体内出现yield关键字,那么再执行函数就不会执行函数代码,会得到一个结果,该结果就是生成器

生成器就是迭代器

yield的功能

yield为我们提供了一种自定义迭代器对象的方法

yield与return的区别:

1.yield可以返回多个值

2.函数暂停和再继续是由yield帮我们保存的

 只要看见函数里出现yield,那么就是生成器

例1:上面我们说到,看见函数里有yield,那么就是生成器,生成器又是迭代器,

那么提到迭代器就要想到xx.__next__()取值方式

def test():
    print('=====>1')
    yield 1
    print('=====>2')
    yield 2
    print('=====>3')
    yield 3
g = test()  #就相当于一个容器
print(g.__next__())
print(g.__next__())
print(next(g))

运行结果:

我们知道这种方式取值之后,就会想到相同原理的另一个简单方式就是for循环

def test():
    print('=====>1')
    yield 1
    print('=====>2')
    yield 2
    print('=====>3')
    yield 3
g = test()
for i in g:
    print(i)

运行结果:

例2:将test1的结果被test2调用,这是就需要用yield自定义一个生成器

def test1():
    for i in range(10):
        yield i   #把0~9变成生成器返回给函数test1
g = test1()     #g是个生成器
def test2(g):
    for i in g:
        print(i)
test2(g)

运行结果:

 例3:日志报错监控器

import time
def tail(filepath):   #定义一个查看文件的函数
    with open(filepath, 'rb') as f:   #打开形参为filepath rb是二进制读
        f.seek(0,2)    #把光标移动到末尾
        while True:  #循环监控日志
            data = f.readline()   #读取文件末尾
            if data:   #加入有数据就用yield返回
                yield data
            else:#  否则就睡眠0.05秒
                time.sleep(0.05)
def grep(file, k):    #定义过滤关键字函数
    for i in tail(file):   #循环生成器中的数据
        if k in i.decode('utf-8'):  #因为是用二进制读取方式,所以需要解码显示
            print(i.decode('utf-8'))
grep('a.txt', '500')  #监控a.txt最新日志,并过滤500的错误代码

 一旦有500出现就会被抓拍到

yield的另一用法,赋值

def test(name):
    while True:
        foot = yield
        print('%s正在吃%s' % (name, foot))

e = test('轩轩') #e是生成器
next(e)    #初始化,e.__next__()
# e.send(None)    #初始化,与上一行二选一
e.send('饺子')    #发送值传给foot
e.send('冰激凌')    #发送值传给foot

运行结果:

递归调用

递归调用:在调用一个函数的过程中,直接或者间接又调用了函数本身,称之为递归调用

递归必备的2个阶段:1递推,2回溯

 例:甲乙丙丁戊,5人吃包子,我们想知道甲吃了几个包子,但甲说比乙多吃2个,乙说比丙多吃2个,丙说比丁多吃2个,丁说比戊多吃2个,戊说他没吃,

那么因为知道戊没吃,所以根据甲乙丙丁的答案,我们可知甲吃了8个,这样一来一回的过程就是递推和回溯

age(甲) = age(乙) + 2

age(乙) = age(丙) + 2

age(丙) = age(丁) + 2

age(丁) = age(戊) + 2

age(戊) = 0

def num(n):
    if n == 1:
        return 0
    return num(n-1) + 2
res = num(5) 
print(res)

运行结果:

 

转载于:https://www.cnblogs.com/liketimes/p/10007287.html

<think>好的,我现在需要回答用户关于Python递归调用原理及示例的问题。首先,我需要回顾一下递归的基本概念。递归是函数自己调用自己,通常用来解决可以分解为相同子问题的情况。不过,递归需要注意终止条件,否则会导致无限递归,比如栈溢出错误,这在引用[2]中提到过。 接下来,我应该用简单的中文解释递归的原理。可能从阶乘的例子开始,因为这是最经典的递归示例。需要说明递归函数的结构:基本情况(base case)和递归情况。比如阶乘的n=0或1时返回1,否则返回n乘以factorial(n-1)。同时要提到递归的工作流程,比如函数调用栈的形成,以及每次递归如何缩小问题规模。 然后,用户可能需要了解递归的应用场景。根据引用[3],递归常用于树形结构遍历、分治算法如快速排序等。可以举一个目录遍历的例子,或者斐波那契数列,不过斐波那契用递归效率低,这里可以提到尾递归优化或者迭代方法,但Python默认不支持尾递归优化,如引用[2]中的栈深度问题。 还要注意递归的优缺点。优点可能是代码简洁,容易理解;缺点是栈溢出风险和重复计算的问题,比如斐波那契数列中的重复计算。这时候可以提到记忆化(memoization)作为优化手段。 用户提供的引用中,引用[4]给出了一个递归函数的例子,但可能存在错误,比如终止条件是否正确。需要检查那个例子是否正确,比如g(n)的定义是否合理,是否会导致无限递归。例如,如果n从1开始,而终止条件是n==10,那么当调用g(1)时,会递归到g(0)、g(-1)等,直到超过最大递归深度,导致错误。这说明递归的终止条件必须正确设置,否则会引发问题,如引用[2]中的错误。 在示例代码方面,可能需要给出正确的递归例子,比如快速排序的实现,如用户提供的示例中的代码。不过用户的问题是关于递归的原理和示例,所以应该用更基础的例子,比如阶乘、斐波那契数列,或者遍历目录结构。 另外,需要提醒用户递归的注意事项,比如设置正确的终止条件,控制递归深度,或者考虑改用迭代方式。引用[3]中提到递归需要谨慎使用,避免无限递归,这也需要强调。 总结回答的结构:先讲原理,再给出示例代码,然后分析优缺点,最后应用场景和注意事项。同时,生成相关问题,如递归与迭代的区别、如何避免栈溢出、递归在算法中的应用等。</think>### Python递归调用原理及示例 #### 一、递归调用原理 递归是函数**直接或间接调用自身**的过程。其核心在于将复杂问题分解为**规模更小的同类子问题**,直到子问题足够简单可直接求解(称为**基本情况**)。递归通过**函数调用栈**实现,每次递归调用会将当前状态压入栈,直到达到基本情况后逐层返回结果[^3]。 #### 二、示例代码 1. **阶乘计算** $$n! = n \times (n-1)! \quad \text{(递归定义)}$$ ```python def factorial(n): if n == 0 or n == 1: # 基本情况 return 1 else: return n * factorial(n-1) # 递归调用 print(factorial(5)) # 输出120 ``` 2. **遍历嵌套列表** ```python def flatten(lst): result = [] for item in lst: if isinstance(item, list): # 若元素是列表,递归展开 result.extend(flatten(item)) else: result.append(item) return result print(flatten([1, [2, [3, 4], 5]])) # 输出[1, 2, 3, 4, 5] ``` #### 三、优缺点分析 | **优点** | **缺点** | |------------------------------|------------------------------| | 代码简洁易读(如分治算法) | 栈溢出风险(Python默认递归深度约1000层)[^2] | | 天然适合树/图结构处理 | 重复计算(如斐波那契数列递归) | #### 四、注意事项 1. **必须设置终止条件**,否则导致无限递归(如引用[4]中的`g(n)`函数若调用`g(1)`会触发`RecursionError`)。 2. **尾递归优化**:Python未原生支持,可通过装饰器或改写为循环实现[^3]。 3. **性能优化**:对存在重复子问题的递归(如斐波那契),使用**记忆化缓存**(`lru_cache`装饰器)。 #### 五、应用场景 - **数据结构遍历**:二叉树、多级目录结构 - **分治算法**:快速排序、归并排序 - **动态规划问题**:背包问题(递归+记忆化) - **数学问题**:汉诺塔、组合数计算 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值