《嵌入式AI筑基笔记04:python函数与模块01---从C的刻板到Python的灵动》
前言
C语言的函数,是程序的骨架------必须声明返回类型,参数传递非值即指针,作用域简单直接,模块化靠头文件和源文件分割。这些规则清晰且严谨,稍有越界就是编译错误或内存异常。
Python的函数简洁且灵活:不用声明类型,想返回几个值都行,参数可以缺省、可以命名、可以变长,甚至可以在函数内部再定义函数。而模块机制让代码复用变得像呼吸一样自然,任何 .py 文件都能直接导入,不需要头文件、不需要库链接。
这一篇,我们将深入Python的函数与模块,以一个C程序员的视角,看看到底是哪些设计让Python的函数如此灵活,又有哪些陷阱需要避开。
原文内容过长,为了方便阅读,将内容拆分成函数和模块两篇文章,本章聚焦于函数。

函数定义

定义
使用 def 关键字定义函数。
go
# 使用 def 关键字定义函数
def func():
print("hello")
func() # 调用函数 hello
func() # 调用函数 hello
def func2(a, b):
print(f'a = {a}, b = {b}')
func2(1, 2) # 传递参数 a = 1, b = 2
func2(3, 4) # 传递参数 a = 3, b = 4
C语言视角
• C必须明确参数类型和返回值类型,Python是动态类型,任何类型都可传入。
• C需要先声明后使用(或头文件),Python只需定义在调用前。
参数

无参数
Python函数可以不接收任何参数。
go
# 无参数情况
def func3(): # 无参数
print("hello")
func3() # 调用函数 hello
位置参数
最常见的参数传递方式,调用时按定义顺序传入。
go
# 位置参数
def func4(a, b):
print(f'a = {a}, b = {b}')
func4(1, 2) # 传递参数 a = 1, b = 2
默认参数
为参数指定默认值,调用时可省略。
C无此特性
go
# 默认参数,c=3
def func5(a, b, c=3):
print(f'a = {a}, b = {b}, c = {c}')
func5(1, 2) # 传递参数 a = 1, b = 2, c = 3
func5(1, 2, 5) # 传递参数 a = 1, b = 2, c = 5
关键字参数
调用时指定参数名,顺序可任意。
C只能按位置传参。
go
# 关键字参数, 一般和默认参数结合,体现在传参时
def func6(a, b, c=7, d=5):
print(f'a = {a}, b = {b}, c = {c}, d = {d}')
func6(1, 2, 3) # d 使用默认参数 a = 1, b = 2, c = 3, d = 5
func6(1, 2, d=9) # c 使用默认参数 a = 1, b = 2, c = 7, d = 9
可变参数

*args:接收任意多个位置参数,打包为元组。
**kwargs:接收任意多个关键字参数,打包为字典。
两者可混合使用,但 *args 必须在 **kwargs 之前。
go
# *args: 接收任意多个位置参数, 元组
def func7(*args):
print(args)
func7(1) # 接收 1 个参数 (1,)
func7(1, 2, 3) # 接收 3 个参数 (1, 2, 3)
# **kwargs: 接收任意多个关键字参数, 字典
def func8(**kwargs):
print(kwargs)
func8(a=1, b=2) # 接收 2 个关键字参数 {'a': 1, 'b': 2}
func8(c=4, d=5, e=6) # 接收 3 个关键字参数 {'c': 4, 'd': 5, 'e': 6}
C语言视角
• C语言可变参数通过 stdarg.h 实现,但需要手动处理类型,且不能处理关键字参数。
• Python的 *args 和 **kwargs 让函数接口非常灵活。
参数解包
将序列或字典解包后传入函数。
go
# 参数解包,将序列或字典解包后传递给函数
def add(a, b, c):
return a + b + c
nums = [1, 2, 3]
print(add(*nums)) # 6,相当于 add(1,2,3)
info = {'a': 2, 'b': 3, 'c': 4}
print(add(**info)) # 9,相当于 add(a=2,b=3,c=4)
传参本质

