news 2026/4/17 21:05:44

Python 函数学习笔记

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Python 函数学习笔记

是什么

函数 = 一段被命名的、可重复使用的代码块

函数(function)是带名字的代码块,用于完成具体的工作。要执行函数定义的特定任务,可调用(call)该函数。当需要在程序中多次执行同一项任务时,无须反复编写完成该任务的代码,只需要调用执行该任务的函数。它接收输入(参数),执行特定操作,返回结果(或无结果)。

定义一个函数

  1. 函数代码块以def关键词开头,后接函数标识符名称圆括号 ()
  2. 任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数。
  3. 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
  4. 函数内容以冒号(:)起始,并且缩进。
  5. return [表达式]结束函数,选择性地返回一个值给调用方,不带return 表达式的函数相当于返回None

def functionname(parameters):"函数_文档字符串"function_suitereturn[expression]

定义一个空函数

如果想定义一个什么事也不做的空函数,可以用pass语句,缺少了pass,代码运行就会有语法错误,空函数无法被调用。

pass语句什么都不做,那有什么用?

实际上pass可以用来作为占位符,比如现在还没想好怎么写函数的代码,就可以先放一个pass,让代码能运行起来。

def empty_fun(): pass

返回多个值

Python 的函数可以返回多个值。

比如在游戏中经常需要从一个点移动到另一个点,给出坐标、位移和角度,就可以计算出新的坐标:

importmathdefmove(x,y,step,angle=0):nx=x+step*math.cos(angle)ny=y-step*math.sin(angle)returnnx,ny

import math语句表示导入math包,并允许后续代码引用math包里的sincos等函数。

然后,我们就可以同时获得返回值:

>>> x, y = move(100, 100, 60, math.pi / 6) >>> print(x, y) 151.96152422706632 70.0

但其实这只是一种假象,Python函数返回的仍然是单一值:

>>> r = move(100, 100, 60, math.pi / 6) >>> print(r) (151.96152422706632, 70.0)

原来返回值是一个tuple!但是,在语法上,返回一个tuple可以省略括号,而多个变量可以同时接收一个tuple,按位置赋给对应的值,所以,Python的函数返回多值其实就是返回一个tuple,但写起来更方便。

Python类型注解(Type Hints)

类型注解是 Python 从动态语言向‘可维护性语言’进化的重要一步。在 Python 中,类型注解不是必须的,但它是让代码清晰的‘最佳实践’。

类型注解 = 在函数、变量上添加类型信息,但改变运行时行为
只用于静态类型检查(如 PyCharm、mypy),不用于运行时类型检查

基本语法

defadd(a:int,b:int)->int:"""添加两个整数"""returna+b# 调用print(add(3,4))# 7

变量类型注解

name:str="Alice"age:int=30is_active:bool=True

高级类型注解

集合类型(List, Dict, Tuple)

fromtypingimportList,Dict,Tuple# 列表:整数列表numbers:List[int]=[1,2,3]# 字典:字符串->整数映射user:Dict[str,int]={"id":123,"age":30}# 元组:固定长度的元组point:Tuple[float,float]=(3.5,4.2)

可选类型(Optional)

fromtypingimportOptionaldefget_user(id:int)->Optional[Dict[str,int]]:"""可能返回用户,也可能返回 None"""ifid==0:returnNonereturn{"id":id,"name":"Alice"}user=get_user(123)ifuserisnotNone:print(user["name"])

参数传递

在 python 中,类型属于对象,对象有不同类型的区分,变量是没有类型的:

a=[1,2,3]a="Runoob"

以上代码中,[1,2,3] 是 List 类型,“Runoob” 是 String 类型,而变量 a 是没有类型,它仅仅是一个对象的引用(一个指针),可以是指向 List 类型对象,也可以是指向 String 类型对象。

Python中一切都是对象,所以严格意义我们不能说值传递还是引用传递,我们应该说传不可变对象和传可变对象。

可更改(mutable)对象

类似 C++ 的引用传递,如 列表,字典。如 fun(la),则是将 la 真正的传过去,修改后 fun 外部的 la 也会受影响。

''' 在Python函数的参数传递,主要分参数类型: - 不可变类型 - 可变类型 **不可变对象类型**: 也即值传递,如整数、浮点数、字符串、元组等。 比如如def fun(a):,传递的只是a的值,没有传递a对象的地址。比如在fun(a)内部修改a的值, 只是修改另一个复制的对象的值,不会影响 a 本身对象的值。 **可变对象类型**: 也即引用(地址)传递,如列表,集合、字典等。如def fun(la):,则是将 la对象地址传过去,修改后fun外部的la也会受影响。 '''# 传入可变(mutable)对象类型参数案例defchange_list(my_list):my_list[1]=50print("函数内的值",my_list)print("函数内列表的内存",id(my_list))m_list=[1,2,3]change_list(m_list)print("函数外的值",m_list)print("函数外列表的内存",id(m_list))# 输出结果#函数内的值 [1, 50, 3]#函数内列表的内存 1149137300800#函数外的值 [1, 50, 3]#函数外列表的内存 1149137300800

