零基础学 Python——函数(二)

函数(二)

各位亦菲彦祖你们好,欢迎回到 Python 函数的进阶篇!在上一篇内容里,我们已经学会了如何定义和调用函数,也了解了函数的参数和返回值,并简单体验了什么是一等公民函数。本篇将继续深入探讨更多关于函数的高级用法:交换变量值、冒泡排序、递归、lambda表达式以及高阶函数。让我们继续进阶,一起愉快地学习吧~


1. 交换变量值

1.1 背景介绍

在编写代码时,常常会遇到「交换两个变量的值」的需求。例如,变量 a = 10b = 20 时,你想把 a 的值变成 20b 的值变成 10。在其他编程语言里,有时需要借助第三个变量来完成。但在 Python 中,不仅可以用第三变量,还能一行搞定!

1.2 方法一:使用中间变量

下面这个例子演示了如何借助第三个变量 c 来完成交换:

a = 10
b = 20

# 1. 定义中间变量
c = a

# 2. 将 b 的数据存储到 a,此时 a = 20
a = b

# 3. 将 c(原 a)赋值到 b,此时 b = 10
b = c

print(a)  # 20
print(b)  # 10
小结
  1. 通过中间变量暂存数据,再进行替换;
  2. 方法直观易懂,但略显繁琐。

1.3 方法二:Python 一行搞定

Python 有一个语法糖,可以直接写成:

a, b = 1, 2
a, b = b, a
print(a)  # 2
print(b)  # 1

一句话就能完成交换!这也是 Python 强大又优雅的语言特性之一,推荐使用这一种方式。


2. 冒泡排序

2.1 算法简介

冒泡排序(Bubble Sort)是所有排序算法里相对简单易懂的一种。它的思路是:

  1. 比较相邻元素:如果前者比后者大,就交换它们;
  2. 一轮下来:「最大」的或「最小」的元素会被冒泡到一端;
  3. 重复执行:对剩余的元素再执行同样的操作,直到不需要交换为止。

虽然冒泡排序并不算效率最高的排序算法,但它是很多算法学习的启蒙算法,能够很好地帮助我们理解「排序」的逻辑。

2.2 代码实现

下面的例子演示如何使用冒泡排序将 [3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48] 从小到大进行排序,且不使用 Python 内置的排序函数

def bubbleSort(arr):
    n = len(arr)
    for i in range(n):
        # 内层循环负责比较相邻元素并交换
        for j in range(0, n - 1):
            if arr[j] > arr[j + 1]:
                # Python 直接支持 a, b = b, a 的交换
                arr[j], arr[j + 1] = arr[j + 1], arr[j]
    return arr

result = bubbleSort([3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48])
print(result)
# 结果:[2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]
小结
  • 如果想要从大到小排序,只需把 > 改成 < 即可;
  • 冒泡排序虽然简单,但在大数据量场景下性能较低,适合入门了解排序原理。

3. 递归(Recursion)

3.1 什么是递归

递归是一种让函数自己调用自己的编程思想,通常用来解决层次结构明晰、分而治之的问题。例如:

  1. 遍历文件夹:遍历某个文件夹时,如果遇到子文件夹,再遍历这个子文件夹…… 直到没有文件夹为止;
  2. 某些算法:快速排序、二叉树遍历、汉诺塔等。
3.1.1 递归的两大特点
  1. 函数内部自己调用自己
  2. 必须有出口 —— 否则会陷入无限循环。

3.2 代码示例:数字累加求和

下面的例子演示如何用递归实现 1 + 2 + ... + num 的结果:

def sum_numbers(num):
    # 出口(最简单的情况)
    if num == 1:
        return 1
    # 最关键的是这一步
    return num + sum_numbers(num - 1)

sum_result = sum_numbers(3)  # 计算 3 + 2 + 1
print(sum_result)  # 6

大致的过程是:

  • sum_numbers(3) 调用 sum_numbers(2)
  • sum_numbers(2) 又调用 sum_numbers(1)
  • sum_numbers(1) 返回 1
  • 最终汇总得到 3 + 2 + 1 = 6

3.3 应用案例:求阶乘

求 1~n 的阶乘

  1. 递归公式: n! = n * (n-1)!
  2. 出口: 1! = 1
def factorial(n):
    if n == 1:
        return 1
    return n * factorial(n - 1)

print(factorial(5))  # 5*4*3*2*1 = 120

4. lambda 表达式

4.1 何时用 lambda

如果一个函数:

  • 有一个返回值;
  • 函数体只有一句代码;

此时可以用 lambda 表达式替代,更加简洁。

4.2 语法

lambda 参数列表: 表达式
  • 参数列表:可以有,也可以没有。
  • 表达式:只能是一个表达式,不能写多行逻辑。
  • 返回值lambda 会返回表达式的计算结果。
4.2.1 快速入门
# 普通函数
def fn1():
    return 200

print(fn1())
# 200

# lambda
fn2 = lambda: 100
print(fn2())
# 100

可以看到,定义 fn2 时就直接把 lambda 表达式赋值给了 fn2。当我们执行 fn2() 时,就会得到返回值 100

4.3 常见示例

4.3.1 计算 a + b
  • 函数写法

    def add(a, b):
        return a + b
    
    print(add(1, 2))
    # 3
    
  • lambda 写法

    fn_add = lambda a, b: a + b
    print(fn_add(1, 2))
    # 3
    