Python是"对象引用传递"。区分可变/不可变即可
• 不可变对象(int, str, tuple):形参修改不影响实参。
• 可变对象(list, dict, set):修改内容影响实参。
go
def modify(x, lst):
x = 10 # 重新绑定局部变量x,外部不受影响
lst.append(4) # 修改列表内容,外部受影响
a = 5
b = [1, 2, 3]
modify(a, b)
print(a) # 5
print(b) # [1, 2, 3, 4]
C语言视角
• C需区分值传递和指针传递。
• Python则统一为对象引用,只关注对象是否可变。
返回值

特点
• return 返回结果,无 return 默认返回 None。
• return 立即结束函数。
• 可返回多个值,实际是元组。
go
# 返回值
# 单返回值情况
def func9(a, b):
s = a + b
return s
print(func9(1, 2)) # 返回 1+2 的值 3
print(func9(10, 55)) # 返回 10+55 的值 65
# 多返回值,实际为元组
def get_min_max(numbers):
return min(numbers), max(numbers)
result = get_min_max([3, 1, 4, 2])
print(result) # (1, 4)
print(type(result)) # <class 'tuple'>
min_val, max_val = get_min_max([3, 1, 4, 2])
print(min_val, max_val) # 1 4
C语言视角
• C返回多个值需用指针参数或结构体。
• Python的元组解包更自然,且不需要预先分配变量。
函数名

特点
• 函数名称既是函数名,也是指向该函数的变量(对象)。
• 只要是指向该函数的变量,就可以调用该函数。
• Python中函数可赋值、传参、返回。
go
# 函数名,也是指向该函数的变量(对象)
def func10(x):
return x*x
f3 = func10 # 给 f3 赋值函数名,相当于函数指针
f4 = func10(7) # f4 接收 func10(7) 的返回值
print(f3(5), f4) # 25 49
def square(x):
return x ** 2
def cube(x):
return x ** 3
funcs = [square, cube] # 类似C函数指针数组
for f in funcs:
print(f(3), end=" ") # 9, 27
print()
C语言视角
• 类似函数指针,但Python无需 * 和解引用,更简洁。
作用域

局部变量
函数内部定义的变量默认为局部,函数外部不可见。
全局变量
函数内部可以读取全局变量,但要修改必须用 global 声明。
go
# 作用域
# 局部变量和全局变量
m = 10
n = 20
def func11():
global m
m = 15 # global声明使用全局变量,修改对函数外也起作用
n = 30 # 定义的局部变量,修改函数内的值,函数外不起作用
print(m, n) # 15 30
func11()
print(m, n) # m 被函数修改过 15 20
嵌套函数
函数内部可以定义函数。
闭包:内部函数可访问外部函数的变量,即使外部已返回。
go
# 函数嵌套与闭包
def outer(x):
def inner(y):
return x + y
return inner
add5 = outer(5) # add5 是一个闭包,记住了 x=5
print(add5(3), add5(10)) # 8 15
nonlocal 声明
嵌套函数中修改外层(非全局)变量,需 nonlocal
go
# nonlocal声明
# nonlocal 函数嵌套时用
m = 10
n = 20
def func12():
m = 12
n = 32
def func13():
nonlocal m
m = 17 # nonlocal声明使用全局变量,修改对函数fun也起作用
n = 22 # 定义的局部变量,修改函数内的值,函数外不起作用
print(f'func13: {m} , {n}') # func13: 17 , 22
func13()
print(f'func12: {m} , {n}') # fun: 17 , 32
func12()
print(f'main: {m} , {n}') # main: 10 , 20
匿名函数

特点
• 匿名性:没有函数名,通常直接使用。
• 简洁性:一行代码定义,适合简单逻辑。
• 表达式限制:只能包含一个表达式,不能有循环、分支等复杂逻辑。
• 自带 return:表达式结果自动返回。
作用
快速定义简单、一次性使用的小函数。
基础语法
go
lambda 参数列表: 表达式
• 参数列表:支持位置参数、默认参数。
• 表达式:只能是单个表达式,结果自动返回。
go
# 匿名函数,lambda
# 快速定义简单的、一次性使用的小函数
def add(a, b):
return a+b
la_ = lambda a, b: a + b # 等价于 add 函数
print(add(1, 2)) # 调用 add 函数 3
print(la_(3, 4)) # 调用 lambda 函数 7
print((lambda a, b: a + b)(5, 7)) # 直接调用lambda函数 12
高阶用法
sorted 排序