不可更改(immutable)对象

类似 C++ 的值传递,如整数、字符串、元组。如 fun(a),传递的只是 a 的值,没有影响 a 对象本身。如果在 fun(a) 内部修改 a 的值,则是新生成一个 a 的对象。

''' 在Python函数的参数传递,主要分参数类型: - 不可变类型 - 可变类型 **不可变对象类型**: 也即值传递,如整数、浮点数、字符串、元组等。 比如如def fun(a):,传递的只是a的值,没有传递a对象的地址。比如在fun(a)内部修改a的值, 只是修改另一个复制的对象的值,不会影响 a 本身对象的值。 **可变对象类型**: 也即引用(地址)传递,如列表,集合、字典等。如def fun(la):,则是将 la对象地址传过去,修改后fun外部的la也会受影响。 '''# 传入不可变(immutable)对象类型参数案例defchange_int(a:int)->None:print("函数体中未改变前a的内存地址",id(a))a=10print("函数体中改变后a的内存地址",id(a))a=2change_int(a)print(a)print("函数外b的内存地址",id(a))# 输出结果#函数体中未改变前a的内存地址 140733455352776#函数体中改变后a的内存地址 140733455353032#2#函数外b的内存地址 140733455352776

参数

调用函数时可使用的正式参数类型:

  • 必需参数
  • 关键字参数
  • 默认参数
  • 不定长参数

不定长参数

*args:接收任意数量的位置参数

当函数需要处理不确定数量的参数时(如<font style="color:rgb(6, 10, 38);">sum(1, 2, 3, 4)</font>),Python 用<font style="color:rgb(6, 10, 38);">*args</font>解决。

defsum_all(*args):"""接收任意数量的位置参数"""total=0fornuminargs:total+=numreturntotalprint(sum_all(1,2,3))# 6print(sum_all(10,20,30,40))# 100

**kwargs:接收任意数量的关键字参数

当函数需要处理不确定数量的命名参数时(如<font style="color:rgb(6, 10, 38);">config(key1="value1", key2="value2")</font>),Python 用<font style="color:rgb(6, 10, 38);">**kwargs</font>解决。

defprint_config(**kwargs):"""接收任意数量的关键字参数"""forkey,valueinkwargs.items():print(f"{key}:{value}")print_config(host="localhost",port=8080,timeout=30)# 输出:# host: localhost# port: 8080# timeout: 30

lambda(匿名函数)

Python 使用 lambda 来创建匿名函数。
lambda 函数是一种小型、匿名的、内联函数,它可以具有任意数量的参数,但只能有一个表达式。
匿名函数不需要使用 def 关键字定义完整函数。
lambda 函数通常用于编写简单的、单行的函数,通常在需要函数作为参数传递的情况下使用,
例如在 map()、filter()、reduce() 等函数中。

lambda 函数特点:

  • lambda函数是匿名的,它们没有函数名称,只能通过赋值给变量或作为参数传递给其他函数来使用
  • lambda 函数通常只包含一行代码,适用于编写简单的函数

案例

