《嵌入式AI筑基笔记04:python函数与模块01—从C的刻板到Python的灵动》

《嵌入式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:指定排序依据的函数,接收一个参数。

reverseTrue 降序,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()
相关推荐
551只玄猫2 小时前
【数学建模 matlab 实验报告5】最短路问题作业
开发语言·数学建模·matlab·课程设计·图论·最短路径·实验报告
智算菩萨2 小时前
【Pygame】第2章 Pygame基础概念与游戏循环
python·游戏·pygame
深度学习lover2 小时前
<数据集>yolo骑行者识别<目标检测>
人工智能·python·yolo·目标检测·计算机视觉
ada0_ada12 小时前
Qt的Widgets项目
开发语言·qt
凤山老林2 小时前
Spring Boot 深度集成 Tess4J 实战:构建企业级 OCR 服务
spring boot·python·ocr
1104.北光c°2 小时前
Leetcode146 LRU缓存的三种写法 【hot100算法个人笔记】【java写法】
java·开发语言·笔记·算法·leetcode·hot100·lru缓存
花千树-0102 小时前
用 Java 实现 RAG 组件化:从 PDF 加载到智能问答全流程
java·开发语言·人工智能·langchain·pdf·aigc·ai编程
Dovis(誓平步青云)2 小时前
《QT学习第一篇:QT的概述与安装、信号与槽》
开发语言·qt·学习·功能详解
AI帮小忙2 小时前
CTF安全竞赛能力矩阵
开发语言·php