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 + b

help(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) 
    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]

3. 函数参数传递

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

4. 变量作用域

就近 -> 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

5. 匿名函数

是一种无需使用def关键字定义的轻量级函数,也称为lambda函数,

使用情况

  1. 函数特别简单
  2. 函数只是一次性使用
  3. 某些函数的参数是一个函数
 # 定义一个简单的加法函数
 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

6. 高阶函数

把一个或多个函数当作参数传递给另外一个函数

高阶函数优势

  • 代码简洁,可读性强
  • 可扩展性好
  • 惰性计算 =》当使用数据的时候,才去计算,避免在瞬间资源占用高 =》迭代器和生成器

1. map

map(函数,可迭代对象) => 映射 map object
可迭代对象:list,tuple,string,dict…

# 将列表中所有的元素都转换成绝对值
mylist = [1, -2, -3, 4, -5]
print(map(abs, mylist))	# 
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 + b

def 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)  # 8

print(math_utils.PI)  # 3.14159

calc = 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. 打印商品信息

  1. 打印编写、名称、价格、库存
  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

你可能感兴趣的:(Python,python,开发语言)