目录
一、普通函数
1.1 函数的定义与调用
1.2 函数的说明文档
1.3 函数的参数
1.4 函数的返回值
二、函数的作用域和关键字
2.1 局部作用域
2.2 全局作用域
2.4 global关键字和nonlocal关键字的使用
三、函数的递归与嵌套
3.1 嵌套函数
3.2递归函数
四、函数名的应用
4.1 函数名可以作为另一个函数的参数或者返回值
4.2 函数名可以成为字典、集合、列表、元组中的元素
五、匿名函数与高阶函数
5.1 匿名函数
5.2 高阶函数
六、函数的闭包与装饰器
6.1 闭包
6.2 装饰器
一、普通函数
1.1 函数的定义与调用
定义:
def 函数名(参数):
函数体
return 返回值
函数通过def关键字定义,def关键字后面跟着函数的函数名,函数名后面跟着小括号,小括号里面传入函数需要的参数(函数可以有参数也可以没有参数)。中间写函数体,最后写返回值(返回值可以有可以没有,默认为None)。
1.2 函数的说明文档
定义:函数说明文档(docstring)是用来描述函数功能、参数、返回值等信息的字符串,直接写在函数定义的第一行,使用三重引号 """ """
包裹。它可以帮助其他开发者快速理解函数的用途,也方便自动生成文档。
使用内置函数help()可以查看函数的说明文档、使用函数名.__doc__的方式也能够查看。
示例:
def add(a, b):"""计算两个数的和。参数:a (int or float): 第一个加数b (int or float): 第二个加数返回:int or float: 两数之和"""return a + bhelp(add)
print(add.__doc__)
1.3 函数的参数
函数的参数有可变参数与不可变参数
不可变参数:位置参数、关键字参数、仅关键字参数、默认参数。
可变参数:可变位置参数(*args)、可变关键字参数(**kwargs)。
参数的定义顺序为:位置参数-->关键字参数-->可变位置参数(*args)-->仅关键字参数-->可变关键字参数(**kwargs)
1.4 函数的返回值
函数的返回值可以有多个(当有多个返回值时,会自动打包成元组),也可以没有返回值,返回值默认为None
二、函数的作用域和关键字
函数作用域遵循以下规则:Python 按 LEGB 顺序查找变量:Local(局部作用域)→ Enclosing(闭包作用域) → Global(全局作用域) → Built-in(内置作用域)。
2.1 局部作用域
定义在函数内的变量称为局部变量,该变量只能在局部作用域中访问和修改。
2.2 全局作用域
定义在函数外的变量称为全局变量,该变量可以在任意作用域中访问。
2.3 可变类型与不可变类型
可变类型:指的是在对某一可变类型进行修改时不会随着修改而改变内存地址的,即对象本身不变。(可变类型有:列表,字典,集合)
不可变类型:该对象在内存中的地址固定,一旦确定了将不会发生改变,如果对该对象进行修改则会改变它在内存中的地址。(不可变类型有:字符串,元组,数值类型,布尔类型)
可变类型与不可变类型在函数作用域的影响:我们都知道,在局部作用域中如果不使用global关键字声明的话就只能对对象进行访问不能进行修改,如果该对象是一个可变类型的,那么我们在局部作用域中也能够对该对象进行访问和修改的操作(这里的修改不是改变该对象本身)
2.4 global关键字和nonlocal关键字的使用
global关键字:
如果想通过局部作用域来修改全局变量的话,那么就需要使用global关键字来声明。被global关键字声明的变量可以在局部作用域中被修改(未声明的变量只能访问)。
示例:
使用global:在函数内部,如果想要修改函数外部(全局作用域)定义的变量,必须使用 global 关键字声明该变量。x = 10 # 全局变量def modify():global x # 声明x是全局变量x = 20 # 修改全局变量xmodify() print(x) # 输出 20
不使用global:如果没有使用 global,函数内部对同名变量的赋值会创建一个新的局部变量,不会影响全局变量。
x = 10def modify():x = 20 # 这里创建了一个局部变量x,和全局变量无关modify() print(x) # 输出 10,未被修改
nonlocal关键字:
nonlocal 用于在嵌套函数中声明变量,表示该变量不是当前函数的局部变量,而是外层(但不是全局)函数作用域中的变量。这样,内层函数就可以修改外层函数中的变量。
示例:多层嵌套
def outer():x = 10def middle():nonlocal xdef inner():nonlocal xx = 30inner()middle()print(x) # 输出 30outer()
三、函数的递归与嵌套
3.1 嵌套函数
定义:在一个函数内部定义另一个函数,或者在函数内部调用另一个函数,满足其中任意一个条件即称为嵌套函数。
示例:inner_function 是定义在 outer_function 内部的嵌套函数,outer_function 内部调用了 inner_function。
def outer_function(x):def inner_function(y):return y * yreturn inner_function(x) + 1print(outer_function(3)) # 输出 10,因为 3*3+1=10
3.2递归函数
定义:递归函数就是函数自己调用自己
注意事项:在使用递归函数的时候要给递归函数设置一个出口,否则函数会一直执行下去直到栈溢出。
示例:factorial 函数通过递归计算阶乘,if n == 0 是递归出口,防止无限递归。
def factorial(n):if n == 0: # 递归出口return 1else:return n * factorial(n - 1) # 函数自己调用自己print(factorial(5)) # 输出 120
四、函数名的应用
4.1 函数名可以作为另一个函数的参数或者返回值
示例:函数名本质上是指向函数对象的引用,可以作为参数传递给其他函数,也可以作为函数的返回值返回。
def greet():return "Hello!"def call_func(func):return func() # 调用传入的函数result = call_func(greet)
print(result) # 输出:Hello!def get_greet_func():return greet # 返回函数对象f = get_greet_func()
print(f()) # 输出:Hello!
4.2 函数名可以成为字典、集合、列表、元组中的元素
示例:函数名作为函数对象,可以存储在各种数据结构中,便于动态调用。
def add(x, y):return x + ydef multiply(x, y):return x * yfunc_list = [add, multiply]
print(func_list[0](2, 3)) # 输出:5
print(func_list[1](2, 3)) # 输出:6func_dict = {'加法': add, '乘法': multiply}
print(func_dict['加法'](4, 5)) # 输出:9func_tuple = (add, multiply)
print(func_tuple[1](3, 7)) # 输出:21func_set = {add, multiply}
for f in func_set:print(f(1, 2)) # 依次输出3和2(顺序不确定)
五、匿名函数与高阶函数
5.1 匿名函数
匿名函数指的是只用一串代码就能定义的函数,使用lambda关键字声明。
语法:lambda 参数:函数体+返回值(函数体就是返回值,返回值就是函数体)
应用场景:对一些比较简单的函数的创建与使用,作为高阶函数中的参数,对一些只使用一次的简单函数的创建。
示例:
# 普通函数定义
def add(x, y):return x + yprint(add(3, 5)) # 输出 8# 使用匿名函数
add_lambda = lambda x, y: x + y
print(add_lambda(3, 5)) # 输出 8# 作为高阶函数参数
numbers = [1, 2, 3, 4, 5]# 用lambda对列表元素平方
squares = list(map(lambda x: x ** 2, numbers))
print(squares) # 输出 [1, 4, 9, 16, 25]# 用lambda筛选偶数
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(evens) # 输出 [2, 4]# 用lambda排序,根据字符串长度排序
words = ['apple', 'banana', 'pear', 'grape']
words_sorted = sorted(words, key=lambda s: len(s))
print(words_sorted) # 输出 ['pear', 'grape', 'apple', 'banana']
5.2 高阶函数
定义:一个函数如果他的参数中有函数名,或者是他的返回值有函数名就可以被称为高阶函数
常见的高阶函数有:
1、map(function, iterable)
参数:第一个参数为函数,第二个参数为可迭代对象
返回值:返回一个迭代器对象
作用:对可迭代对象中的每个元素执行指定函数。返回一个新的迭代器(返回结果为该迭代器的内存地址)
2、reduce(function, iterable[, initializer])
参数:第一个参数为函数,第二个参数为可迭代对象。initializer用于指定计的初始值。
- 如果指定了 initializer,累计时的第一个调用会用 initializer 和可迭代对象的第一个元素作为参数调用 function。
- 如果不指定,reduce 会用可迭代对象的前两个元素作为第一次调用的参数,累计结果从第一个元素开始。
返回值:返回一个数值型对象。
作用:对可迭代对象的元素累计执行函数(函数必须接收两个参数),将函数返回的结果与下一个元素做累积处理,最终返回单一值。
示例:
from functools import reduce# 计算列表元素之和
result = reduce(lambda x, y: x + y, [1, 2, 3, 4], 10)
print(result) # 输出 20,因为初始值是 10,累计结果是 10+1+2+3+4=20
3、filter(function, iterable)
参数:第一个参数是一个函数,第二个参数是可迭代对象
作用:根据函数定义的规则过滤可迭代对象,保留函数返回值为True的元素,返回一个过滤后的迭代器对象。
返回值:返回一个迭代器对象
4、sorted(iterable, *, key=None, reverse=False)
参数:第一个参数为可迭代对象,第二个参数为‘*’目的是为了使key和reverse变为仅关键字参数,key是一个函数用于指定排序规则,默认为None。reverse为False时为升序排序,为True时为降序排序。
返回值:返回一个列表。
作用:对可迭代对象排序,按照key所定义的规则,返回一个新的列表。
示例:
# 对数字列表升序排序(默认)
print(sorted([3, 1, 4, 2])) # 输出 [1, 2, 3, 4]# 对数字列表降序排序
print(sorted([3, 1, 4, 2], reverse=True)) # 输出 [4, 3, 2, 1]# 根据字符串长度排序
words = ['apple', 'banana', 'cherry', 'date']
print(sorted(words, key=len)) # 输出 ['date', 'apple', 'banana', 'cherry']
5、zip(*iterables, strict=False)
参数:第一个参数为任意数量的可迭代对象,第二个参数strict默认为False
- 如果为 False(默认),zip 会以最短的可迭代对象长度为准,生成对应数量的元组,超出部分会被忽略。
- 如果为 True,则要求所有可迭代对象长度相同,否则会抛出 ValueError 异常。
返回值:返回一个迭代器对象
作用:合并参数一中的可迭代对象,参数二默认值为False,当strict为True时,要求每个可迭代对象的元素个数要一样多,否则发生报错。
6、enumerate(iterable, start=0)
参数:第一个参数是可迭代对象,第二个参数是指定索引起始值,默认从 0 开始计数。可以设置为任意整数。
返回值:返回一个迭代器对象
作用:可迭代对象进行遍历时,同时获取元素的索引(序号)和元素本身。返回一个枚举对象(迭代器),其中每个元素是一个由索引和值组成的元组。
高阶函数应用场景:
六、函数的闭包与装饰器
6.1 闭包
定义:一个前提两个条件,满足就为闭包。在嵌套函数中,内部函数使用了外部函数的参数并且内部函数的返回值为外部函数的函数名,那么就把这个使用了外部函数参数的内部函数称为闭包。
闭包的作用:我们都知道,当一个函数执行结束时,函数内部的变量都将被销毁。如果使用了闭包,那么该函数执行结束将不会被销毁,并且在全局作用域中可以通过闭包间接访问局部变量。
示例:
def outer(x):def inner(y):return x + y # 内部函数使用了外部函数的参数xreturn inner # 返回内部函数f = outer(10) # f是inner函数的闭包,记住了x=10
print(f(5)) # 输出 15
6.2 装饰器
定义和作用:装饰器(Decorator)是一种特殊的函数它接受一个函数作为参数,并返回一个新的函数。它的主要作用是在不修改被装饰函数的源代码和调用方式的前提下,为函数增加额外功能(装饰器的本质是:高阶函数+闭包)
装饰器的基本语法:使用语法糖@后面跟上装饰器的函数名。在函数定义时装饰需要被装饰的函数。
def decorator(func):def wrapper():# 在调用原函数前可以做一些操作print("开始执行函数")func()# 在调用原函数后可以做一些操作print("函数执行完毕")return wrapper@decorator # 语法糖,等同于 foo = decorator(foo)
def foo():print("这是被装饰的函数")foo()
"""
输出:
复制
开始执行函数
这是被装饰的函数
函数执行完毕
"""
应用场景:
日志记录:在函数执行前后打印日志信息
权限校验:在函数执行前检查用户权限
性能测试:计算函数执行时间
缓存:保存函数的计算结果,避免重复计算