函数
函数定义
函数是组织好的,可重复使用的,用来实现单一或相关联功能的代码段。
python函数定义规则:
def my_max(a,b): #定义函数用def关键字开头,函数名-》my_max ()定义参数 if a>b: #函数体以:开始并进行缩进return a #结束函数,选择性返回一个值给调用方,不带return相当于返回Noneelse: return b
print(my_max(3,4)) #函数名() 函数调用
函数参数
def modify(a): print(hex(id(a))) #0x7ff92c79e328 a=10 #传入不可变对象相当于传入新的a,不改变原传入对象的值print(hex(id(a))) #0x7ff92c79e328print(a) #10
a=1
print(hex(id(a))) #0x7ff92c79e448
modify(a)
print(a) #1
def modify(lis): #可变类型对象的测试,原对象传过来修改也影响了原对象lis.append([1,2])print('list in func ',lis) #[1, 2, 3, [1, 2]]print(hex(id(lis))) #0x22215e11f00 函数内地址与函数外一样
mylis=[1,2,3]
print(hex(id(mylis))) #0x22215e11f00
modify(mylis)
print('out funct ',mylis) #[1, 2, 3, [1, 2]]
参数类型
必需参数 | 必需参数须以正确的顺序传入函数,调用时的数量必须和声明时的一样。 |
关键字参数 | 函数调用使用关键字参数来确定传入的参数值,使用关键字参数允许函数调用时参数的顺序与声明时不一致,因为 Python 解释器能够用参数名匹配参数值。 |
默认参数 | 调用函数时,如果没有传递参数,则会使用默认参数,传递了自然用传递的参数 |
不定长参数 | 在形参前边加上一个* ,这样这个形参将会获取到所有的实参,并将所有的实参保存到一个元组中,* 形参只能接收位置参数,而不能接收关键字参数。** 形参可以接收其他的关键字参数,它会将这些参数统一保存到一个字典中。字典的 key 就是参数的名字,字典的 value 就是参数的值。** 形参只能有一个,并且必须写在所有参数的最后。 |
#必须参数
def show(str):print(str)return
# show() #TypeError: show() missing 1 required positional argument: 'str'
show('2') #关键字参数
def show1(name,age):print(name,age)return
show1(age=10,name='AC')
show1(name='AC',age=10)
show1('AC',6)
#默认参数
def show2(name,age=10,add='here'): #与C++一样,一旦有了默认值后面的都要有print(name,age,add)return
show2(age=2,name='AC')
show2(name='AC')
#不定长参数
def show3(*name):print(name,type(name)) #('ac', 'li', 'io') <class 'tuple'>
show3('ac','li','io')
def show4(arg,*name):print(arg) print(name)
show4(1) #1 ()
show4(1,2) # 1 (2,)
show4(1,2,4) #1 (2,4)
def show5(arg,*name,age): #age 必须使用关键字参数print(arg,name,age)
show5(1,2,3,age=5) #1 (2, 3) 5
def show6(arg, name, **a): #** 形参可以接收其他的关键字参数,它会将这些参数统一保存到一个字典中print('a =', a, type(a)) #a = {'x': 3, 'y': 4} <class 'dict'>print(arg,name)
show6(arg=1,name=2,x=3,y=4)
show6(1,2,x=3,y=4) #a = {'x': 3, 'y': 4} <class 'dict'>
#强制位参数
def show7(a,b,/,c,d,*,e):print(a,b,c,d,e)
show7(1,2,3,d=4,e=5)
#show7(1,b=2,c=3,d=4,e=5) #b 不能使用关键字参数的形式
#show7(1,2,3,4,5) #e 必须使用关键字参数的形式
匿名函数
#匿名函数定义及调用
func=lambda x,y:x+y #lambda 生成一个函数对象,参数x,y 返回值x+y
func(1,2) #3 函数对象赋给了func, 使用变量调用函数和普通函数无异
#匿名函数作为返回值
def build(x,y):return lambda: x*x+y*y
build(2,3)()
高阶函数
函数式编程:是一种编程范式,一种结构化编程(子程序或者程序代码块),思想在于尽量协程一系列嵌套的函数调用,它的特点是允许把函数作为参数传给另一个函数,还可以返回一个函数,python并非函数式编程语言,但是支持一些函数式编程构建(匿名函数、BIF(filter/map)、偏函数)本质上通过封装对象实现函数式编程。
内置高阶函数map、filter、reduce
# filter函数的使用
def is_odd(x):return x % 2 == 1# 使用filter过滤出列表中的奇数
list_of_numbers = [1, 2, 3, 4, 5, 6]
filtered_numbers = filter(is_odd, list_of_numbers)
print(list(filtered_numbers)) # 输出: [1, 3, 5]
result = list(filter(lambda x: x % 2 == 0, [1, 2, 3, 4, 5]))
print(result) # [2, 4]# map函数的使用
def square(x):return x * x# 使用map计算列表中每个数的平方
list_of_numbers = [1, 2, 3, 4, 5]
squared_numbers = list(map(square, list_of_numbers))
print(squared_numbers) # 输出: [1, 4, 9, 16, 25]
result = list(map(lambda x: x * x, [1, 2, 3, 4, 5]))
print(result) # [1, 4, 9, 16, 25]# reduce函数的使用(Python 3中需要从functools模块导入)
from functools import reducedef add(x, y):return x + y# 使用reduce进行求和
list_of_numbers = [1, 2, 3, 4, 5]
result = reduce(add, list_of_numbers)
print(result) # 输出: 15
result = reduce(lambda x, y: x + y, [1, 2, 3, 4, 5])
print(result) # 15
装饰器
装饰器是一种特殊类型的函数,它可以修改或增强其他函数的功能,而无需更改原始函数的源代码。装饰器本质上是一个接收函数作为参数的函数,它返回一个新的函数或者修改过的原函数。
#装饰器
def decorator(func):def wrapper():print("Before func_to_decorate called.")func()print("After func_to_decorate called.")return wrapper
@decorator
def func_to_decorate():print("Function to decorate.")
func_to_decorate()
闭包
闭包(closure)是一个函数和它所引用环境的组合。在Python中闭包通常是指在函数内部定义的函数,该内部函数可以访问外部函数的局部变量,即使外部函数已经返回。闭包的一个常见用途是创建可以记住某些状态的函数。
#闭包
# 默认情况下,内部函数不能直接修改外部函数的局部变量,除非它使用 nonlocal 关键字声明
def outer_function(x):print('out_func',x) #2def inner_function(y):print('inner ',y) #3 当double(3)传入return x * y return inner_functiondouble = outer_function(2)
print(double(3)) # 6
变量的作用域
作用域就是一个 Python 程序可以直接访问命名空间的区域,在一个 python 程序中,直接访问一个变量,会从内到外依次访问所有的作用域直到找到,否则会报未定义的错误。
变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称。Python 的作用域一共有4种,分别是:
- L(Local):最内层,包含局部变量,比如一个函数/方法内部。
- E(Enclosing):包含了非局部(non-local)也非全局(non-global)的变量。比如两个嵌套函数,一个函数(或类) A 里面又包含了一个函数 B ,那么对于 B 中的名称来说 A 中的作用域就为 nonlocal。
- G(Global):当前脚本的最外层,比如当前模块的全局变量。
- B(Built-in): 包含了内建的变量/关键字等,最后被搜索。
搜索规则顺序: L –> E –> G –> B在局部找不到,便会去局部外的局部找(例如闭包),再找不到就会去全局找,再者去内置中找。当内部作用域想修改外部作用域的变量时,就要用到 global 和 nonlocal
global关键字用于在函数内部声明变量为全局变量。当需要在一个函数内修改全局作用域中的变量时,就需要使用global关键字。
nonlocal关键字用来在函数或其他作用域中使用外层(非全局)变量。它主要用在嵌套函数中,当需要修改嵌套作用域内的变量时使用nonlocal。
z=30
def out_fun():y=20global z #表明全局变量被修改z=39print("global z: ",z) #39 if no global 39print(len("sf")) #2 内建函数def func():x=10 #局部嵌套变量nonlocal y #内存修改了外层变量y=24print("local x: ",x) #10print("Local y: ",y) #24 if no nonlocal 24print("global z: ",z) #39 if no global 39func()#print(x) #外部不可以调用print("out local y: ",y) #24 if no nonlocal 20
out_fun()
print("global z: ",z) #39 if no global 30
偏函数
functools.partial的作用就是,把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,调用这个新函数会更简单
from functools import partial
def func(a, b, c):return a + b + c
# 创建一个新的偏函数,预先绑定a=1和b=2
new_func = partial(func, a=1, b=2)
# 现在可以调用new_func并只提供c的值
result = new_func(c=3) # 返回 6
模块-包
模块:是一个包含所有你定义的函数和变量的文件,以.py后缀结尾。模块可以被别的程序引入和使用其中的函数功能。
包Package: 即文件夹,传统包里有一个 __init__.py
文件。可以为空文件,但一定要有该文件,它是包的标志性文件,在需要情况下可以在里面进行一些包的初始化工作。
#模块
import math #导入Python标准库中的math模块
print(math.sqrt(4))
from math import sqrt #也可以导入模块中的特定函数或对象如只导入sqrt函数
print(sqrt(3))
#模块重载 Python解释器会在模块第一次导入时执行模块文件。如果模块文件发生了改变
# 必须先卸载模块,然后再重新导入,以便获取最新的代码。可以使用importlib.reload()
# 函数来卸载并重新导入模块:
# import importlib
# import my_module
# # 对my_module.py做一些修改
# importlib.reload(my_module)#包,创建包需要一个名为__init__.py的文件,它可以为空,但其存在表明这个目录
#应被视为一个包。如创建一个名为my_package的包:
#my_package/
# __init__.py
# my_module.py
#__init__.py文件可以包含初始化代码和要导入的对象。例如,在my_package/__init__.py
# 中导入my_module中的my_function:# my_module.py 在my_module.py中,可以定义一个函数
# def my_function():
# print("Hello from my_package!")
#from my_package.my_module import my_function
#my_function() # 输出:Hello from my_package!#包的导入 分为相对导入和绝对导入
#相对导入(以点开头),from .my_module import my_function
# 或绝对导入(直接指定模块或子包的名称) from my_package.my_module import my_function#包版本管理
#每个包都可以包含一个名为__version__.py的文件,用于指定包的版本。这可以通过
#导入pkg_resources模块来检查