python-函数模块包
python-函数模块包
- 前言
- 一、函数
- 1. 函数的定义
- 2. 函数的参数
- 2.1 形参分类(定义)
- 2.2 实参分类(调用)
- 3. 函数参数传递
- 4. 变量作用域
- 5. 匿名函数
- 6. 高阶函数
- 1. map
- 2. filter
- 3. sorted
- 二、模块
- 1. 定义模块
- 2. 导入模块
- 3. 导入指定函数
- 4. 模块的执行机制
- 三、包
- 1. 包的结构
- 2. 导入包
- 总结
- 练习
- 1. 编写函数实现提取身份证号码中的年月日信息
- 2. 打印商品信息
- 3. sorted排序
前言
函数 模块 包 =>封装代码 => 代码复用(维护更方便)
包 => 目录(包含多个模块的目录)
模块 => 文件(包含 Python 代码的.py文件,可包含函数、类、变量等)
函数 => 具体代码(实现功能)
一、函数
1. 函数的定义
def 函数名(参数列表:参数类型)-》参数返回值:函数体# 返回值(return可以没有,如果没有,返回None)return
参数的数量:0个,1个或n个
返回值数量:0个,1个或n个
建议:尽量用return将数据返回,而不是用print输出(只能在控制台看到结果,不能将结果返回到主程序,数据不能进行后续操作)
尽量写一些注释
尽量写一些类型注解
类型注解是可选的,并且不会在运行时强制执行
# 计算两个数的和
def mysum1(a, b):return a + b
# 函数调用
result = mysum1(1, 2)
print(result) # 3# 计算两个数的和(类型声明->方便使用者了解函数需要的类型,不一致不会报错)
def mysum2(a:int, b:int):# 类型注解""":param a: 一个加数:param b: 另一个加数:return: 返回两个数的和"""return a + bhelp(mysum2) # 查看类型注解
help(mysum1)result = mysum1("abc", "def")
result = mysum2("abc", "def")
# Python 是动态类型语言,变量类型在运行时确定。+操作符根据操作数类型具有不同行为:
# 当a和b是整数时,执行加法
# 当a和b是字符串时,执行拼接
print(result) # abcdef
2. 函数的参数
2.1 形参分类(定义)
- 必须参数 a:调用时必须要填写
- 默认参数 a=0:调用时没有传参,那么就是用默认值
- 可变长位置参数 *args:N个按位置传递的参数 =》()
- 可变长关键字参数 **kwargs: key = value =》 {key:value}
定义函数参数的顺序要求:
必选参数,可变长位置参数,默认参数,可变长关键字参数
2.2 实参分类(调用)
- 位置参数:mysum(1, 2) =》 按位置一一对应
- 关键字参数:
mysum(a=1, b=2) => 按参数名字进行对应
mysum(b=2, a=1)
# 必选参数和默认参数
def stuinfo(name:str, age:int,sex="female"):print(name, age, sex)stuinfo("cali",18) # cali 18 female
stuinfo("cali",18,"male") # cali 18 male
stuinfo(age=18,name="cali") cali 18 female
# 如果位置参数和关键字参数混用,先写位置参数,再写关键字参数
stuinfo("cali",age=18,sex="male") cali 18 male# stuinfo(age=18,sex="male","cali")
# SyntaxError: positional argument follows keyword argument# 可变长位置参数,可变长关键字参数
def mysum(*args, **kwargs):print(args,type(args)) # (1, 2, 3) <class 'tuple'>print(kwargs, type(kwargs)) # {'a': 1, 'b': 2, 'c': 3} <class 'dict'>
mysum(1,2,3,a=1,b=2,c=3) # 定义一个mysum函数,计算N个数的和(位置参数得到一个和,关键字参数得到一个和)
def mysum(*args, **kwargs):sum1 = 0sum2 = 0for i in args:sum1 += ifor value in kwargs.values():sum2 += valuereturn sum1, sum2print(mysum(1,2,3,a=1,b=2,c=3)) # (6, 6) # 返回值 值1, 值2 => 多个返回值,返回的是一个元组
# 数据的pack,unpack
sum1, sum2 = mysum(1,2,3,a=1,b=2,c=3)
print(sum1, sum2) # 6 6sum1, sum2 = (10, 100)
print(sum1, sum2) # 10 100mylist = [1,2,3, 3, 4, 5, 6]
a, *b = mylist # *分隔参数
print(a, b) # 1 [2, 3, 3, 4, 5, 6]
3. 函数参数传递
Python变量是引用机制
在不可变对象中,参数传递效果类似传值(在函数中的修改不影响函数外)
在可变对象中,参数传递效果类似传地址(在函数中的修改会影响函数外)
Python中函数的传参 -> 传递“引用”
def myfunc(a):print("函数中1", a, id(a))a += 1print("函数中2", a, id(a))a = 1
print("执行前", a, id(a))
myfunc(a)
print("执行后", a, id(a))
# 执行前 1 140710943463864
# 函数中1 1 140710943463864
# 函数中2 2 140710943463896 影响函数外
# 执行后 1 140710943463864 def myfunc(a):print("函数中1", a, id(a))a += [2]# a.append(2)print("函数中2", a, id(a))a = [1]
print("执行前", a, id(a))
myfunc(a)
print("执行后", a, id(a))
# 执行前 [1] 2050786506496
# 函数中1 [1] 2050786506496
# 函数中2 [1, 2] 2050786506496 不影响函数外
# 执行后 [1, 2] 2050786506496# 关于默认值注意 !!!!
# 产生此现象的原因:形参默认参数,在函数定义时开拓了空间(类似java/c中静态变量)
def myfunc(nums=[]):print("函数中", id(nums))nums.append(1)print("函数中", nums, id(nums))print(sum(nums))myfunc() # 1nums = [1, 2, 3]
print("函数外", id(nums))
myfunc(nums) # 7
myfunc() # 2
myfunc() # 3# 推荐写法
def myfunc(nums=None):if nums is None: nums = [1, 2, 3, 4]print("函数中1", id(nums))nums.append(1)print("函数中2", nums, id(nums))print(sum(nums))myfunc()
# 函数中1 1808177549696
# 函数中2 [1, 2, 3, 4, 1] 1808177549696
# 11
nums = [1, 2, 3]
print("函数外", id(nums)) # 函数外 1808177549696
myfunc(nums)
# 函数中1 1808177549696
# 函数中2 [1, 2, 3, 1] 1808177549696
# 7
myfunc()
# 函数中1 1808180548288
# 函数中2 [1, 2, 3, 4, 1] 1808180548288
# 11
myfunc() # 11
4. 变量作用域
就近 -> LEGB规则
Local(局部作用域):函数内部
Enclosing(闭包作用域): 嵌套函数的外层函数
Global (全局作用域)
Build Built-in(内置作用域):Python 内置模块 如:__file__
a = 3 # Globaldef func1():a = 1 # Enclosingdef func2():a = 2 # Localprint(a)func2()
func1() # 2# 手动声明全局变量
def func3():global aaaaaa = 1func3()
print(aaa) # 1
5. 匿名函数
是一种无需使用def关键字定义的轻量级函数,也称为lambda函数,
使用情况
- 函数特别简单
- 函数只是一次性使用
- 某些函数的参数是一个函数
# 定义一个简单的加法函数def func4(a, b):return a + bfunc5 = lambda a, b: a + b
print(func5(1, 2)) # 3# 接受一个列表,返回列表的第一个元素
func6 = lambda a: a[0]
print(func6([1, 2, 3])) # 1
6. 高阶函数
把一个或多个函数当作参数传递给另外一个函数
高阶函数优势
- 代码简洁,可读性强
- 可扩展性好
- 惰性计算 =》当使用数据的时候,才去计算,避免在瞬间资源占用高 =》迭代器和生成器
1. map
map(函数,可迭代对象) => 映射 map object
可迭代对象:list,tuple,string,dict…
# 将列表中所有的元素都转换成绝对值
mylist = [1, -2, -3, 4, -5]
print(map(abs, mylist)) # <map object at 0x0000024329C17760>
print(list(map(abs, mylist))) # [1, 2, 3, 4, 5]# 计算每个元素的平方
print(list(map(lambda x: x * x, mylist))) # [1, 4, 9, 16, 25]# 将列表中的用户名转换成标准的名称:首字母大写其他字母小写
mylist = ["mary", "LISA", "CAli", "ToNy"]
print(list(map(lambda x: x[0].upper() + x[1:].lower(), mylist)))
print(list(map(lambda x: x.title(), mylist))) # ['Mary', 'Lisa', 'Cali', 'Tony']
2. filter
filter: 过滤器 =>将可迭代对象中的每一个元素都进行function运算
如果运算结果位True,保留该数,如果为False。不保留该数
filter(function or None, iterable) --> filter object
# 筛选出列表中的偶数
mylist = [1, -2, -3, 4, -5]
print(list(filter(lambda x: x % 2 == 0, mylist))) # [-2, 4]# 筛选出列表中的负数
print(list(filter(lambda x: x < 0, mylist))) # [-2, -3, -5]
3. sorted
sorted(iterable, key=None,reverse=False):排序
key => 函数
# 将列表进行排序
mylist.sort(reverse=True)
print(mylist) # [4, 1, -2, -3, -5]mylist = [("mary", "80"), ("LISA", "30"), ("CAli", "50"), ("ToNy", "90"), ("Cara", "90")]
# 按成绩排序
sorted_by_name = sorted(mylist, key=lambda x: x[1])
print(sorted_by_name) # [('LISA', '30'), ('CAli', '50'), ('mary', '80'), ('ToNy', '90'), ('Cara', '90')]# 按名字首字母排序(不区分大小写)
sorted_by_name = sorted(mylist, key=lambda x: x[0].upper())
print(sorted_by_name) # [('CAli', '50'), ('Cara', '90'), ('LISA', '30'), ('mary', '80'), ('ToNy', '90')]
# 按成绩排序+名字首字母排序(不区分大小写)
sorted_by_name = sorted(mylist, key=lambda x: (x[1], x[0].upper()))
print(sorted_by_name) # [('LISA', '30'), ('CAli', '50'), ('mary', '80'), ('Cara', '90'), ('ToNy', '90')]# 按绝对值进行排序
mylist = [1, -2, -1, 4, -8]
print(sorted(mylist, key=lambda x: abs(x)))
print(sorted(mylist, key=abs)) # [1, -1, -2, 4, -8]
二、模块
一个包含 Python 代码的.py文件,将相关的函数、类、变量等封装在一个文件中,便于复用和维护
模块的定义:模块名与变量的命名要求一致
模块导入
导入整个模块/包 import …
导入指定函数 from … import …
1. 定义模块
# 定义模块 math_utils.py
def add(a, b):"""计算两数之和"""return a + bdef multiply(a, b):"""计算两数之积"""return a * b# 模块变量
PI = 3.14159# 模块类
class Calculator:def power(self, base, exponent):return base ** exponent
2. 导入模块
import math_utils # 导入模块# 使用模块中的功能
result = math_utils.add(3, 5)
print(result) # 8print(math_utils.PI) # 3.14159calc = math_utils.Calculator()
print(calc.power(2, 3)) # 8
3. 导入指定函数
from math_utils import add, multiply # 导入指定成员result = add(3, 5)
print(result) # 8# 错误:未导入PI,需额外声明
# print(PI) # NameError: name 'PI' is not defined
4. 模块的执行机制
首先在内存中查找该模块,如果已经存在,就不会再导入了(内建对象,已经导入过的对象)
如果内存不存在,通过sys.path路径顺序一个一个地查找
# math_utils.py(新增测试代码)
def add(a, b):return a + b# 仅在直接运行模块时执行(非导入时)
if __name__ == "__main__":print("测试add函数:", add(1, 2)) # 输出: 测试add函数: 3
__name__ 是模块的内置变量:
当直接运行模块时,__name__ == “__main__” 为True
当模块被导入时,__name__ 为模块名(如"math_utils")
三、包
本质上是一个包含模块和子包的目录
1. 包的结构
包是一个包含__init__.py文件的目录,其中可包含模块、子包或其他资源
__init__文件,用于对包做初始化
当导入包时,会执行__init__.py文件中的代码
2. 导入包
# 导入整个包
import 包名# 导入包中模块
import 包名.模块# 绝对导入(推荐)
form 包名 import 模块
# 相对导入(只能在包内部使用)
from . import 模块
总结
函数:封装可复用的代码逻辑
模块:将相关函数组织到一个文件中
包:将多个模块组织到一个目录,通过__init__.py控制导入行为
练习
1. 编写函数实现提取身份证号码中的年月日信息
def date(a):""":param a: 输入身份证号:return: 返回年月日信息"""a = str(a)try:if len(a) != 18:raise Exception("请输入18位有效数字")elif a.isdigit() == False:raise Exception("请输入18位有效数字")except Exception as e:raise Exception("请输入18位有效数字:", e)return a[6:14]# result = date(input("请输入:"))
result = date(123456202506157890)
print(f"年月日为:{result}") # 年月日为:20250615
2. 打印商品信息
- 打印编写、名称、价格、库存
- 打印多样化的商品信息
pro_info = {
“p001”: {“name”: “苹果”, “price”: 5, “store”: 100, “size”: 100, “color”: “red”},
“p002”: {“name”: “香蕉”, “price”: 3, “store”: 150, “size”: 50, “color”: “yellow”},
“p003”: {“name”: “橘子”, “price”: 2, “store”: 200, “size”: 20, “color”: “orange”},
}
def show_info1():for key, value in pro_info.items():print(f"商品ID:{key},水果:{value['name']},价格:{value['price']},库存:{value['store']}")
def show_info2():for key, value in pro_info.items():print(f"商品ID:{key},商品信息:{value}")show_info1() # 示例:商品ID:p001,水果:苹果,价格:5,库存:100
show_info2() # 示例:商品ID:p001,商品信息:{'name': '苹果', 'price': 5, 'store': 100, 'size': 100, 'color': 'red'}
3. sorted排序
数字在前,字母在后,且不改变原来的顺序
mystr = “1a4b3c4d5e6f”
-> 143456abcdef
sorted_chars = sorted(enumerate(mystr), key=lambda x: (x[1].isalpha(), x[0]))
# 提取元组的第二个元素 char(即字符本身),忽略第一个元素 index(用 _ 表示占位)
result = ''.join(char for _, char in sorted_chars)
print(result) # 143456abcdef