• sorted(iterable, key=None, reverse=False)
• iterable:待排序的可迭代对象。
• key:指定排序依据的函数,接收一个参数。
• reverse:True 降序,False 升序(默认)。
go
# sorted 结合排序
# 基本用法:不指定key,默认排序;指定key,key作为排序依据。
# 理解:将列表每个元素进行key指定的函数进行处理后,再用处理完成的值进行排序。
# 示例:加入我需要对列表中每个奇数进行符号反转后再排序,反转后为 [3, -2, -1, -5]
def func14(x):
if x % 2 == 0:
return x
else:
return -x
nums = [-3, 1, -2, 5]
news = sorted(nums) # 没有 key,默认排序
new2 = sorted(nums, key=func14) # 按照func14指定函数处理后排序
print(news, new2) # [-3, -2, 1, 5] [5, -2, 1, -3]
高阶示例
• 字符串按长度排序
• 元组列表按最后位置元素排序
• 字典按值排序(先转成键值对列表)
• 列表数字按绝对值排序
go
# 高阶示例
# 字符串按长度排序
words = ["apple", "banana", "cat1", "dog"]
new1 = sorted(words, key=lambda x:len(x))
print(new1) # ['dog', 'cat1', 'apple', 'banana']
# 元组列表按最后位置元素排序
data = [(1, 3, 5), (4, 1, 2), (2, 2, 7)]
new1 = sorted(data, key=lambda x: x[-1])
print(new1) #[(4, 1, 2), (1, 3, 5), (2, 2, 7)]
# 字典按值排序(先转成键值对列表)
score_dict = {"math": 88, "english": 92, "chinese": 90}
print(score_dict.items()) #dict_items([('math', 88), ('english', 92), ('chinese', 90)])
new1 = sorted(score_dict.items(), key=lambda x:x[1])
print(new1) # [('math', 88), ('chinese', 90), ('english', 92)]
# 按绝对值排序
nums = [-3, 1, -2, 5]
new1 = sorted(nums, key=lambda x:abs(x))
print(new1) # [1, -2, -3, 5]
map 批处理

• map(function, *iterables)
• function:应用的函数
• *iterables:一个或多个可迭代对象,数量决定 function 的参数个数
go
# map 结合批处理
# 基本用法,示例:求几个数的平方
li = [1, 3, 5, 7, 9]
def pow(x):
return x ** 2
print(list(map(pow, li))) # [1, 9, 25, 49, 81]
高阶示例
• 求几个数的平方
• 字符串列表转大写
• 两个列表对应元素相加
• 三个列表拼接成元组
go
# 高阶用法
# 求几个数的平方
li = [1, 3, 5, 7, 9]
new1 = list(map(lambda x:x**2, li))
print(new1) # [1, 9, 25, 49, 81]
#字符串列表转大写
words = ["hello", "world", "python"]
new1 = list(map(lambda x:x.upper(), words))
print(new1) # ['HELLO', 'WORLD', 'PYTHON']
# 两个列表对应元素相加
nums1 = [1, 2, 3]
nums2 = [10, 20, 30]
new1 = list(map(lambda x,y: x+y, nums1, nums2))
print(new1) # [11, 22, 33]
# 三个列表拼接成元组
a = [1, 2]
b = ["a", "b"]
c = [True, False]
print(list(map(lambda x,y,z:(x, y, z), a, b, c))) # [(1, 'a', True), (2, 'b', False)]
filter 过滤