""" Python lambda(匿名函数) Python 使用 lambda 来创建匿名函数。 lambda 函数是一种小型、匿名的、内联函数,它可以具有任意数量的参数,但只能有一个表达式。 匿名函数不需要使用 def 关键字定义完整函数 公式表达: lambda arguments: expression lambda是 Python 的关键字,用于定义 lambda 函数。 arguments 是参数列表,可以包含零个或多个参数,但必须在冒号(:)前指定。 expression 是一个表达式,用于计算并返回函数的结果。 """# ab法则defoperator(a,b):returna+bdeffunction(a,b,my_lambda_function):returnmy_lambda_function(a,b)print("使用普通函数修改:",function(1,2,operator))print("*"*20)print("="*10,"after","="*10)deffunction(a,b,lambda_operator):returnlambda_operator(a,b)print("使用lambda函数修改:",function(1,2,lambdaa,b:a+b))print("="*20)# lambda 函数没有参数f=lambda:"Hello, world!"print(f())# 输出: Hello, world!# lambda 函数1个参数x=lambdaparam:param+10print(x(5))# 输出: 15# lambda 函数多个参数,参数之间使用逗号 , 隔开x=lambdaa,b,c:a+b+cprint(x(5,6,2))# lambda 函数通常与内置函数如 map()、filter() 和 reduce() 一起使用,以便在集合上执行操作numbers=[1,2,3,4,5,6,7,8]even_numbers=list(filter(lambdax:x%2==0,numbers))print(even_numbers)# 输出:[2, 4, 6, 8]'''上述代码对标Java: List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8); List<Integer> evenNumbers = numbers.stream().filter(x -> x % 2 == 0).collect(Collectors.toList()); System.out.println(evenNumbers);'''# 有三名学生的姓名和年龄,按年龄排序student_list=[{"name":"z3","age":36},{"name":"li4","age":14},{"name":"w5","age":27}]print(sorted(student_list,key=lambdax:x["age"]))# map() 的主要作用是将给定的函数批量应用到可迭代对象的每个元素上,实现数据转换map_result=map(lambdax:x*x,[0,1,3,7,9])print(list(map_result))# [0, 1, 9, 49, 81]# filter() 的主要作用是将给定的函数**批量应用**到可迭代对象的每个元素上,实现数据过滤filter_result=filter(lambdax:x>=0,[-0,-1,-3,7,9])print(list(filter_result))# [0, 7, 9]

解包(unpacking)

解包 = 将序列(列表、元组、字符串等)的元素,一次性分配给多个变量。

核心价值
消除索引依赖,用有意义的变量名代替**<font style="color:rgb(6, 10, 38);">numbers[0]</font>**,提升可读性+可维护性

''' 基本定义 把可迭代对象(list/tuple/str/range/生成器等)里的元素“按位置”或“按名字” 批量赋给左侧变量的语法统称“解包”。 1 函数定义时的“收集” # *args 收集多余位置参数 # **kwargs 收集多余关键字参数 def f(a,*args, **kwargs): pass 2 函数调用时的解包 args = (1, 2) kwargs = {'x': 3, 'y': 4} func(a,*args, **kwargs) # 等价于 func(100,1, 2, x=3, y=4) '''deffunc(a,*args,**kwargs):print(a)print(args)print(kwargs)func(100,1,2,3,k1=20,k2=30)print("*"*20)# 解包传参:函数调用时解包defadd(a,b,c):returna+b+c args=(1,2)kwargs={"c":3}print(add(*args,**kwargs))print("*"*20)deffunc1(seq:int,*number:int)->int:result=0;print(seq)forxinnumber:result=result+(x*x)returnresultprint(func1(1,*(1,2,3)))print(func1(2,1,2,3))#print(func1(3, (1,2,3)))# TypeError: can't multiply sequence by non-int of type 'tuple'

闭包(Closure)

闭包 = 一个函数 + 它"记住"的外部环境(变量)

Python 闭包是指嵌套内部函数引用了其外部(嵌套)函数的变量 / 参数且内部函数被返回或暴露出去,
从而保留了外部函数的作用域(即使外部函数已执行完毕)的一种函数对象。
简单来说,闭包让内部函数 “记住” 了它诞生时的外部环境变量,即使外部函数已经执行结束,这些变量也不会被销毁。

defouter(x):definner(y):returnx+y# inner 闭包了 xreturninner# 创建闭包add_5=outer(5)print(add_5(3))# 输出 8

闭包必须同时满足 3 个条件:

  1. 函数嵌套
  2. 内部函数引用外部函数的局部变量
  3. 外部函数把内部函数返回(或当作参数传递出去)

优缺点

优点:封装隐藏数据、持久化状态、简化参数传递,适合实现轻量级的状态保持场景

缺点:内存占用过高、可读性 / 调试性差、循环变量捕获陷阱,使用时需避免持有大数据

价值:闭包是 Python 中实现函数式编程和装饰器的重要基础!

💡为什么重要
装饰器 =闭包的典型应用,是 Python 的核心特性(如<font style="color:rgb(6, 10, 38);">@staticmethod</font><font style="color:rgb(6, 10, 38);">@property</font>)。