4.3.2 lambda 的参数形式
  1. 无参数

    fn = lambda: 100
    print(fn())
    # 100
    
  2. 一个参数

    fn = lambda x: x ** 2
    print(fn(5))
    # 25
    
  3. 默认参数

    fn = lambda a, b, c=100: a + b + c
    print(fn(10, 20))
    # 130
    
  4. 可变参数 *args

    fn = lambda *args: args
    print(fn(10, 20, 30))
    # (10, 20, 30)
    

    这里返回一个元组。

  5. 可变参数 **kwargs

    fn = lambda **kwargs: kwargs
    print(fn(name='Python', age=20))
    # {'name': 'Python', 'age': 20}
    
4.3.3 带判断的 lambda
fn_max = lambda a, b: a if a > b else b
print(fn_max(1000, 500))
# 1000
4.3.4 在 sort() 中应用 lambda
students = [
    {'name': 'TOM', 'age': 20},
    {'name': 'ROSE', 'age': 19},
    {'name': 'Jack', 'age': 22}
]

# 按 name 升序
students.sort(key=lambda x: x['name'])
print(students)

# 按 name 降序
students.sort(key=lambda x: x['name'], reverse=True)
print(students)

# 按 age 升序
students.sort(key=lambda x: x['age'])
print(students)

5. 高阶函数

5.1 概念

把函数作为参数传入,这样的函数称为高阶函数。这种风格也体现了「函数式编程」的思想:大量使用函数,减少重复代码,让程序更短、更灵活。

5.2 体验高阶函数

  1. abs(-10) = 10:求绝对值
  2. round(1.9) = 2:四舍五入

需求:对任意两个数字做某种「预处理」后再求和。

  • 方法1(固定死 abs)

    def add_num(a, b):
        return abs(a) + abs(b)
    
    print(add_num(-1, 2))
    # 3
    

    这样可以,但如果以后需要对数字做别的处理(如 round),就得改函数。

  • 方法2(高阶函数)

    def sum_num(a, b, f):
        return f(a) + f(b)
    
    print(sum_num(-1, 2, abs))
    # 3
    
    print(sum_num(1.2, 3.9, round))
    # 1 + 4 = 5
    

    这样写,后续可以随意替换 f 为任何处理函数,代码更灵活。

5.3 Python 内置高阶函数

5.3.1 map()

map(func, lst) 会把 func 作用到 lst 的每个元素上,返回一个可迭代对象。

list1 = [1, 2, 3, 4, 5]

def func(x):
    return x ** 2

result = map(func, list1)

print(result)        # <map object ...>
print(list(result))  # [1, 4, 9, 16, 25]
5.3.2 zip()

zip() 用于将可迭代对象(列表、元组等)打包成元组,返回可迭代的 zip 对象。

a = [1, 2, 3]
b = [4, 5, 6]
c = [4, 5, 6, 7, 8]

result1 = zip(a, b)
print(list(result1))
# [(1, 4), (2, 5), (3, 6)]

result2 = zip(a, c)
print(list(result2))
# [(1, 4), (2, 5), (3, 6)]
# 以最短列表为基准打包
5.3.3 reduce()

reduce(func, lst) 会对参数序列里的元素进行累积运算;func 必须接收两个参数,每次执行的结果会继续参与下一次计算。

import functools

list1 = [1, 2, 3, 4, 5]

def func(a, b):
    return a + b

result = functools.reduce(func, list1)
print(result)  # 15
5.3.4 filter()

filter(func, lst) 会对 lst 里的元素进行筛选,保留 func(x) 返回 True 的元素。

list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

def func(x):
    return x % 2 == 0

result = filter(func, list1)
print(list(result))
# [2, 4, 6, 8, 10]

6. 练习题

各位亦菲彦祖你们好,下面是一些练习题,建议完成后再看参考答案哦~

  1. 递归求和

    • 尝试用递归写一个函数 sum_numbers(n),实现 1 + 2 + ... + n
    • 要求:若 n = 1,则直接返回 1 作为递归结束条件。
  2. 冒泡排序升级

    • 改写冒泡排序函数 bubbleSort(arr),让它能支持从小到大或从大到小排序:
      • 可通过传一个参数 reverse,默认是 False 表示从小到大,当 reverse=True 时从大到小。
    • 提示:只要在比较大小的时候做条件判断的调整即可。
  3. lambda 表达式进阶

    • 结合 lambdamap() 写一个代码,输入 [1, 2, 3, 4],输出每个元素的三次方 [1, 8, 27, 64]
    • 结合 lambdafilter(),筛选出 [1, -3, 9, -2, 0] 里所有大于 0 的数。
  4. 高阶函数应用

    • 用高阶函数写一个通用的「处理数字后再求和」函数 sum_func(a, b, f),并分别传入 absroundlambda x: x**2 等进行测试,观察结果是否正确。

7. 总结

恭喜各位亦菲彦祖你们好,学完了这一篇,你已经掌握了更多 Python 函数进阶技能。来回顾一下,本篇主要包含了:

  1. 交换变量值:利用 Python 的 a, b = b, a 语法糖,无需借助第三变量。
  2. 冒泡排序:学习了一种简单的排序方法,虽不高效,但很直观。
  3. 递归:函数内自我调用,必须有明确出口。
  4. lambda 表达式:让只有一行逻辑的函数写起来更短更优雅;它的参数可以是位置、默认、可变等多种形式。
  5. 高阶函数:将函数当作参数传递,减少重复代码,使程序更加灵活;包括 map()zip()reduce()filter() 等常见内置高阶函数。

在实际项目中,如果你能灵活运用这些知识点,就能够写出更简洁、可维护的 Python 代码。不要忘记多加练习,把理论化为实践,相信你很快就能体会到更高级的编程乐趣啦!

下次再见,各位亦菲彦祖你们好,继续加油哦~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杨胜增

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值