• filter(function, iterable)
• function:过滤条件函数,返回 True 的元素保留
• iterable:待过滤的可迭代对象
go
# filter结合 过滤处理
# 基本用法,示例:过滤列表中的偶数
def is_even(n):
return n % 2 == 0
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
even_numbers = filter(is_even, numbers)
print(list(even_numbers)) # 输出: [2, 4, 6, 8, 10]
高阶示例
• 筛选列表中的奇数
• 筛选长度大于2的字符串
• 筛选字典列表中满足条件的元素
go
# 高阶用法
# 筛选列表中的奇数
nums = [1, 2, 3, 4, 5, 6]
new1 = list(filter(lambda x:x%2!=0, nums))
print(new1) # [1, 3, 5]
# 筛选长度大于2的字符串
words = ["a", "ab", "abc", "abcd"]
new1 = list(filter(lambda x:len(x)>2, words))
print(new1) # ['abc', 'abcd']
# 筛选字典列表中满足条件的元素
students = [
{"name": "Alice", "score": 85},
{"name": "Bob", "score": 60},
{"name": "Charlie", "score": 90}
]
# 筛选成绩≥80的学生
new1 = list(filter(lambda x:x["score"] > 80, students))
print(new1) # [{'name': 'Alice', 'score': 85}, {'name': 'Charlie', 'score': 90}]
C语言视角
• C没有匿名函数,但可以用函数指针和静态函数模拟,代码会冗长许多。
特殊函数

回调
本质将函数指针当做参数传给另一个函数,供另一个函数调用。
go
# 回调函数
def fn(x, cb):
print(x, cb(x))
def callback(x):
return x**2
fn(5, callback) # 回调函数 5 25
递归
自己调用自己,关键:找公式 + 找临界值。
go
# 递归处理
# 求5的阶乘(使用函数递归)
# 1. 找公式:n! = n * (n-1)!
# 2. 找临界值(递归结束条件):n=1, fn(1) = 1
def fn(n):
if n <= 1: # 递归结束条件
return 1
else: # 递归执行体
return n * fn(n-1)
print(fn(5)) # 120
# 封装函数,传入m,得到第m个斐波那契数 # 1 1 2 3 5 8 13 21
def f(n):
if n <= 2:
return 1
else:
return f(n-1) + f(n-2)
print(f(6)) # 8
# 兔子繁殖问题。 设有一对新生的兔子,从第4个月开始他们每个月月初都生一对新兔子,
# 新生的兔子从第4个月开始又每个月月初生一对兔子。 按此规律,并假定兔子没有死亡,20个月末共有多少对兔子?
# 当月的兔子 = 上个月的兔子 + 三个月前的兔子数(三月前的兔子会生下一批,刚好在本月生产新兔子)
def f(n):
if n <= 3:
return 1
else:
return f(n-1) + f(n-3)
print(f(20)) # 872
练习

