函数(Functions)基础
-
什么是函数?
-
一个命名的代码块,代指一大堆代码。
-
定义:
def function_name():
(使用def
关键字,英文括号,冒号,缩进代码块)。 -
执行/调用:
function_name()
(写函数名加括号)。 -
特性: 定义时不执行,调用时才执行。可重复调用。
-
-
为什么学习函数?(优势与应用场景)
-
增强代码重用性: 将重复或公共的代码块提取成函数,需要时调用即可,避免复制粘贴。
-
提高代码可读性: 将复杂逻辑拆分成多个小函数,每个函数负责一个清晰的功能,使主逻辑更简洁易懂。就像将大任务分解为小任务并命名。
-
-
函数参数(Function Parameters)
-
基本使用:
-
定义参数: 在函数名后的括号中定义变量名(形参)。
-
传递参数: 调用函数时传入值(实参)。
-
位置传参: 按参数在函数定义中的顺序传值。
-
示例:
def func(x1, x2): ...
调用func(1, 2)
。
-
-
关键字传参: 调用时指定参数名赋值。顺序不重要。
-
示例:
func(x2=2, x1=1)
。
-
-
混合传参: 位置参数必须在前,关键字参数在后。
-
示例:
func(1, x2=2)
(正确),func(x1=1, 2)
(错误)。
-
-
类型: 任意类型(
int
,str
,list
,dict
等)都可以作为参数传递。
-
-
参数默认值:
-
定义:
def func(x1, x2=default_value): ...
-
行为: 调用时如果不传该参数,则使用默认值;如果传入,则覆盖默认值。
-
注意: 带默认值的参数必须放在不带默认值的参数之后。
-
-
动态参数(
*args
和**kwargs
):-
*args
(星号参数/可变位置参数):-
定义:
def func(*args): ...
-
接收: 接收任意数量的位置参数。这些参数会被打包成一个元组(tuple)。
-
示例:
func(1, 2, 'hello')
,args
将是(1, 2, 'hello')
。 -
不传参数时,
args
为空元组()
。 -
易错点: 传入的列表/元组本身会作为一个整体元素放入
args
元组中,而不是被解包。
-
-
**kwargs
(双星号参数/可变关键字参数):-
定义:
def func(**kwargs): ...
-
接收: 接收任意数量的关键字参数。这些参数会被打包成一个字典(dict)。
-
示例:
func(name='Alice', age=30)
,kwargs
将是{'name': 'Alice', 'age': 30}
。 -
不传参数时,
kwargs
为空字典{}
。
-
-
混合使用(
*args
和**kwargs
):-
定义顺序: 必须是
def func(normal_param, *args, **kwargs): ...
-
传参顺序:
func(位置参数, *args打包的参数, **kwargs打包的参数)
-
惯例: 动态参数名通常写为
*args
和**kwargs
。 -
应用: 常见于内置函数(如
print()
)和框架/库中,用于灵活接收用户传入的任意参数。
-
-
-
实践案例:Python发送邮件
-
实现思路: 借助于第三方邮箱服务器(如网易126邮箱)的SMTP服务。
-
注册邮箱并开启SMTP服务: 登录邮箱设置,找到POP3/SMTP服务,开启并获取授权码(替代邮箱密码用于代码登录)。记录SMTP服务器地址(如
smtp.126.com
)。 -
导入模块:
import smtplib
和from email.mime.text import MIMEText
。 -
构建邮件内容: 使用
MIMEText
创建邮件对象,指定主题、发件人、收件人、正文。 -
发送邮件:
-
创建SMTP连接:
smtp_obj = smtplib.SMTP_SSL('smtp.126.com', 465)
(SMTP_SSL使用SSL加密,端口通常为465)。 -
登录邮箱:
smtp_obj.login(sender_email, authorization_code)
。 -
发送:
smtp_obj.sendmail(sender_email, [receiver_email], msg.as_string())
。 -
退出:
smtp_obj.quit()
。
-
-
-
结合函数: 可将发送邮件逻辑封装成函数,通过参数动态传入收件人、主题、内容,实现更灵活的邮件发送功能。
函数的返回值(Return Values)
-
作用: 执行完函数后,将结果返回给调用者。
-
语法:
return 值
。 -
return
vs.print
:-
print
:仅输出到控制台。 -
return
:将值返回给调用者,可被变量接收。
-
-
特性:
-
任意类型: 返回值可以是任意Python类型。
-
默认
None
: 函数若无return
语句,默认返回None
。 -
终止函数: 函数内部一旦遇到
return
,立即终止执行后续代码。
-
-
多值返回:
return val1, val2, val3
实际返回一个元组。调用时可利用解包a, b, c = func()
。
函数内调用函数 (嵌套调用)
-
函数内部可以调用其他函数。
-
调用发生时,会先执行被调用的函数,待其执行完毕(及处理返回值)后,再回到原函数继续执行。
函数参数传递:引用 vs. 值
-
结论: Python函数参数传递的是引用,不会重新拷贝数据。
-
证明:
-
可变类型 (如列表): 函数内部对参数的修改(如
append
,remove
)会直接影响到外部传入的原始数据,因为它们指向同一内存地址。 -
不可变类型 (如字符串、数字、元组): 虽然传递的是引用,但由于不可变类型本身无法被原地修改,任何"修改"操作(如
str.upper()
)都会生成新对象,原引用保持不变。
-
作用域(Scope)
-
定义: 一块共享的区域,区域内数据可被访问。
-
Python中的作用域:
-
全局作用域: 最外层代码块,全局变量可在任何地方被访问。
-
函数作用域: 每个函数都是一个独立的作用域(局部作用域)。
-
-
查找规则: 在函数内部查找变量时,优先在自身局部作用域查找;若无,则向上一级(父级,通常是全局作用域)查找。
-
局部变量 vs. 全局变量:
-
局部变量: 函数内部定义的变量,仅在该函数内有效。
-
全局变量: 在任何函数之外定义的变量。
-
规范: 全局变量通常使用大写命名,局部变量使用小写。
-
-
global
关键字:-
作用:在函数内部声明变量为全局变量。
-
效果:使用
global var_name
后,函数内部对var_name
的任何操作都将直接作用于全局作用域中的同名变量,而不是在局部作用域内创建新变量。 -
示例:
global name; name = 'new_val'
会修改全局name
。
-
函数名本质是一个变量
-
概念: 函数名像其他变量一样,可以被赋值、作为参数传递、存储在数据结构(列表、字典)中。
-
func
vs.func()
:-
func
:代表函数本身(函数对象),不执行。 -
func()
:表示调用并执行函数,获取其返回值。
-
-
应用场景:
-
批量执行: 将多个函数名存储在列表/元组中,通过循环统一调用执行,避免重复代码。
-
调度中心 (命令模式): 使用字典将功能编号/名称映射到对应的函数名。根据用户选择获取并执行相应函数,简化
if/elif/else
结构。
-
拉姆达式(Lambda Expressions)/ 匿名函数
-
定义: 一种用于创建小型、单行匿名函数的简洁方式。
-
语法:
lambda 参数: 表达式
-
lambda
:关键字。 -
参数
:函数参数,可省略或多个。 -
表达式
:函数体,执行后隐含return
。
-
-
特点:
-
匿名: 没有名称。
-
单行: 只能包含一个表达式,结果被隐式返回。
-
简洁: 适用于逻辑简单的函数。
-
-
应用: 常用于作为参数传递给其他高阶函数(如
map
,filter
,sorted
的key
参数),如filter(lambda x:x>5, [1,6,3]),或作为数据结构中的元素。