Python4 - 函数

发布时间:2026/9/16 9:06:36
Python4 - 函数 摘要本文是 Python 函数与模块的入门教程。文章从教务管理系统中重复统计成绩的代码冗余问题引入函数概念系统讲解了函数的定义与调用、参数与返回值、形式参数与实际参数、嵌套调用等基础知识随后进阶介绍了全局变量与局部变量的作用域规则以及位置传参、关键字传参、混合传参、默认参数、不定长参数、lambda 匿名函数、递归和类型注解等传参与函数特性最后介绍了 Python 模块与软件包的组织方式包括官方模块的多种导入形式以及通过 __init__.py、__all__ 和 if __name__ __main__ 实现自定义模块的封装与导入。目录前言一、函数基础二、函数进阶1、全局变量与局部变量2、参数三、模块1、Python官方模块2、自定义模块总结前言上一篇讲数据容器的文章中最后一个案例是教务管理系统。不知道小伙伴们有没有注意到在实现 “统计班级语文、数学、英语成绩的最高分、最低分、平均分” 这一需求时分别对语文、数学、英语成绩三个对象做了三次求最大值、求最小值、求平均分的操作代码冗余。这时就需要一个提前组织好的、可以重复使用的、用来实现特定功能的代码片段——函数。一、函数基础函数必须先定义再调用。定义时不会执行调用时才会执行就像造车定义只是把车造出来调用才会把车开动起来。# 函数的定义与调用 # 定义函数 def is_four_leaf_rose(num): # num -- 形式参数只能在函数内使用 # 函数的说明文档pycharm中鼠标悬浮在函数上会自动展示 判断一个四位数是否为四叶玫瑰数指一个四位数它的各位数字的四次方之和等于它本身。1000到9999之间一共有3个1634、8208、9474。 :param num: 一个四位数 :return: 判断结果 # 函数体 if not (1000 num 9999): return False a num // 1000 # 千位除以1000取整 b (num // 100) % 10 # 百位除以100取整再除以10取余 c (num // 10) % 10 # 十位除以10取整再除以10取余 d num % 10 # 个位除以10取余 return a**4 b**4 c**4 d**4 num # return只返回不打印 # 调用函数 test_num int(input(请输入一个四位数)) if is_four_leaf_rose(test_num): # 调用时传入的test_num -- 实际参数 print(f{test_num} 是四叶玫瑰数) # 如果test_num打印出来为None说明函数没有 返回 数据 else: print(f{test_num} 不是四叶玫瑰数) # 函数的嵌套调用遵循栈结构最后被调用的函数最先返回 def function_a(): print(a ... before) function_b() print(a ... after) def function_b(): print(b ... before) function_c() print(b ... after) def function_c(): print(c ...) function_a() print(函数调用完毕 ~) # 示例 # 1. 定义一个函数计算传入的字符串中元音字母的个数元音字母为 aeiouAEIOU。 def count_aeiou(str_data): 计算传入的字符串中元音字母的个数 :param str_data: 用户传入的字符串 :return: 元音字母的个数 count 0 for i in str_data: if i in aeiouAEIOU: count 1 return count count1 count_aeiou(hello world hello python) print(传入的字符串中元音字母的个数为, count1) # 2. 定义一个函数计算传入的班级学员高考成绩列表中成绩的最高分、最低分、平均分(保留1位小数)并返回。 def score(score_list): 计算传入的班级学员高考成绩列表中成绩的最高分、最低分、平均分(保留1位小数) :param score_list: 传入的成绩列表 :return: 最高分、最低分、平均分 max_score max(score_list) min_score min(score_list) avg_score round(sum(score_list) / len(score_list), 1) # round() 设置小数位数 return max_score, min_score, avg_score # Python可以一次性返回多个值C语言、Java不行多个返回值会封装到一个元组中 max_s, min_s, avg_s score([750, 681, 515, 497, 667, 548, 703, 669, 587]) print(f最高分{max_s}最低分{min_s}平均分{avg_s})上述代码包含知识点函数的定义与调用参数与返回值形式参数与实际参数函数的说明文档嵌套调用函数。二、函数进阶1、全局变量与局部变量# 全局变量和局部变量 tax_rate 0.05 # 定义全局变量在函数内外都可以访问。- 尽量避免在函数中使用全局变量因为会使代码难以维护和调试 def cal_tax(total_price): # global tax_rate # global关键字告诉Python解释器, 函数中使用的是全局变量tax_rate # tax_rate 0.08 # 修改全局变量的值 tax_rate 0.08 # 定义局部变量只在函数内起作用 if total_price 10000: tax total_price * tax_rate # 在使用变量时 优先 在当前作用域范围内查找如果未查询到再到上一层作用域查询。 elif total_price 5000: tax total_price * tax_rate * 0.8 else: tax 0 return tax my_tax cal_tax(10000) print(f税前价格: 10000, 税: {my_tax}) print(tax_rate) # 这里是全局变量2、参数定义函数时主要有三种传参方式位置传参、关键字传参和混合传参。当参数小于等于3个并且顺序自然时建议用位置传参其他情况建议用关键字传参或混合传参。# 传参方式 def info(name, age, gender, city): print(f注册成功姓名{name}年龄{age}性别{gender}城市{city}) # {} -- 是占位符 return {name:name, age:age, gender:gender, city:city} # {} -- 用来定义字典 print(info(乌昂, 21, 女, A市)) # 位置传参参数个数与顺序必须一致 -- 简洁但易出错 print(info(name乌蒙, age19, gender女, cityB市)) # 关键字传参形参名实参值不要求顺序 -- 繁琐但易维护 print(info(乌膺, 33, gender男, cityC市)) # 混合传参关键字传参必须在位置传参之后 # 指定传参方式 def info(name, age, *, gender, city): # *后面必须使用关键字传参 -- 常见 # def info(name, age, /, gender, city): # /前面必须使用位置传参 print(f注册成功姓名{name}年龄{age}性别{gender}城市{city}) return {name:name, age:age, gender:gender, city:city} print(info(乌昂, 21, gender女, cityA市)) # 默认参数在函数定义时必须放在所有参数的末尾 def info(age, gender, name乌昂, cityA市): print(f注册成功姓名{name}年龄{age}性别{gender}城市{city}) return {name:name, age:age, gender:gender, city:city} print(info( 21, 男)) # 调用时没传参数就用默认值 print(info(name汪芜, age21, gender男, cityB市)) # 调用时传了参数就用传进来的值 # 不定长位置参数传入的所有参数合并封装在一个元组里 和 不定长关键字参数传入的所有参数合并封装在一个字典里 # 定义一个函数根据传入的数据计算这批数据中的最小值、最大值、平均值。 要求调用函数时可以指定显示几位小数 和 是否显示原数据 def data(*args, **kwargs): # *args传入的是数据**kwargs传入的是对数据的描述 max_data max(args) min_data min(args) avg_data sum(args) / len(args) if kwargs[my_round] is not None: # 判断是否为None用 is / is not avg_data round(avg_data, kwargs[my_round]) if kwargs.get(my_print): print(f原数据为{args}) return max_data, min_data, avg_data max_d, min_d, avg_d data(74, 39, 97, 256, 3577, 22, 698, my_round2, my_printTrue ) # 传一批数值 # max_d, min_d, avg_d data(*[16, 74, 82, 14, 39, 48, 98]) # 传一个列表或元组的话要先解包 print(f最大值{max_d}最小值{min_d}平均值{avg_d}) # 参数类型 # 1普通参数int, bool, list, dict, ... # 2特殊参数将函数名作为参数传入某个函数的定义中 def add(a, b): return a b def divide(a, b): return a / b def calculate(a, b, oper): return oper(a, b) print(calculate(2, 4, add)) print(calculate(1835, 4, divide)) # 匿名函数 lambda # 语法 -- lambda 参数列表 : 函数体 # 应用场景函数功能简单一次调用就结束。作为高阶函数的参数使用的时候最多 data [人生苦短, 库, 咳咳咳, 阿致, kdsjijhuw, ssddjfhjuiig] data.sort(key lambda x : len(x)) # 把排序标准设为字符串长度 print(f按字符串长度排序结果{data}) data.sort() print(f默认排序结果{data}) # 案例1计算N的 阶乘factorial # 递归先层层调用再逐层回归 def factorial(n): if n 1: # 必须给递归调用一个出口否则会陷入死循环 return 1 return n * factorial(n-1) # 递归调用自己调自己 input1 int(input(请输入要计算谁的阶乘)) res factorial(input1) print(f{input1}的阶乘为{res}) # 类型注解非强制 语法 -- 变量名: 建议类型 # 常规类型注解 name : str 乌昂 # 面对变量赋值、变量运算、容器的推导场景时Python解释器会自行推断数据类型 flag : bool True pic : None None list1 : list[int | str] [16, hello, 4977, 32] tuple1 : tuple[int, str, float, str] (54, world, 3.5, he) # 元组的类型注解要一一对应 set1 : set[str] {语文, 数学, 英语} # 写类型注解时都用[] dict1 : dict[str, int | float] {count: 0, price: 88.8} # 函数类型注解定义函数时给形参指定一个类型的话后续用的时候就方便调用相应类型的方法 def circle_area_len(r: float) - tuple[float, float]: return round(3.14 * r * r, 1), round(2 * 3.14 * r, 1) al circle_area_len(8.5) print(al)三、模块1、Python官方模块Python模块一个.py文件就是一个模块模块是Python程序的基本组织单位。在模块中可以定义变量、函数、类以及可执行的代码。Python软件包本质就是一个文件夹该文件夹中可以包含若干python模块.py文件文件夹下还自带了一个__init__.py。模块的导入形式功能 调用方式包的导入形式功能 调用方式import 模块名模块名.功能名import 包名.模块名包名.模块名.功能名import 模块名 as 别名别名.功能名from 包名 import 模块名模块名.功能名from 模块名 import 功能名功能名from 包名 import *模块名.功能名from 模块名 import 功能名 as 别名别名from 包名.模块名 import 功能名功能名from 模块名 import *功能名from 包名.模块名 import *功能名2、自定义模块__init__.py__all__ [my_func, my_str]my_func.py__all__ [log_separator1, log_separator4] # __all__只与导入时的*有关 # 函数 def log_separator1(): print(- * 30) # - 重复输出30次 def log_separator2(): print( * 30) def log_separator3(): print(# * 30) def log_separator4(): print(* * 30) # 测试代码放在如下语句块中只在本模块生效当本文件被当作模块导入时__name__等于模块的文件名(不含.py后缀) if __name__ __main__: # main回车自动生成 log_separator1() log_separator2() log_separator3() log_separator4() # 不缩进的话另一个文件也会执行这些代码my_str.py__all__ [NAME] # __all__只与导入时的*有关 # 常量(不会发生变化的数据 ; 常量的名称为全部大写) PI 3.1415926535 NAME 自定义模块 if __name__ __main__: # main回车自动生成 print(f模块内的PI {PI}) print(f模块内的NAME {NAME})test.py# 自定义模块导入使用 from pkg import my_func from pkg.my_func import * # 只能导入 __all__ 开放给我们的 from pkg.my_str import * print(my_func.__name__) # 输出pkg.my_func log_separator1() # log_separator2() # my_func.py文件中的log_separator2方法没开放会报错 print(NAME) # print(PI) # my_str.py中的常量PI没开放会报错 # from my_func import PI # 直接导入并调用功能名不受__all__影响 # print(PI)总结以上就是今天要讲的内容本文简单介绍了Python中函数与模块的基础知识。如有问题欢迎指教