回文数
go
# 封装一个函数 验证一个数是否是回文:str(n)[::-1] == str(n)
# 回文: 颠倒过来 与 自身数据一样的称为回文 例如 111 121 1221 12321
def fn1(n) -> bool:
return str(n)[::-1] == str(n) # 强转成字符串,后倒序与正序相比
print(fn1(12321), fn1(123)) # True False
多值统计
go
# 封装一个函数,获取多个数中的最小值,最大值,和,以及平均值
def fn2(*args) -> tuple:
return max(args), min(args), sum(args)/len(args)
print(fn2(1, 3, 4, 7, -4)) # (7, -4, 2.2)
数值统计
go
# 封装一个函数 获取多个数中的平均值并统计其中高于平均数的值个数
def fn3(*args) -> tuple:
avg = sum(args)/len(args)
count = 0
for arg in args:
if arg > avg:
count += 1
return avg, count
print(fn3(1, 6, 3, 5)) # (3.75, 2)
水仙花数
go
# 封装一个函数,获取所有的水仙花数
# 水仙花数是指一个3位数,它的每个位上的数字的3次幂之和等于它本身
# (例如:1^3 + 5^3+ 3^3 = 153)
def fn4(x):
return (((x // 100) ** 3) + ((x // 10 % 10) ** 3) + ((x % 10) ** 3)) == x
print(list(filter(fn4, range(100, 999)))) # [153, 370, 371, 407]
万年历
go
# 实现万年历效果图,使用函数封装
# A:先输出提示语句,并接受用户输入的年、月。
def fa():
year = int(input("请输入年份:"))
month = int(input("请输入月份:"))
fh(year,month)
# B:根据用户输入的年,先判断是否是闰年。
def fb(year):
return (year % 4 == 0 and year % 100 != 0) or year % 400 == 0
# C:根据用户输入的月来判断月的天数。
def fc(year, month):
if month == 2:
return 29 if fb(year) else 28
elif month in [4, 6, 9, 11]:
return 30
elif month in [1, 3, 5, 7, 8, 10, 12]:
return 31
else:
return 0
# D:用循环计算用户输入的年份距1900年1月1日的总天数。
def fd(year):
s = 0
for i in range(1900, year):
s += 366 if fb(i) else 365
return s
# E:用循环计算用户输入的月份距输入的年份的1月1日共有多少天,
def fe(year, month):
s = 0
for i in range(1, month):
s += fc(year, i)
return s
# F:相加D与E的天数,得到总天数。
def ff(year, month):
return fd(year) + fe(year, month)
# G:用总天数来计算输入月的第一天的星期数
def fg(year, month):
return ff(year, month) % 7
# H:根据G的值,格式化输出这个月的日历!
def fh(year, month):
# 打印第一行
print('一', '二', '三', '四', '五', '六', '日', sep='\t')
# 打印空格
for m in range(1, fg(year, month)+1):
print("\t", end ="")
# 打印日期
for i in range(1, fc(year, month)+1):
print(i, end="\t")
# 每一周换行
if (i+fg(year, month)) % 7 == 0:
print()
# 请输入年份:2026
# 请输入月份:3
# 一 二 三 四 五 六 日
# 1
# 2 3 4 5 6 7 8
# 9 10 11 12 13 14 15
# 16 17 18 19 20 21 22
# 23 24 25 26 27 28 29
# 30 31
fa()
总结
从C到Python,函数的演进体现了从"机器思维"到"人的思维"的转变:
• 函数定义:无需类型声明,可返回多值,支持文档字符串,让代码自解释。
• 参数系统 :默认参数、关键字参数、可变参数、参数解包,让函数接口极其灵活,同时 *args 和 **kwargs 能应对任意调用场景。
• 作用域与闭包 :nonlocal 支持闭包修改外层变量,使得Python也能实现函数式编程风格。
• 匿名函数:lambda 让简单函数定义更快捷,配合高阶函数发挥巨大作用。
当然,Python的灵活性也带来了一些陷阱:默认参数的共享问题、可变对象的副作用、作用域的意外引用。但只要理解了背后的原理,这些都可以轻松避免。
本章仅介绍函数,想获取模块及完整代码内容,请参考《嵌入式AI筑基笔记04:python函数与模块02---从C的刻板到Python的灵动》。
下一站,我们将进入面向对象的世界,看看Python的类如何实现封装、继承和多态,与C的结构体和函数指针又有何不同。
接下来学什么
第一篇:语法规则(与 C 的对比) ✅ 已完成
第二篇:数据结构:列表、元组、字典、集合 ✅ 已完成
第三篇:流程控制:条件、循环、推导式 ✅ 已完成
第四篇:函数与模块:定义、参数、作用域 ✅ 已完成
第五篇:对象和类:Class ⏳ 准备中
第六篇:文件操作与异常处理 ⏳
第七篇:NumPy 入门:像操作内存一样操作数据 ⏳
第八篇:Pandas 基础:给数据"做表格" ⏳
一步一步来,不急。
完整代码
go
'''
* @Filename : python_function.py
* @Revision : $Revision: 1.00 $
* @Author : Feng(更多编程相关的知识和源码见微信公众号:不只会拍照的程序猿,欢迎订阅)
* @Description : python 函数
'''
# ###################### 函数 ###################### #
# 函数定义
# 使用 def 关键字定义函数
def func():
print("hello")
func() # 调用函数 hello
func() # 调用函数 hello
def func2(a, b):
print(f'a = {a}, b = {b}')
func2(1, 2) # 传递参数 a = 1, b = 2
func2(3, 4) # 传递参数 a = 3, b = 4
# 传参
# 无参数情况
def func3(): # 无参数
print("hello")
func3() # 调用函数 hello
# 位置参数
def func4(a, b):
print(f'a = {a}, b = {b}')
func4(1, 2) # 传递参数 a = 1, b = 2
# 默认参数,c=3
def func5(a, b, c=3):
print(f'a = {a}, b = {b}, c = {c}')
func5(1, 2) # 传递参数 a = 1, b = 2, c = 3
func5(1, 2, 5) # 传递参数 a = 1, b = 2, c = 5
# 关键字参数, 一般和默认参数结合,体现在传参时
def func6(a, b, c=7, d=5):
print(f'a = {a}, b = {b}, c = {c}, d = {d}')
func6(1, 2, 3) # d 使用默认参数 a = 1, b = 2, c = 3, d = 5
func6(1, 2, d=9) # c 使用默认参数 a = 1, b = 2, c = 7, d = 9
# *args: 接收任意多个位置参数, 元组
def func7(*args):
print(args)
func7(1) # 接收 1 个参数 (1,)
func7(1, 2, 3) # 接收 3 个参数 (1, 2, 3)
# **kwargs: 接收任意多个关键字参数, 字典
def func8(**kwargs):
print(kwargs)
func8(a=1, b=2) # 接收 2 个关键字参数 {'a': 1, 'b': 2}
func8(c=4, d=5, e=6) # 接收 3 个关键字参数 {'c': 4, 'd': 5, 'e': 6}
# 参数解包,将序列或字典解包后传递给函数
def add(a, b, c):
return a + b + c
nums = [1, 2, 3]
print(add(*nums)) # 6,相当于 add(1,2,3)
info = {'a': 2, 'b': 3, 'c': 4}
print(add(**info)) # 9,相当于 add(a=2,b=3,c=4)
# 参数传递本质:对象引用传递
def modify(x, lst):
x = 10 # 重新绑定局部变量x,外部不受影响
lst.append(4) # 修改列表内容,外部受影响
a = 5
b = [1, 2, 3]
modify(a, b)
print(a, b) # 5 [1, 2, 3, 4]
# 返回值
# 单返回值情况
def func9(a, b):
s = a + b
return s
print(func9(1, 2)) # 返回 1+2 的值 3
print(func9(10, 55)) # 返回 10+55 的值 65
# 多返回值,实际为元组
def get_min_max(numbers):
return min(numbers), max(numbers)
result = get_min_max([3, 1, 4, 2])
print(result) # (1, 4)
print(type(result)) # <class 'tuple'>
min_val, max_val = get_min_max([3, 1, 4, 2])
print(min_val, max_val) # 1 4
# 函数名,也是指向该函数的变量(对象)
def func10(x):
return x*x
f3 = func10 # 给 f3 赋值函数名,相当于函数指针
f4 = func10(7) # f4 接收 func10(7) 的返回值
print(f3(5), f4) # 25 49
def square(x):
return x ** 2
def cube(x):
return x ** 3
funcs = [square, cube] # 类似C函数指针数组
for f in funcs:
print(f(3), end=" ") # 9, 27
print()
# 作用域
# 局部变量和全局变量
m = 10
n = 20
def func11():
global m
m = 15 # global声明使用全局变量,修改对函数外也起作用
n = 30 # 定义的局部变量,修改函数内的值,函数外不起作用
print(m, n) # 15 30
func11()
print(m, n) # m 被函数修改过 15 20
# 函数嵌套与闭包
def outer(x):
def inner(y):
return x + y
return inner
add5 = outer(5) # add5 是一个闭包,记住了 x=5
print(add5(3), add5(10)) # 8 15
# nonlocal声明
# nonlocal 函数嵌套时用
m = 10
n = 20
def func12():
m = 12
n = 32
def func13():
nonlocal m
m = 17 # nonlocal声明使用全局变量,修改对函数fun也起作用
n = 22 # 定义的局部变量,修改函数内的值,函数外不起作用
print(f'func13: {m} , {n}') # func13: 17 , 22
func13()
print(f'func12: {m} , {n}') # fun: 17 , 32
func12()
print(f'main: {m} , {n}') # main: 10 , 20
# 匿名函数,lambda
# 快速定义简单的、一次性使用的小函数
def add(a, b):
return a+b
la_ = lambda a, b: a + b # 等价于 add 函数
print(add(1, 2)) # 调用 add 函数 3
print(la_(3, 4)) # 调用 lambda 函数 7
print((lambda a, b: a + b)(5, 7)) # 直接调用lambda函数 12
# sorted 结合排序
# 基本用法:不指定key,默认排序;指定key,key作为排序依据。
# 理解:将列表每个元素进行key指定的函数进行处理后,再用处理完成的值进行排序。
# 示例:加入我需要对列表中每个奇数进行符号反转后再排序,反转后为 [3, -2, -1, -5]
def func14(x):
if x % 2 == 0:
return x
else:
return -x
nums = [-3, 1, -2, 5]
news = sorted(nums) # 没有 key,默认排序
new2 = sorted(nums, key=func14) # 按照func14指定函数处理后排序
print(news, new2) # [-3, -2, 1, 5] [5, -2, 1, -3]
# 高阶示例
# 字符串按长度排序
words = ["apple", "banana", "cat1", "dog"]
new1 = sorted(words, key=lambda x:len(x))
print(new1) # ['dog', 'cat1', 'apple', 'banana']
# 元组列表按最后位置元素排序
data = [(1, 3, 5), (4, 1, 2), (2, 2, 7)]
new1 = sorted(data, key=lambda x: x[-1])
print(new1) #[(4, 1, 2), (1, 3, 5), (2, 2, 7)]
# 字典按值排序(先转成键值对列表)
score_dict = {"math": 88, "english": 92, "chinese": 90}
print(score_dict.items()) #dict_items([('math', 88), ('english', 92), ('chinese', 90)])
new1 = sorted(score_dict.items(), key=lambda x:x[1])
print(new1) # [('math', 88), ('chinese', 90), ('english', 92)]
# 按绝对值排序
nums = [-3, 1, -2, 5]
new1 = sorted(nums, key=lambda x:abs(x))
print(new1) # [1, -2, -3, 5]
# map 结合批处理
# 基本用法,示例:求几个数的平方
li = [1, 3, 5, 7, 9]
def pow(x):
return x ** 2
print(list(map(pow, li))) # [1, 9, 25, 49, 81]
# 高阶用法
# 求几个数的平方
li = [1, 3, 5, 7, 9]
new1 = list(map(lambda x:x**2, li))
print(new1) # [1, 9, 25, 49, 81]
#字符串列表转大写
words = ["hello", "world", "python"]
new1 = list(map(lambda x:x.upper(), words))
print(new1) # ['HELLO', 'WORLD', 'PYTHON']
# 两个列表对应元素相加
nums1 = [1, 2, 3]
nums2 = [10, 20, 30]
new1 = list(map(lambda x,y: x+y, nums1, nums2))
print(new1) # [11, 22, 33]
# 三个列表拼接成元组
a = [1, 2]
b = ["a", "b"]
c = [True, False]
print(list(map(lambda x,y,z:(x, y, z), a, b, c))) # [(1, 'a', True), (2, 'b', False)]
# filter结合 过滤处理
# 基本用法,示例:过滤列表中的偶数
def is_even(n):
return n % 2 == 0
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
even_numbers = filter(is_even, numbers)
print(list(even_numbers)) # 输出: [2, 4, 6, 8, 10]
# 高阶用法
# 筛选列表中的奇数
nums = [1, 2, 3, 4, 5, 6]
new1 = list(filter(lambda x:x%2!=0, nums))
print(new1) # [1, 3, 5]
# 筛选长度大于2的字符串
words = ["a", "ab", "abc", "abcd"]
new1 = list(filter(lambda x:len(x)>2, words))
print(new1) # ['abc', 'abcd']
# 筛选字典列表中满足条件的元素
students = [
{"name": "Alice", "score": 85},
{"name": "Bob", "score": 60},
{"name": "Charlie", "score": 90}
]
# 筛选成绩≥80的学生
new1 = list(filter(lambda x:x["score"] > 80, students))
print(new1) # [{'name': 'Alice', 'score': 85}, {'name': 'Charlie', 'score': 90}]
# 特殊函数
# 回调函数
def fn(x, cb):
print(x, cb(x))
def callback(x):
return x**2
fn(5, callback) # 回调函数 5 25
# 递归处理
# 求5的阶乘(使用函数递归)
# 1. 找公式:n! = n * (n-1)!
# 2. 找临界值(递归结束条件):n=1, fn(1) = 1
def fn(n):
if n <= 1: # 递归结束条件
return 1
else: # 递归执行体
return n * fn(n-1)
print(fn(5)) # 120
# 封装函数,传入m,得到第m个斐波那契数 # 1 1 2 3 5 8 13 21
def f(n):
if n <= 2:
return 1
else:
return f(n-1) + f(n-2)
print(f(6)) # 8
# 兔子繁殖问题。 设有一对新生的兔子,从第4个月开始他们每个月月初都生一对新兔子,
# 新生的兔子从第4个月开始又每个月月初生一对兔子。 按此规律,并假定兔子没有死亡,20个月末共有多少对兔子?
# 当月的兔子 = 上个月的兔子 + 三个月前的兔子数(三月前的兔子会生下一批,刚好在本月生产新兔子)
def f(n):
if n <= 3:
return 1
else:
return f(n-1) + f(n-3)
print(f(20)) # 872
# 练习
# 封装一个函数 验证一个数是否是回文:str(n)[::-1] == str(n)
# 回文: 颠倒过来 与 自身数据一样的称为回文 例如 111 121 1221 12321
def fn1(n) -> bool:
return str(n)[::-1] == str(n) # 强转成字符串,后倒序与正序相比
print(fn1(12321), fn1(123)) # True False
# 封装一个函数,获取多个数中的最小值,最大值,和,以及平均值
def fn2(*args) -> tuple:
return max(args), min(args), sum(args)/len(args)
print(fn2(1, 3, 4, 7, -4)) # (7, -4, 2.2)
# 封装一个函数 获取多个数中的平均值并统计其中高于平均数的值个数
def fn3(*args) -> tuple:
avg = sum(args)/len(args)
count = 0
for arg in args:
if arg > avg:
count += 1
return avg, count
print(fn3(1, 6, 3, 5)) # (3.75, 2)
# 封装一个函数,获取所有的水仙花数
# 水仙花数是指一个3位数,它的每个位上的数字的3次幂之和等于它本身
# (例如:1^3 + 5^3+ 3^3 = 153)
def fn4(x):
return (((x // 100) ** 3) + ((x // 10 % 10) ** 3) + ((x % 10) ** 3)) == x
print(list(filter(fn4, range(100, 999)))) # [153, 370, 371, 407]
# 实现万年历效果图,使用函数封装
# A:先输出提示语句,并接受用户输入的年、月。
def fa():
year = int(input("请输入年份:"))
month = int(input("请输入月份:"))
fh(year,month)
# B:根据用户输入的年,先判断是否是闰年。
def fb(year):
return (year % 4 == 0 and year % 100 != 0) or year % 400 == 0
# C:根据用户输入的月来判断月的天数。
def fc(year, month):
if month == 2:
return 29 if fb(year) else 28
elif month in [4, 6, 9, 11]:
return 30
elif month in [1, 3, 5, 7, 8, 10, 12]:
return 31
else:
return 0
# D:用循环计算用户输入的年份距1900年1月1日的总天数。
def fd(year):
s = 0
for i in range(1900, year):
s += 366 if fb(i) else 365
return s
# E:用循环计算用户输入的月份距输入的年份的1月1日共有多少天,
def fe(year, month):
s = 0
for i in range(1, month):
s += fc(year, i)
return s
# F:相加D与E的天数,得到总天数。
def ff(year, month):
return fd(year) + fe(year, month)
# G:用总天数来计算输入月的第一天的星期数
def fg(year, month):
return ff(year, month) % 7
# H:根据G的值,格式化输出这个月的日历!
def fh(year, month):
# 打印第一行
print('一', '二', '三', '四', '五', '六', '日', sep='\t')
# 打印空格
for m in range(1, fg(year, month)+1):
print("\t", end ="")
# 打印日期
for i in range(1, fc(year, month)+1):
print(i, end="\t")
# 每一周换行
if (i+fg(year, month)) % 7 == 0:
print()
# 请输入年份:2026
# 请输入月份:3
# 一 二 三 四 五 六 日
# 1
# 2 3 4 5 6 7 8
# 9 10 11 12 13 14 15
# 16 17 18 19 20 21 22
# 23 24 25 26 27 28 29
# 30 31
fa()