函数定义
将一段完成特定功能的代码封装起来,通过调用函数名来重复使用这段代码
函数是组织代码的基本单位。当一段逻辑需要被多次使用时,将其封装为函数可以避免重复编写代码,提高代码的可读性和可维护性。
函数的基本定义格式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 """ def 函数名(参数列表): 函数体(实现功能的代码) return 返回值(可选) 注意: - def 是定义函数的关键字 - 函数名遵循标识符命名规则(小写字母+下划线) - 函数体必须有缩进(4个空格) - 没有 return 语句时,函数默认返回 None """ def greet (): print ("Hello, Python!" ) def add (a, b ): return a + b
函数命名规范
1 2 3 4 5 6 7 8 9 10 11 12 13 14 """ - 使用小写字母和下划线 - 函数名应该描述其功能,通常使用动词开头 - 避免使用 Python 关键字和内置函数名 """ def calculate_average (scores ): return sum (scores) / len (scores) def is_even (num ): return num % 2 == 0 def get_user_name (user_id ): pass
空函数与 pass 语句
1 2 3 4 5 6 7 8 9 10 11 """ 当暂时不实现函数功能时,使用 pass 占位 如果什么都不写,就会有报错 pass 是一个空语句,什么也不做,仅用于保持程序结构完整 """ def future_feature (): pass def todo_function (): """待实现的函数""" pass
函数调用
定义函数只是告诉 Python 有这么一段代码,只有调用函数时,函数体中的代码才会真正执行。
基本调用方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 def show_hello (): print ("你好,PyTs1n9!" ) print ("欢迎学习 Python" ) show_hello() print ("---" )show_hello()
函数调用的执行流程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 """ 1. 程序从上到下执行 2. 遇到 def 时跳过函数体(不会执行内部代码) 3. 遇到 函数名() 时,跳入函数体逐行执行 4. 函数体执行完毕后,回到调用处继续执行后续代码 """ def step1 (): print (" 步骤1:准备食材" ) def step2 (): print (" 步骤2:开始烹饪" ) print ("开始做菜:" )step1() step2() print ("菜做好了!" )
函数嵌套调用 重点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 def line (): print ("-" * 20 ) def show_title (): line() print ("Python 学习笔记" ) line() show_title()
函数参数
函数定义时声明用于接收外部数据的变量,调用时传入实际值
参数让函数更加灵活,同一个函数可以处理不同的数据。Python 支持多种参数传递方式。
在了解各种传参方式之前,先明确两个重要概念:
1 2 3 4 def add (a, b ): return a + b result = add(3 , 5 )
概念
英文
定义
出现位置
形参
parameter
函数定义时括号内声明的变量,用于接收 数据
def 函数名(形参1, 形参2):
实参
argument
函数调用时括号内传入的具体值,用于传递 数据
函数名(实参1, 实参2)
简单理解:形参是"占位符",等待调用时被赋值;实参是"真实值",调用时传递给函数。
位置参数
1 2 3 4 5 6 7 8 9 10 def student_info (name, age, score ): print (f"姓名:{name} ,年龄:{age} ,成绩:{score} " ) student_info("小明" , 18 , 95 ) student_info("小红" , 92 , 17 )
关键字参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 def student_info (name, age, score ): print (f"姓名:{name} ,年龄:{age} ,成绩:{score} " ) student_info(name="小刚" , age=20 , score=88 ) student_info(score=76 , name="小丽" , age=19 ) student_info("小明" , score=95 , age=18 )
默认参数
定义函数时为参数指定默认值,调用时如果不传则使用默认值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 def greet (name, greeting="你好" ): print (f"{greeting} ,{name} !" ) greet("小明" ) greet("小红" , greeting="早上好" )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 def create_profile (name, age, city="未填写" , hobby="无" ): """创建一个用户档案,城市和爱好为可选信息""" print (f"{name} | {age} 岁 | {city} | 爱好:{hobby} " ) create_profile("张三" , 25 ) create_profile("李四" , 30 , city="北京" ) create_profile("王五" , 28 , hobby="打篮球" ) create_profile("赵六" , 22 , "上海" , "编程" )
不定长参数 重点
当不确定会传入多少个参数时,使用 *args(位置参数)和 **kwargs(关键字参数)
在不定长参数中,*args 和 **kwargs 是两个特殊的写法:
写法
含义
存储类型
使用方式
*args
arguments ,接收任意数量的位置实参
元组
直接遍历或用索引访问 args[0]
**kwargs
keyword arguments ,接收任意数量的关键字实参
字典
kwargs["key"] 或遍历 .items()
注意 :这里的 args 和 kwargs 只是约定俗成的命名,真正起作用的是前面的 * 和 **。你完全可以写成 *nums 或 **info,但为了代码可读性,建议使用约定命名。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 def sum_all (*args ): """计算任意个数的累加和""" total = 0 for num in args: total += num return total print (sum_all(1 , 2 )) print (sum_all(1 , 2 , 3 , 4 , 5 )) print (sum_all()) def show_info (**kwargs ): """打印任意键值对信息""" for key, value in kwargs.items(): print (f"{key} :{value} " ) show_info(name="小明" , age=18 , hobby="编程" )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 def order_food (restaurant, *dishes, **details ): """点餐函数:餐厅名 + 若干菜品 + 备注信息""" print (f"餐厅:{restaurant} " ) print (f"菜品:{', ' .join(dishes)} " ) if details: print (f"备注:{details} " ) order_food("川味轩" , "宫保鸡丁" , "麻婆豆腐" , "米饭" , time="12:30" , remark="少辣" )
参数传递的说明
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 """ Python 中参数的传递是"对象引用传递": - 不可变类型(int, str, tuple 等):在函数内部修改不会影响外部 - 可变类型(list, dict, set 等):在函数内部修改会影响外部 """ def change_num (n ): n = 100 print (f"函数内部:n = {n} " ) x = 10 change_num(x) print (f"函数外部:x = {x} " )def add_item (lst ): lst.append(4 ) print (f"函数内部:{lst} " ) my_list = [1 , 2 , 3 ] add_item(my_list) print (f"函数外部:{my_list} " )
函数返回值
函数执行完毕后,将结果返回给调用方,供后续代码使用
return 语句用于指定函数的返回值,是函数与外部交换数据的核心方式。
返回单个值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 def square (x ): return x ** 2 result = square(5 ) print (f"5的平方是:{result} " ) print (f"8的平方是:{square(8 )} " ) def no_return (): print ("这条消息会打印" ) result = no_return() print (result)
返回多个值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 def calculate (x, y ): add = x + y sub = x - y mul = x * y return add, sub, mul a, b, c = calculate(10 , 5 ) print (f"和:{a} ,差:{b} ,积:{c} " )result = calculate(8 , 3 ) print (f"返回的元组:{result} ,类型:{type (result)} " )
return 结束函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 """ return 执行后,函数立即结束 return 之后的代码不会被执行 """ def check_age (age ): if age < 0 : return "年龄不合法" if age >= 18 : return "已成年" return "未成年" print ("这行代码永远不会执行" ) print (check_age(-5 )) print (check_age(20 )) print (check_age(16 ))
变量作用域
变量的生效范围,分为局部变量(函数内部)和全局变量(整个程序)
理解变量的作用域对于编写正确的函数至关重要,它决定了在哪里可以访问和修改变量。
局部变量
1 2 3 4 5 6 7 def my_func (): local_var = "我是局部变量" print (local_var) my_func()
全局变量
1 2 3 4 5 6 7 8 9 10 11 12 total = 100 def show_total (): print (f"total 的值为:{total} " ) def add_to_total (n ): pass show_total() print (total)
global 关键字
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 """ 如果需要在函数内部修改全局变量,使用 global 关键字声明 """ total = 100 def add_to_total (n ): global total total += n print (f"函数内:total = {total} " ) add_to_total(50 ) print (f"函数外:total = {total} " )
LEGB 变量查找规则 了解即可
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 """ Python 变量查找遵循 LEGB 规则(由内向外): L (Local) 局部作用域:函数内部 E (Enclosing) 嵌套函数的外层作用域 G (Global) 全局作用域:文件级别 B (Built-in) 内置作用域:print, len 等内置函数 """ x = "全局变量" def outer (): x = "外层函数的变量" def inner (): x = "内层函数的变量" print (f"inner 中的 x:{x} " ) inner() print (f"outer 中的 x:{x} " ) outer() print (f"全局的 x:{x} " )
lambda 匿名函数
一种使用 lambda 关键字定义的简洁函数,通常用于简单的一行表达式
lambda 函数可以理解为一个"轻量级"的函数,不需要 def 和函数名,常用于需要传入函数作为参数的场景。
基本语法
1 2 3 4 5 6 7 8 9 10 11 12 13 """ lambda 参数1, 参数2, ... : 表达式 注意:lambda 只能写一行表达式,结果自动作为返回值 """ def add (a, b ): return a + b add_lambda = lambda a, b: a + b print (add(3 , 5 )) print (add_lambda(3 , 5 ))
lambda 的常见使用场景
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 students = [ {"name" : "小明" , "score" : 85 }, {"name" : "小红" , "score" : 92 }, {"name" : "小刚" , "score" : 78 } ] sorted_students = sorted (students, key=lambda s: s["score" ], reverse=True ) for stu in sorted_students: print (f"{stu['name' ]} :{stu['score' ]} " )
1 2 3 4 5 6 7 8 9 10 11 12 13 nums = [1 , 2 , 3 , 4 , 5 ] squared = list (map (lambda x: x ** 2 , nums)) print (squared) nums = [1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 ] even_nums = list (filter (lambda x: x % 2 == 0 , nums)) print (even_nums) result = (lambda x, y: x * y)(6 , 7 ) print (result)
lambda 与 def 的选择
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 """ lambda 适用场景: - 简单的一行表达式 - 作为其他函数的参数(sorted, map, filter 等) def 适用场景: - 多行逻辑 - 需要注释说明的复杂逻辑 - 需要复用多次的函数 """ words = ["banana" , "apple" , "cherry" , "date" ] words.sort(key=lambda w: len (w)) print (words) def sort_key (w ): """按字符串长度排序,长度相同时按字母顺序""" return (len (w), w) words.sort(key=sort_key) print (words)
函数文档与类型提示
写好函数说明和类型标注,提高代码可读性和编辑器提示能力
文档字符串(docstring)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 def calc_bmi (weight, height ): """ 计算身体质量指数(BMI) 参数: weight: 体重(单位:千克) height: 身高(单位:米) 返回: BMI 值(float),保留一位小数 """ return round (weight / (height ** 2 ), 1 ) print (calc_bmi.__doc__)
类型提示(Type Hints,Python 3.5+)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 """ 类型提示不会影响代码运行,但可以让编辑器给出更好的代码补全和错误提示 """ def greet (name: str , times: int = 1 ) -> str : """向某人打招呼,可以指定次数""" return f"{name} ,你好!" * times def calculate_average (scores: list [int ] ) -> float : """计算分数列表的平均值""" if not scores: return 0.0 return sum (scores) / len (scores) def get_user (user_id: int ) -> dict [str , str ] | None : """根据ID获取用户信息,不存在则返回None""" users = {1 : {"name" : "小明" , "role" : "admin" }} return users.get(user_id) result = greet("Python" , times=3 ) print (result)avg = calculate_average([85 , 92 , 78 , 90 ]) print (f"平均分:{avg} " )
递归函数 重点
函数内部调用自身,用于解决可以分解为相同子问题的问题
递归是一种强大的编程思想,但需要谨慎使用,确保有明确的终止条件。
递归的基本结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 """ 递归函数必须包含两个部分: 1. 递归终止条件(基线条件):防止无限递归 2. 递归调用(递归条件):将问题分解为更小的子问题 """ def factorial (n ): if n <= 1 : return 1 return n * factorial(n - 1 ) print (factorial(5 ))
递归的经典应用 斐波那契数列
1 2 3 4 5 6 7 8 9 10 def fibonacci (n ): if n <= 2 : return 1 return fibonacci(n - 1 ) + fibonacci(n - 2 ) for i in range (1 , 10 ): print (fibonacci(i), end=" " )
递归与循环的对比
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 def sum_recursive (n ): if n <= 1 : return n return n + sum_recursive(n - 1 ) def sum_loop (n ): total = 0 for i in range (1 , n + 1 ): total += i return total print (sum_recursive(100 )) print (sum_loop(100 ))
综合练习
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 """ 实现一个简单的四则运算计算器 支持加减乘除,除数为0时给出提示 """ def calculator (a, b, operator ): """简易计算器""" if operator == "+" : return a + b elif operator == "-" : return a - b elif operator == "*" : return a * b elif operator == "/" : if b == 0 : return "错误:除数不能为0" return a / b else : return "错误:不支持的运算符" print (calculator(10 , 5 , "+" )) print (calculator(10 , 5 , "/" )) print (calculator(10 , 0 , "/" )) print (calculator(10 , 5 , "^" ))
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 32 33 34 """ 检测密码强度的函数 弱:纯数字或纯字母,长度<6 中:数字+字母,长度>=6 强:数字+字母+特殊字符,长度>=8 """ def check_password_strength (password ): has_digit = False has_letter = False has_special = False for ch in password: if ch.isdigit(): has_digit = True elif ch.isalpha(): has_letter = True else : has_special = True length = len (password) if length < 6 and not (has_digit and has_letter): return "弱" elif length >= 8 and has_digit and has_letter and has_special: return "强" elif length >= 6 and has_digit and has_letter: return "中" else : return "弱" print (check_password_strength("123456" )) print (check_password_strength("abc123" )) print (check_password_strength("Py@2024!!" ))
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 """ 包含添加成绩、计算平均分、查找最高分最低分、统计及格率 """ def add_score (scores, name, score ): """添加学生成绩""" scores[name] = score print (f"已添加:{name} -> {score} 分" ) def get_average (scores ): """计算平均分""" if not scores: return 0 return sum (scores.values()) / len (scores) def get_top_student (scores ): """找到最高分学生""" if not scores: return None return max (scores, key=scores.get) def get_pass_rate (scores, pass_line=60 ): """计算及格率""" if not scores: return 0 passed = sum (1 for s in scores.values() if s >= pass_line) return passed / len (scores) * 100 def show_report (scores ): """打印成绩报表""" print ("\n===== 成绩报表 =====" ) for name, score in scores.items(): level = "及格" if score >= 60 else "不及格" print (f" {name} :{score} 分 ({level} )" ) print (f" 平均分:{get_average(scores):.1 f} " ) print (f" 最高分:{get_top_student(scores)} ({scores[get_top_student(scores)]} 分)" ) print (f" 及格率:{get_pass_rate(scores):.1 f} %" ) print ("=" * 22 ) scores_dict = {} add_score(scores_dict, "小明" , 85 ) add_score(scores_dict, "小红" , 92 ) add_score(scores_dict, "小刚" , 58 ) add_score(scores_dict, "小丽" , 76 ) add_score(scores_dict, "小华" , 45 ) show_report(scores_dict)
函数是 Python 编程的基石。掌握函数的定义、参数传递、返回值、作用域以及 lambda 表达式,你就能写出结构清晰、易于复用的代码。记住"高内聚、低耦合"的原则:一个函数只做好一件事。
Python Study Note 系列文章
Python Study Note Python 函数使用(四) Python 判断语句(二) Python 基础语法(一) Python 异常处理(七) Python 循环语句(三) Python 数据容器(五) Python 文件基础操作(六) Python 模块与包(八) Python 类型注解(十) Python 面向对象(九)重点 Python 高阶技巧(十一)