函数 模块 包 =>封装代码 => 代码复用(维护更方便)
包 => 目录(包含多个模块的目录)
模块 => 文件(包含 Python 代码的.py文件,可包含函数、类、变量等)
函数 => 具体代码(实现功能)
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 + b
help(mysum2) # 查看类型注解
help(mysum1)
result = mysum1("abc", "def")
result = mysum2("abc", "def")
# Python 是动态类型语言,变量类型在运行时确定。+操作符根据操作数类型具有不同行为:
# 当a和b是整数时,执行加法
# 当a和b是字符串时,执行拼接
print(result) # abcdef
定义函数参数的顺序要求:
必选参数,可变长位置参数,默认参数,可变长关键字参数
# 必选参数和默认参数
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)
print(kwargs, type(kwargs)) # {'a': 1, 'b': 2, 'c': 3}
mysum(1,2,3,a=1,b=2,c=3)
# 定义一个mysum函数,计算N个数的和(位置参数得到一个和,关键字参数得到一个和)
def mysum(*args, **kwargs):
sum1 = 0
sum2 = 0
for i in args:
sum1 += i
for value in kwargs.values():
sum2 += value
return sum1, sum2
print(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 6
sum1, sum2 = (10, 100)
print(sum1, sum2) # 10 100
mylist = [1,2,3, 3, 4, 5, 6]
a, *b = mylist # *分隔参数
print(a, b) # 1 [2, 3, 3, 4, 5, 6]
Python变量是引用机制
在不可变对象中,参数传递效果类似传值(在函数中的修改不影响函数外)
在可变对象中,参数传递效果类似传地址(在函数中的修改会影响函数外)
Python中函数的传参 -> 传递“引用”
def myfunc(a):
print("函数中1", a, id(a))
a += 1
print("函数中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() # 1
nums = [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
就近 -> LEGB规则
Local(局部作用域):函数内部
Enclosing(闭包作用域): 嵌套函数的外层函数
Global (全局作用域)
Build Built-in(内置作用域):Python 内置模块 如:__file__
a = 3 # Global
def func1():
a = 1 # Enclosing
def func2():
a = 2 # Local
print(a)
func2()
func1() # 2
# 手动声明全局变量
def func3():
global aaa
aaa = 1
func3()
print(aaa) # 1
是一种无需使用def关键字定义的轻量级函数,也称为lambda函数,
使用情况
# 定义一个简单的加法函数
def func4(a, b):
return a + b
func5 = lambda a, b: a + b
print(func5(1, 2)) # 3
# 接受一个列表,返回列表的第一个元素
func6 = lambda a: a[0]
print(func6([1, 2, 3])) # 1
把一个或多个函数当作参数传递给另外一个函数
高阶函数优势
map(函数,可迭代对象) => 映射 map object
可迭代对象:list,tuple,string,dict…
# 将列表中所有的元素都转换成绝对值
mylist = [1, -2, -3, 4, -5]
print(map(abs, mylist)) #
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]
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 …
# 定义模块 math_utils.py
def add(a, b):
"""计算两数之和"""
return a + b
def multiply(a, b):
"""计算两数之积"""
return a * b
# 模块变量
PI = 3.14159
# 模块类
class Calculator:
def power(self, base, exponent):
return base ** exponent
import math_utils # 导入模块
# 使用模块中的功能
result = math_utils.add(3, 5)
print(result) # 8
print(math_utils.PI) # 3.14159
calc = math_utils.Calculator()
print(calc.power(2, 3)) # 8
from math_utils import add, multiply # 导入指定成员
result = add(3, 5)
print(result) # 8
# 错误:未导入PI,需额外声明
# print(PI) # NameError: name 'PI' is not defined
首先在内存中查找该模块,如果已经存在,就不会再导入了(内建对象,已经导入过的对象)
如果内存不存在,通过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")
本质上是一个包含模块和子包的目录
包是一个包含__init__.py文件的目录,其中可包含模块、子包或其他资源
__init__文件,用于对包做初始化
当导入包时,会执行__init__.py文件中的代码
# 导入整个包
import 包名
# 导入包中模块
import 包名.模块
# 绝对导入(推荐)
form 包名 import 模块
# 相对导入(只能在包内部使用)
from . import 模块
函数:封装可复用的代码逻辑
模块:将相关函数组织到一个文件中
包:将多个模块组织到一个目录,通过__init__.py控制导入行为
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
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'}
数字在前,字母在后,且不改变原来的顺序
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