""" 简化代码 闭包可以提前捕获外部函数的参数,形成一个参数部分固定的新函数, 简化后续调用,避免重复传入相同参数,提升代码复用性和简洁性。 示例:固化 “问候前缀”,后续只需传入姓名即可。 """importrandomdefcreate_greeter(prefix):defgreeter(name):returnf"{prefix}{name}!"returngreeter hello_greeter=create_greeter("你好")print(hello_greeter)print(hello_greeter(random.randint(1000,9999)))# 你好,随机数!(无需重复传入"你好")# 最终建议:不要写三层嵌套!用最简单的单层闭包。# 💡 为什么这是最佳实践?# 避免嵌套函数(减少代码复杂度)# 调用方式符合直觉(像普通函数一样)defcreate_greeter(prefix):defgreeter(name):defgreeter2(age):returnf"{prefix}{name}{age}!"returngreeter2# 1. 返回 greeter2(在 greeter 内部定义后)returngreeter# 2. 返回 greeter(外部函数)# 使用方式:greet=create_greeter("Hello")greet_name=greet("Alice")# 返回 greeter2print(greet_name(30))# 输出: Hello,Alice,30!# summary''' 闭包是 Python 中实现函数式编程和装饰器的重要基础! 一句话定义 闭包(closure) =「内部函数」+「定义时所在作用域的变量」——即使外层函数已返回,内部函数仍能记住并访问那些变量。 必须同时满足 3 个条件 函数嵌套 内部函数引用外部函数的局部变量 外部函数把内部函数返回(或当作参数传递出去) 记忆口诀 “外层返回内层,内层抓着外层的局部; 返回的函数带着背包,变量永生不死。” 闭包 = 内部函数 + 引用外部变量 + 外部函数返回内部函数, '''defouter(x):# 外部函数definner(y):# 内部函数returnx+y# 内部函数引用了外部变量 xreturninner# 返回的是“带背包”的内部函数对象add_10Var=outer(10)# 外部函数返回内部函数,但 x=10 被 inner 背着print(add_10Var(7))# 17print(add_10Var.__closure__)# 查看闭包保存的变量元组print(add_10Var.__closure__[0].cell_contents)# 10# 即使 outer(10) 已经执行结束,x=10 本应被销毁,但由于 inner 引用了它,Python 会将 x 保留在闭包环境中
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/18 8:31:15

Python 装饰器函数(decoratots) 学习笔记

是什么装饰器 一个函数&#xff0c;它接收另一个函数作为参数&#xff0c;并返回一个新的函数&#xff08;通常通过闭包实现&#xff09; 本质是高阶函数 闭包&#xff0c;用于在不修改原函数代码的前提下&#xff0c;增强函数功能Python 装饰器&#xff08;decorator&#x…

作者头像 李华
网站建设 2026/4/18 7:40:37

Sambert语音情感维度分析:离散标签与连续空间对比

Sambert语音情感维度分析&#xff1a;离散标签与连续空间对比 1. 开箱即用的多情感中文语音合成体验 你有没有试过&#xff0c;输入一段文字&#xff0c;几秒钟后就听到一个带着开心、生气、温柔或惊讶语气的声音在说话&#xff1f;不是那种机械念稿的感觉&#xff0c;而是像…

作者头像 李华
网站建设 2026/4/18 7:56:27

Sambert合成进度显示:前端反馈机制实现步骤

Sambert合成进度显示&#xff1a;前端反馈机制实现步骤 1. 为什么需要语音合成的进度反馈 你有没有试过点下“生成语音”按钮后&#xff0c;盯着空白界面等了十几秒&#xff0c;心里开始打鼓&#xff1a;“是不是卡住了&#xff1f;”“是不是网络断了&#xff1f;”“要不要…

作者头像 李华
网站建设 2026/4/12 7:32:29

Qwen2.5-0.5B-Instruct环境部署:零基础入门教程

Qwen2.5-0.5B-Instruct环境部署&#xff1a;零基础入门教程 1. 这个小模型&#xff0c;真能跑得动AI对话&#xff1f; 你可能已经试过不少大模型&#xff0c;但每次点开网页都得等几秒加载、输入问题后还要盯着转圈图标——这种“思考延迟”&#xff0c;其实不是AI在想&#…

作者头像 李华
网站建设 2026/4/18 7:57:56

直播新形态:基于Live Avatar的虚拟主播实现路径

直播新形态&#xff1a;基于Live Avatar的虚拟主播实现路径 在短视频和直播内容爆炸式增长的今天&#xff0c;真人出镜成本高、时间难协调、风格难统一&#xff0c;已成为中小团队和个体创作者的普遍痛点。而真正能投入日常使用的虚拟主播方案&#xff0c;长期受限于动作僵硬、…

作者头像 李华
网站建设 2026/4/17 13:09:03

轻量大模型崛起:Qwen2.5-0.5B开源部署一文详解

轻量大模型崛起&#xff1a;Qwen2.5-0.5B开源部署一文详解 1. 为什么0.5B模型突然火了&#xff1f; 你有没有试过在一台没有显卡的旧笔记本上跑大模型&#xff1f;点下“发送”后&#xff0c;等三分钟才蹦出第一句话——那种焦灼感&#xff0c;像在火车站盯着迟迟不更新的电子…

作者头像 李华