Python一些我不懂的地方

Python一些我不懂的地方

再议 input
最后看一个有问题的条件判断。很多同学会用input()读取用户的输入,这样可以自己输入,程序运行得更有意思:

birth = input('birth: ')
if birth < 2000:
    print('00前')
else:
    print('00后')

输入1982,结果报错:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unorderable types: str() > int()

这是因为input()返回的数据类型是str,str不能直接和整数比较,必须先把str转换成整数。Python提供了int()函数来完成这件事情:

s = input('birth: ')
birth = int(s)
if birth < 2000:
    print('00前')
else:
    print('00后')

再次运行,就可以得到正确地结果。但是,如果输入abc呢?又会得到一个错误信息:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: 'abc'

原来int()函数发现一个字符串并不是合法的数字时就会报错,程序就退出了。

如何检查并捕获程序运行期的错误呢?后面的错误和调试会讲到。

continue

在循环过程中,也可以通过continue语句,跳过当前的这次循环,直接开始下一次循环。

n = 0
while n < 10:
    n = n + 1
    print(n)

上面的程序可以打印出1~10。但是,如果我们想只打印奇数,可以用continue语句跳过某些循环:

n = 0
while n < 10:
    n = n + 1
    if n % 2 == 0: # 如果n是偶数,执行continue语句
        continue # continue语句会直接继续下一轮循环,后续的print()语句不会执行
    print(n)

执行上面的代码可以看到,打印的不再是1~10,而是1,3,5,7,9。

可见continue的作用是提前结束本轮循环,并直接开始下一轮循环。

<think>嗯,用户之前问过如何查看微信小程序的后端代码,现在转向Python函数的递归原理,看来他们对编程概念感兴趣,可能刚开始学习编程。用户提到看不懂递归的原理,需要详细且易懂的解释。 首先,我需要确定用户的理解程度。他们可能已经知道函数的基本概念,但对递归这种自我调用的机制感到困惑。递归涉及到函数调用自身,这对新手来说可能有点抽象,容易和循环混淆。 接下来,我需要用简单明了的例子来说明递归的原理。比如阶乘或者斐波那契数列这样的经典例子,这些例子容易理解,并且能展示递归如何分解问题。同时,必须强调递归的两个关键点:基线条件和递归条件,避免无限递归。 用户可能对栈的概念太熟悉,所以解释递归的执行过程时,可以用更直观的方式,比如分解步骤,或者用比喻,比如俄罗斯套娃,一层层展开再一层层返回。这样可以帮助用户形象化递归的过程。 另外,用户可能担心递归的效率问题,比如堆栈溢出或者重复计算,可以简要提到尾递归优化或者记忆化技术,但重点还是先理解基本原理。 需要检查是否有术语使用当的地方,确保语言口语化,避免过于技术性的词汇。同时,结构要清晰,分步骤解释,可能用代码示例来辅助说明,但代码要简单,避免复杂语法干扰理解。 最后,总结递归的要点,对比循环,帮助用户巩固概念。确保回答真实可靠,例子正确,避免错误信息。可能用户后续还会问优化或应用场景的问题,但当前先解决原理的理解问题。</think>### **Python 函数递归原理详解** 递归(Recursion)是函数**直接或间接调用自身**的编程技巧,通过将复杂问题分解为**重复的子问题**来解决。理解递归的核心在于抓住两个关键点:**基线条件**(停止条件)和**递归条件**(调用自身的条件)。下面通过一个简单例子逐步拆解其原理。 --- #### **1. 递归的底层逻辑** 假设我们要计算阶乘 $n! = n \times (n-1) \times ... \times 1$,用递归实现如下: ```python def factorial(n): if n == 1: # 基线条件:当 n=1 时停止递归 return 1 else: # 递归条件:问题拆解为 n * (n-1)! return n * factorial(n-1) ``` ##### **执行过程分析(以 n=3 为例)** 1. **第一层调用** `factorial(3)`: - 检查 `3 == 1`?否 ➔ 执行 `3 * factorial(2)` - **暂停当前函数**,先计算 `factorial(2)` 2. **第二层调用** `factorial(2)`: - 检查 `2 == 1`?否 ➔ 执行 `2 * factorial(1)` - **再次暂停**,计算 `factorial(1)` 3. **第三层调用** `factorial(1)`: - 检查 `1 == 1`?是 ➔ 返回 `1` 4. **逐层返回结果**: - `factorial(1)` 返回 1 ➔ `factorial(2)` 计算 `2 * 1 = 2` - `factorial(2)` 返回 2 ➔ `factorial(3)` 计算 `3 * 2 = 6` - 最终结果:6 --- #### **2. 递归的“栈”结构** 递归调用依赖**调用栈(Call Stack)** 来管理函数状态: - **入栈**:每次函数调用自身时,当前函数的变量和状态被压入栈顶。 - **出栈**:当达到基线条件后,栈顶函数依次弹出并计算结果。 - **内存风险**:如果递归过深(如未正确设置基线条件),会导致栈溢出错误(Stack Overflow)。 ![递归调用栈示意图](https://example.com/recursion-stack.png) --- #### **3. 递归 vs. 循环** 递归和循环(如 `for`、`while`)都能解决重复性问题,但适用场景同: | 特点 | 递归 | 循环 | |--------------------|------------------------------|-------------------------| | **代码简洁性** | 更简洁(如树遍历) | 需手动管理状态 | | **内存消耗** | 高(栈空间占用) | 低 | | **问题适用性** | 适合分治问题(如汉诺塔) | 适合线性重复操作 | --- #### **4. 递归的经典案例** ##### **(1) 斐波那契数列** ```python def fib(n): if n <= 1: # 基线条件 return n else: # 递归条件 return fib(n-1) + fib(n-2) ``` **注意**:此实现效率低(重复计算),实际开发中需优化(如记忆化缓存)。 ##### **(2) 文件夹遍历** ```python import os def scan_dir(path): print("当前目录:", path) for file in os.listdir(path): full_path = os.path.join(path, file) if os.path.isdir(full_path): # 如果是子目录,递归扫描 scan_dir(full_path) else: print("文件:", full_path) ``` --- #### **5. 如何避免递归陷阱?** - **明确基线条件**:确保递归有终止点(例如 `n == 1`)。 - **控制递归深度**:Python 默认递归深度限制约为 1000 层(可通过 `sys.setrecursionlimit()` 修改,但推荐)。 - **优先考虑尾递归优化**(Python 未原生支持,但可通过装饰器实现)。 --- ### **总结** 递归的本质是**通过自我调用来分解问题**,其核心思维是: 1. **拆解问题**:将大问题转化为更小的同类问题。 2. **逐层解决**:从最小子问题开始,反向拼装最终结果。 **关键公式**: $$ \text{递归结果} = \text{当前操作} + \text{更小问题的递归结果} $$ 通过多练习简单案例(如阶乘、链表遍历),逐步培养递归思维!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值