【Python 基础】第4章:函数模块与包完全指南(函数/模块/包)

函数、模块与包

    • 前言
    • [1. 函数基础](#1. 函数基础)
      • [1.1 定义](#1.1 定义)
      • [1.2 参数与返回值](#1.2 参数与返回值)
      • [1.3 函数的说明文档](#1.3 函数的说明文档)
      • [1.4 函数嵌套调用](#1.4 函数嵌套调用)
    • [2. 函数进阶](#2. 函数进阶)
      • [2.1 函数变量的作用域](#2.1 函数变量的作用域)
      • [2.2 函数参数](#2.2 函数参数)
        • [2.2.1 传参方式](#2.2.1 传参方式)
        • [2.2.2 默认参数](#2.2.2 默认参数)
        • [2.2.3 不定长参数](#2.2.3 不定长参数)
        • [2.2.4 参数类型](#2.2.4 参数类型)
        • [2.2.5 匿名函数](#2.2.5 匿名函数)
      • [2.3 类型注解](#2.3 类型注解)
        • [2.3.1 变量类型注解](#2.3.1 变量类型注解)
        • [2.3.2 函数类型注解](#2.3.2 函数类型注解)
    • [3. 模块](#3. 模块)
      • [3.1 介绍](#3.1 介绍)
      • [3.2 导入模块](#3.2 导入模块)
      • [3.3 自定义模块](#3.3 自定义模块)
        • [3.3.1 定义](#3.3.1 定义)
        • [3.3.2 测试函数](#3.3.2 测试函数)
        • [3.3.3 设置导入功能](#3.3.3 设置导入功能)
      • [3.4 包](#3.4 包)
        • [3.4.1 定义](#3.4.1 定义)
        • [3.4.2 创建](#3.4.2 创建)
        • [3.4.3 导入方式](#3.4.3 导入方式)

🎬 博主名称: 超级苦力怕

🔥 个人专栏: 《Python 基础》

🚀 每一次思考都是突破的前奏,每一次复盘都是精进的开始!


前言

本文将系统讲解 Python 中函数的定义、参数、返回值、作用域 等核心概念,并进一步介绍模块与包的使用,帮助你写出更优雅、高效的代码。

1. 函数基础

1.1 定义

函数:组织好的、可重复使用、用于实现特定功能的代码片段,如常用的**print()**就是函数,函数的定义语法如下

python 复制代码
# 定义函数
def 函数名(参数列表):
	函数体
	......
	return 返回值

#	调用函数
函数名(参数)

#示例
def out_line():
	print('---')

#调用函数
out_line()

特点:

  • 函数必须先定义,再调用
  • 函数定义时不会执行,只有调用函数才会执行
  • 函数中通过缩进描述归属关系

注意:函数定义时,参数和返回值可有可无,可以根据需求先做模板,再做调整。

1.2 参数与返回值

在定义函数时,可以根据需求,指定参数与返回值。

python 复制代码
def rectangle_area(l,w):
	area = l * w
	return area

area = rectangle_area(20,10)       # area = 200

示例代码

python 复制代码
def circle_area_len(r):
    area = round(3.14 * r * r, 1)
    circumference = round(2 * 3.14 * r, 1)
    return area, circumference

al = circle_area_len(10)
print(al)				# (314.0, 62.8)
print(type(al)) 		#<class 'tuple'>


area, len = circle_area_len(10)  # 解包,可以让多个返回值封装到元组中
print(area)				#314.0
print(len)				#62.8

注意

  1. 函数定义时如果有多个参数,使用,分隔
  2. return 语句只有返回功能,没有打印功能,需要结合 print() 实现打印

1.3 函数的说明文档

函数的说明文档(Docstring) 是写在函数开头,用三个引号包裹的字符串,用于解释函数的功能、参数、返回值等信息,方便调用者清楚函数的具体作用及细节。

python 复制代码
# 定义一个函数,根据半径,计算圆的周长、面积
def circle_area_len(r):
    """
    这部分是函数的说明文档,通常描述函数的参数、函数的返回值
    
    该函数用于根据圆的半径,计算圆的面积和圆的周长
    :param r: 圆的半径 						
    :return: 圆的面积,圆的周长
    """
    return 3.14 * r * r, 2 * 3.14 * r

al = circle_area_len(10)
print(al)		#(314.0, 62.800000000000004)

拓展:计算机用二进制表示十进制小数时,有些小数(比如0.8)无法精确表示,只能近似存储,所以计算后就会出现这种微小误差。

注意:可以通过鼠标悬浮在函数上查看说明文档(推荐),或者使用 help 函数查看说明文档

python 复制代码
help(circle_area_len)

#输出结果如下
circle_area_len(r)
    该函数用于根据圆的半径,计算圆的面积和圆的周长
    :param r: 圆的半径
    :return: 圆的面积,圆的周长

1.4 函数嵌套调用

嵌套调用指的是在一个函数中,又调用了另外一个函数,具体如下所示。

python 复制代码
# 在 Pycharm 中,可以点击左侧行数,进行断点,这时候运行选择DeBug,就会根据断点处进行停留。
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()

运行结果

shell 复制代码
a ... before
b ... before
c ...
b ... after
a ... after

函数调用遵循栈结构(先进后出),最后被调用的函数最先返回。

执行流程:第一个函数先执行 before,开始执行第二个函数,第二个函数执行 before,开始执行第三个函数,然后第二个函数执行 after,第一个函数执行 after。

拓展:栈可以看作是一个水杯,放进去的东西在最底面,最后才能拿出来

2. 函数进阶

2.1 函数变量的作用域

变量的作用域指的是变量的作用范围(标注这个遍历在哪里可以使用,在哪里不可以使用)

一般来说,我们会把变量分为 局部变量全局变量 ,局部变量只能在函数使用,但是可以使用 global 关键字,声明函数内部的值为全局变量。

补充

  1. 全局变量:在函数之外定义的变量,称之为全局变量,在整个文件中(包括函数内)都可以使用
  2. 局部变量:在函数内部定义的变量,只能够在函数内部访问,外部无法访问(函数执行完毕会自动销毁)
  3. 在项目开发时,尽量避免使用全局变量,这样代码会难以维护,而 global 关键字常用于在程序的状态、配置和计数器等场景。

全局变量的使用方法:先定义变量,再进行使用

python 复制代码
# 定义全局变量
count = 0           # 全局变量 count,初始值为 0
total_score = 100   # 全局变量 total_score,初始值为 100

def add_score(score):
    global total_score          # 声明要使用全局变量
    total_score = total_score + score   # 在函数内部修改全局变量的值

def increment_count():
    global count                # 声明要使用全局变量
    count = count + 1           # 在函数内部修改全局变量的值

# 调用前查看全局变量
print(count)        # 0
print(total_score)  # 100


# 调用函数
add_score(20)       # 将全局变量 total_score 增加 20
increment_count()   # 将全局变量 count 增加 1
increment_count()   # 再次将全局变量 count 增加 1

# 调用后查看全局变量(已被函数修改)
print(count)        # 结果:2 
print(total_score)  # 结果:120 

2.2 函数参数

2.2.1 传参方式

传参方式指的是,在调用函数时,传递实参的方式,分为 位置参数关键字参数

位置参数 :调用函数时根据函数定义时的位置传递参数,也就是参数顺序与定义函数时参数顺序完全一致

python 复制代码
# 定义函数
def reg_stu(name, age, gender, city):
    print(f"注册成功,姓名:{name}, 年龄:{age}, 性别:{gender}, 城市:{city}")
    return {"name": name, "age": age, "gender": gender, "city": city}

# 调用函数
stu = reg_stu("张三", 18, "男", "北京") 		# 对应着 name、age、gender、city
print(stu)

关键字参数 :调用函数时以函数定义形参名称作为关键字,以" 键=值 "的形式来传递参数(不要求顺序)

拓展:如果位置参数与关键字参数混用,关键字参数必须在位置参数之后

python 复制代码
# 定义函数
def reg_stu(name, age, gender, city):
    print(f"注册成功,姓名:{name}, 年龄:{age}, 性别:{gender}, 城市:{city}")
    return {"name": name, "age": age, "gender": gender, "city": city}

# 调用函数
stu = reg_stu(name="张三", age=18, gender="男", city="北京")
print(stu)

stu2 = reg_stu(gender="男", name="王武", city="上海", age=22)
print(stu2)

stu2 = reg_stu("赵四", 28, gender="男", city="上海")		# 这里赵四就是位置参数,男 和 上海 是关键字参数
print(stu2)

总结

  • 位置参数简洁高效,但当参数较多或含义不明确时,容易因顺序错误导致问题,适合参数较少(如不超过3个)的场景
  • 关键字参数优点可读性强易维护易扩展 ,缺点代码繁琐,适合参数多,容易混淆的场景使用
2.2.2 默认参数

默认参数:又称为缺省参数,用于在定义函数的时候,为参数提供默认值,调用函数可以不传递有默认值的参数

python 复制代码
# 定义函数
def reg_stu(name, age, gender, city='北京'):
    print(f"注册成功,姓名:{name}, 年龄:{age}, 性别:{gender}, 城市:{city}")
    return {"name": name, "age": age, "gender": gender, "city": city}

# 调用函数
stu = reg_stu("张三", 18, "男")
print(stu)

stu = reg_stu("赵四", 22, "男", "深圳")
print(stu)

补充

  1. 默认参数必须没有默认值的参数列表后面,一个函数可以设置多个默认参数。
  2. 函数调用时,如果为默认参数传递了值,就会修改默认值,如果没有传递该参数,则直接使用默认值。
2.2.3 不定长参数

不定长参数指可以传递多个参数,且不固定长度,有两种方法

  • 使用*变量名的方式接收位置参数,用于处理数量不稳定的数据,会将多个数据转化为元组
  • 使用**变量名的方式接收关键字参数,用于处理数量不确定的选项(函数的配置参数,用来定制函数的行为),会将多个数据转化为字典
python 复制代码
# 定义函数,可以通过 round 的值去控制小数位数,通过 print 的值控制是否打印
def calc_data(*args, **kwargs):
    min_data = min(args)
    max_data = max(args)
    avg_data = sum(args) / len(args)

    if kwargs.get("r") is not None:
        avg_data = round(avg_data, kwargs.get("r"))

    if kwargs.get("p"):
    		 # 计算出来的最小值: 2, 最大值: 45, 平均值:14.6
        print(f"计算出来的最小值: {min_data}, 最大值: {max_data}, 平均值:{avg_data}")  

    return min_data, max_data, avg_data

# 调用函数
print(calc_data(2, 7, 9, 10, 45, r=3, p=True)) 
2.2.4 参数类型

普通参数:数字、布尔、字符串、列表、元组、集合、字典等。

特殊参数:函数。

函数可以被作为参数,例如下面时模拟计算机,可以指定传递的参数(函数),从而选择加减乘除。

python 复制代码
## 加
def add(x, y):
    return x + y

## 减
def subtract(x, y):
    return x - y

## 乘
def multiply(x, y):  # 1个用法
    return x * y

## 除
def divide(x, y):
    return x / y

## 计算
def calc(x, y, oper):  # 1个用法
    return oper(x, y)

# 这里可以通过复制,去调用不同的函数
print(calc(x=10, y=20, oper=multiply))		# 200
2.2.5 匿名函数

匿名函数指的是没有名称的函数,需要通过lambda表达式来声明函数,可以简化简单函数的编写(单行表达式)。

python 复制代码
# 定义匿名函数
lambda 参数列表: 表达式
# 示例
lambda : print('---')

# 无参数的lambda函数
func1 = lambda: print('---')

# Lambda x, y: x + y
# 有两个参数的lambda函数
func2 = lambda x, y: x + y

# 调用示例
func1()  # 输出: ---
result = func2(10, 20)
print(result)  # 输出: 30

注意

  1. 函数逻辑较简单,且只在一个地方使用时,考虑使用匿名函数简化书写(通常作为高阶函数的参数使用)
  2. 匿名函数可以返回结果,也可以不返回结果(默认返回None),返回不需要写return,表达式的运行结果就是要返回的结果

2.3 类型注解

在进行运算的时候,可能会出现预期不符的现象,例如本该是 int 类型的数,不小心传入了String类型,但由于Python是动态语言,导致运行前不显示错误,这个时候就需要类型注解来提醒。

类型注解是Python中的语法特性,用于明确标识变量、函数参数和返回值的数据类型,当使用类型注解时,调用函数或值,会进行提醒,不影响运行。

2.3.1 变量类型注解

变量类型注解定义语法如下

python 复制代码
# 定义变量
变量名:变量类型 = 值
# 示例
a:int = 695
b:list[int|str] = ["A","C"] 		# 注意,当存储数据容器的时候,可以指定一个数据类型,也可以指定多个数据类型

优点

  • 代码结构更清晰、代码逻辑更安全、更易维护。
  • 更准确的代码自动提示
  • 提前发现代码潜在问题

拓展 :类型推断

类型推断是指Python解释器自动判断出变量、表达式或函数返回值的数据类型的能力,无需开发中显式声明

2.3.2 函数类型注解

为函数添加类型注解,主要为函数的参数和返回值添加类型注解,语法如下

python 复制代码
# 语法
def 函数名(参数名:参数类型) -> 返回值类型:
	return ....

# 示例
def calc(scores: list[int]) -> float:
    return sum(scores) / len(scores)

def calc_data(scores: list[int]) -> tuple[int, int, float]:
    max_v = max(scores)
    min_v = min(scores)
    avg_v = sum(scores) / len(scores)
    return max_v, min_v, avg_v

函数类型注解常用于 团队开发长期维护的项目

3. 模块

3.1 介绍

Python模块(module):一个.py就是一个模块,模块是Python程序的基本组织单位,在模块中可以定义变量、函数、类、可执行的代码。

模块与模块之间是可以互相引用的,Python官方给我们提供了很多自定义模块,比如math(数学计算)、random(随机数)等,通过 import 进行引用,示例如下:

python 复制代码
# 随机点名器
import random

# 人物列表
names = ["王林", "李慕妮", 
    "许立国", "韩立", 
    "涛哥", "莫厉海", 
    "十三", "虎吨", 
    "红蝶", "天运子"]

print(random.choice(names))

通过将不同代码放在不同模块里,不仅避免了命名冲突 ,而且随时拿取,提高代码复用性降低开发门槛

3.2 导入模块

在使用模块提供的功能前,我们需要先导入,再使用,具体语法如下:

导入形式 代码样例 调用方式 调用方式
import 模块名 import random, os 模块名.功能名 random.randint(10, 100)
import 模块名 as 别名 import random as rd 别名.功能名 rd.randint(10, 100)
from 模块名 import 功能名 from random import randint, choice 功能名 randint(10, 100)
from 模块名 import 功能名 as 别名 from random import randint as rint 别名 rint(10, 100)
from 模块名 import * from random import * 功能名 randint(10, 100)
python 复制代码
# 使用 import 模块名 as 别名
import random as rd

# 使用别名调用功能
number = rd.randint(1, 100)  # 生成1-100之间的随机数
name = rd.choice(["张三", "李四", "王五"])  # 随机选择一个名字

print(f"随机数字: {number}")	# 35
print(f"随机姓名: {name}")		# 王五

注意

  1. 在 PyCharm 或大多数其他编译器中,输入对应的方法,会自动导入对应模块,不需要手动导入模块。
  2. 导入模块语句一般写在py文件开头,是因为我们先导入、再使用,且更加直观

3.3 自定义模块

3.3.1 定义

当开发一些复杂的项目,为了让项目结构清晰,方便项目的维护管理 及 代码的复用,可能会把一个项目拆分为若干个模块,我们可以自定义模块并使用,获取里面的变量和函数。

python 复制代码
# my_math.py - 自定义数学模块

def add(a, b):
    """加法函数"""
    return a + b

def multiply(a, b):
    """乘法函数"""
    return a * b

PI = 3.14159  # 模块中的变量
python 复制代码
# 引用刚才的模块
from my_math import add, PI

print(add(20, 30))  # 直接调用,不需要模块名		50
print(PI)

拓展:建议模块的名字遵循 python标识符定义,规范命名。

3.3.2 测试函数

测试函数:Python中内置变量__name__,标识当前模块名字,执行当前模块会执行测试函数内的代码,作为模块导入时,测试函数不执行。

python 复制代码
# my_math.py - 自定义数学模块

def add(a, b):
    """加法函数"""
    return a + b

def multiply(a, b):
    """乘法函数"""
    return a * b

PI = 3.14159  # 模块中的变量

# 当直接运行此文件时执行测试,作为模块导入时不执行
if __name__ == "__main__":
    print("\n手动测试示例:")
    print(add(10, 20))		# 30
    print(multiply(5, 6))	# 30
    print(PI)		# 3.14159

拓展 :Python 借鉴了其他语言的程序入口 main,放运行文件时,会设置内置变量 name = "main ",但如果被导入,他会设置为模块名,这就是为什么作为模块导入时不执行的原因

3.3.3 设置导入功能

__all__是一个模块级别特殊变量,可以指定 from 模块名 import *导入哪些功能

python 复制代码
# all 前后都是两个_
__all__ =["log_separator1","log_separator2","PI"]
PI = 3.1415926
NAME = "超级苦力怕"

def log_separator1():
    print("_ * 30")

def log_separator2():
    print("+ * 30")

def log_separator3():
    print("# * 30")

def log_separator4():
    print("* * 30")

3.4 包

3.4.1 定义

包:本质上是一个文件夹,文件夹中可以包括多个python模块,文件夹还包含了__init__.py(描述当前包的信息)

作用:用来管理多个模块,包本质上也是一个模块。

3.4.2 创建

我们在Pycharm右键文件夹,创建一个包

在包内会自动包含一个__init__模块,我们可以描述包的基本信息,例如

python 复制代码
# 版本
__version__ = "1.0.0"
__author__ ="Coolipa"
# 当导入全部时,导入哪些模块
__all__ = ["my_fun"]

补充:像上述的__name__,还是这里的__version__,只要前面有两个下划线,代表的就是特殊变量。

3.4.3 导入方式
导入形式 代码样例 调用方式 调用方式
import 包名.模块名 import utils.my_fun 包名.模块名.功能名 utils.my_fun.log_separator1()
from 包名 import 模块名 from utils import my_fun 模块名.功能名 my_fun.log_separator1()
from 包名 import * from utils import * 模块名.功能名 my_fun.log_separator1()
from 包名.模块名 import 功能名 from utils.my_fun import log_separator1 功能名 log_separator1()
from 包名.模块名 import * from utils.my_fun import * 功能名 log_separator1()
  • 如果本文对你有帮助:欢迎点赞、收藏,让更多正在学 Python 的同学看到。
  • 遇到问题或有不同理解:可以在评论区留言,一起讨论、互相学习。
  • 想系统看更多内容:可以关注专栏《Python 基础》,一起把基础打牢。
相关推荐
众创岛2 小时前
测试失败时自动截图并附加到 Allure 报告
开发语言·python
Csvn2 小时前
条件判断与循环结构详解
python
maxmaxma2 小时前
ROS2机器人少年创客营:Python第二课
c++·python·机器人
智算菩萨2 小时前
【Tkinter】10 Tkinter Listbox 列表框控件深度解析:多选模式、滚动条联动与双向选择器实战
python·ai编程
csbysj20202 小时前
SQL CREATE DATABASE 指令详解
开发语言
我命由我123452 小时前
React - useEffect、useRef、Fragment
开发语言·前端·javascript·react.js·前端框架·ecmascript·js
蓝之静云2 小时前
mapper执行sql报空指针,需要传入参数
数据库·python·sql
未来龙皇小蓝2 小时前
Java安全通信:RSA签名 + AES混合加密详解
java·开发语言·安全·web安全
heimeiyingwang2 小时前
【架构实战】混沌工程:让系统更健壮的实践
开发语言·架构·php