函数是Python编程的核心概念之一,掌握函数的使用能大幅提升代码的可读性和复用性。本文将通过大量实例带你深入理解函数的奥秘。
目录
一、函数的意义
二、函数的定义和调用
三、函数的参数形式(重要)
3.1 无参函数
3.2 有参,且有默认值
3.3 可变参数 *参数名,参数类型是元组类型
3.4 带关键字可变参数 **参数名,参数类型是字典类型
3.5 组合关键字,复合型参数
3.6 (高阶函数)函数类型参数
3.6.1 常用内置高阶函数(将函数作为参数的高阶函数)
3.6.2 常用内置高阶函数(将函数作为返回值的高阶函数)
3.7 递归函数
四、函数的返回值(小插曲)
五、函数的嵌套
5.1 变量的作用域(全局和局部)
5.1.1 global关键字
5.1.2 nonlocal关键字
六、lambda表达式(匿名函数)
6.1 lambda表达式特点
6.2 lambda表达式的应用
七、可变类型和不可变类型
函数就像现实生活中的「榨汁机」:输入水果→处理榨汁→输出果汁。在编程中:
在Python实际开发中,我们使用函数的目的只有一个“ 让我们的代码可以被重复使用”
函数的作用有两个:
① 代码重用(代码重复使用) ② 模块化编程(模块化编程的核心就是函数,一般是把⼀个系统分解为若干个功能,每个功能就是一个 函数)
1、调用前必须要已经定义好了
2、调用函数的时候要注意参数的个数、类型、位置
3、调用函数时要关心是否需要使用到返回值
根据参数的位置给实际参数值还是根据参数名给实际参数值
#函数的定义
def 函数名称(参数1, 参数2=默认值, *args, **kwargs):
"""函数文档字符串(可选)"""
函数体代码
return 返回值 # 可选
#函数的调用
函数名称(实际参数1, 参数2=值, 其他参数)
具体示例:
def fly(a):
print(f'hello+{a}')
fly('forever')
fly('lifetime')
fly('youth')
def hello():
print('hello')
hello()# 输出:hello
def order(meal, count=1): # 默认点1份
return f"{count}份{meal}"
print(order("拉面")) # 1份拉面
print(order("饺子", 3)) # 3份饺子
用于不确定调用的时候会传递多少个参数(不传参也可以)的场景。
def total_score(*scores):
return sum(scores) #进行累加
print(total_score(90,85,78)) # 253
def user_info(**info):
for k,v in info.items():
print(f"{k}:{v}",end=' ')
user_info(name="Bob", age=25, city="上海")# 输出:name:Bob age:25 city:上海
def complex_args(a, b=10, *args, c=20, **kwargs):
print(a, b, args, c, kwargs)
complex_args(1, 2, 3, 4, c=5, name="test")
# 输出:1 2 (3,4) 5 {'name':'test'}
当一个函数它的参数中有函数类型时,可称其为高阶函数,当一个函数的返回值是函数时,该函数亦可称为高阶函数
高阶函数的意义:当想把调用者的动作(行为)当参数传入,而不是传入固定数据时,可使用高阶函数
高阶函数中的参数函数可以是内置函数,第三方模块函数,自定义函数,且参数类型和数量得一致
示例如下:
# 高阶函数:接收处理函数作为参数
def self_num(a, b, donum):
return donum(a) + donum(b)
# 折扣函数:数值减半
def dazhe(num):
return num / 2
# 扩展函数:数值放大10倍(未被调用)
def kuoda(num):
return num * 10
# 函数调用
print(self_num(a=3, b=2, donum=dazhe)) # 输出:2.5
print(self_num(a=(4,5,2), b=(5,6,3), donum=max)) # 输出:11
map函数:
# map(函数,可迭代对象):把函数作用于可迭代对象中的每个元素,并返回新的可迭代对象
def my(num):
return num**2
mlist = [1,2,3]
res = map(my,mlist)
print(res)
nres = list(res)
print(nres)#[1,4,9]
reduce函数:
# reduce(函数,可迭代对象)汇总数据
import functools as ft
def sum_(x,y):
return x+y
li= [3,4,5,2,1]
res= ft.reduce(sum_, li)
print(res) # 15
filter函数:
# filter(函数,可迭代对象)过滤掉那些函数返回false的元素,返回一个新的迭代器
def f_f(x):
if x%2==0:
return x
f_list=[20,21,32,43,42,11]
print(list(filter(f_f,f_list)))#[20, 32, 42]
print(list(map(f_f,f_list)))#[20, None, 32, None, 42, None]
sorted函数:
# sorted(可迭代对象,key=行为函数)跟sort方法不同的是,sort方法是改变原来的可迭代对象,sorted是改变后生成一个新的可迭代对象
stu = [
{'name':'jack','age':21},
{'name': 'tom', 'age': 24},
{'name': 'com', 'age': 22},
]
def s_f(x):
return -x['age'],x['name']
# stu.sort(key=s_f)
print(sorted(stu,key=s_f))#[{'name': 'tom', 'age': 24}, {'name': 'com', 'age': 22}, {'name': 'jack', 'age': 21}]
print(stu)#[{'name': 'jack', 'age': 21}, {'name': 'tom', 'age': 24}, {'name': 'com', 'age': 22}]
any函数,all函数:
# any()若可迭代对象中至少有一个为True,则为True
# all()若可迭代对象中所有元素均为True,则为True
num = [2,3,1,4,55,'',1]
i = any(num)#True
b = all(num)#False
print(i,b)
zip函数:
# zip()接受多个可迭代对象,将其元素一一对应重新组合成元组装入迭代器中
name = ['a','b','c']
age = [2,3,4]
print(dict(zip(name, age)))#{'a': 2, 'b': 3, 'c': 4}
enumerate函数:
# enumerate()接受一个可迭代对象和一个可选的起始索引,返回一个迭代器,每个元素是一个索引,包含索引和对应的值
fly = ['five','forever','lifetime']
print(list(enumerate(fly,start=1)))#若start不指定则默认为0
# [(1, 'five'), (2, 'forever'), (3, 'lifetime')]
如果一个函数在执行过程中调用自身,那么这个函数就可以称为递归函数。也就是在函数体中调用自己。 递归函数的特点:
1、函数体中调用自己
2、有一个条件作为出口。不然一直自己调用自己层层套下去就成死循环 了,所以必须要有个条件终止。
def factorial(n):
if n == 1:
return 1
else:
return n * factorial(n - 1)
print(factorial(6)) # 输出: 720
递归过程可视化如下:
factorial(6)
6 * factorial(5)
6 * (5 * factorial(4))
6 * (5 * (4 * factorial(3)))
6 * (5 * (4 * (3 * factorial(2))))
6 * (5 * (4 * (3 * (2 * factorial(1)))))
6 * (5 * (4 * (3 * (2 * 1)))) ← 触发终止条件
6 * (5 * (4 * (3 * 2)))
6 * (5 * (4 * 6))
6 * (5 * 24)
6 * 120
720
def re():
return 1
return 2
print(re())#输出:1
如上例子,仅执行第一条return语句,因为return的作用是退出当前函数,故导致第二条return语句不予执行。
若要使一个函数有多个返回值,则可使用return元组的形式
def re():
return 1,2
print(re())#输出:(1,2)
四则运算:
def size(num1, num2):
jia = num1 + num2
jian = num1 - num2
cheng = num1 * num2
chu = num1 / num2
return jia, jian, cheng, chu
# 调用方法
print(size(20, 5))#输出:(25, 15, 100, 4.0)
定义函数时,顾名思义函数中还包含函数即为嵌套
一般来说,内层函数中可以引用到外层函数中定义的变量,但是反过来不行
当全局变量与局部变量同名时,在函数体中修改全局变量的值,需要使用global关键字来声明
five='五行'
def f():
global five
five = '鑫'
print(five)
f()#鑫
当外部和内部函数中有相同的变量名时,想要在内部函数中修改外部函数中的变量值,需要使用nonlocal关键字声明
def person(**kwargs):
name = kwargs.get('name')
age = kwargs.get('age')
def inner_person():
nonlocal name # 声明name是外部函数的局部变量
nonlocal age # 声明age是外部函数的局部变量
name = "Alice" # 修改外部函数的局部变量
age = 25 # 修改外部函数的局部变量
print("Name: " + name + ", Age: " + str(age))#Name: Alice, Age: 25
inner_person() # 调用内部函数
print("Outer Name: " + name + ", Outer Age: " + str(age))#Outer Name: Alice, Outer Age: 25
# 使用**kwargs语法调用函数
person(name="Bob", age=30)
如果⼀个函数有⼀个返回值,并且只有⼀句代码,可以使用 lambda简化
变量 = lambda 函数参数:表达式(函数代码+ return返回值)
参数有默认值的情况
参数是可变参数的情况
参数是带关键字可变参数的情况
函数体是三目运算符的情况
fly = lambda: 100 # 相当于return 100
f = fly()
print(f)#100
fly1 = lambda a, b: a + b
print(fly1(1, 2))#3
_9 = lambda a, b, c=100: a + b + c
print(_9(9, 9))#118
five = lambda i, j: i + j if i % 2 == 0 and j % 2 == 0 else j * i
print(five(3, 6))#18
fn1 = lambda *args : sum(args)
print(fn1(10, 20, 30))#60
fn2 = lambda **args : args
print(fn2(name='five', age=20, address='flyP'))#{'name': 'five', 'age': 20, 'address': 'flyP'}
在python中经常会遇到可变类型与不可变类型之分,那我们该如何区别呢,可根据地址是否变化进行区分,若改变数据后,变量在内存中的地址改变,即为不可变类型,反之,则为可变类型
id()函数:返回变量在内存中的地址
a = 5
print(id(a)) # 输出:140712010609576
a += 1
print(id(a)) # 输出:140712010609608 地址改变 → 不可变类型
lst = [1,2,3]
print(id(lst)) # 输出:2201999605440
lst.append(4)
print(id(lst)) # 输出:2201999605440 地址不变 → 可变类型