Python4 - 函数
2026/9/16 9:06:32 网站建设 项目流程

摘要:

本文是 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="乌蒙", age=19, gender="女", city="B市")) # 关键字传参:形参名=实参值,不要求顺序 --> 繁琐但易维护 print(info("乌膺", 33, gender="男", city="C市")) # 混合传参:关键字传参必须在位置传参之后 # 指定传参方式 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="女", city="A市")) # 默认参数:在函数定义时必须放在所有参数的末尾 def info(age, gender, name="乌昂", city="A市"): print(f"注册成功,姓名:{name},年龄:{age},性别:{gender},城市:{city}") return {"name":name, "age":age, "gender":gender, "city":city} print(info( 21, "男")) # 调用时没传参数,就用默认值 print(info(name="汪芜", age=21, gender="男", city="B市")) # 调用时传了参数,就用传进来的值 # 不定长位置参数(传入的所有参数合并封装在一个元组里) 和 不定长关键字参数(传入的所有参数合并封装在一个字典里) # 定义一个函数,根据传入的数据,计算这批数据中的最小值、最大值、平均值。 要求:调用函数时,可以指定显示几位小数 和 是否显示原数据 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_round=2, my_print=True ) # 传一批数值 # 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中函数与模块的基础知识。如有问题,欢迎指教!

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询