注意此篇文章适合基础不好的同学来看,如果是大佬只能作为知识总结,可以去学习更难的内容。祝你学习愉快!
在编程中,函数是一段代码的封装,具有特定的功能,可以被重复调用这段代码。函数使代码更加模块化、易于维护和重用。在Python中,函数是通过 def
关键字定义的。
1. 函数的定义
-
函数定义使用
def
关键字,后跟函数名、参数列表(可选)和冒号:
。函数体包含在缩进块中,表示函数的具体实现。 -
基本语法:
def function_name(parameters): # 函数体 return value # 可选,返回值
-
例子:
def greet(name): print(f"Hello, {name}!")
在这个例子中,
greet
是函数名,name
是参数。函数体中有一个print()
函数,用于输出问候信息。
2. 函数的调用
- 函数定义(必须先定义再使用)后,可以通过函数名和传入参数来调用它。
- 例子:
这会输出 “Hello, Alice!”。greet("Alice") # 此处没有考虑返回值
3. 参数和返回值
- 参数:函数可以接受多个参数,这些参数在函数调用时传入。
- 返回值:函数可以返回一个值给调用者,使用
return
关键字。如果没有return
,函数默认返回None
。Python中的参数和返回值和有些语言不一样,会自动推断它们类型,不需要显式去写。 - 例子:
def add(a, b): return a + b result = add(3, 4) print(result) # 输出: 7
3.1 形参和实参
形参(形式参数)
- 定义:形参是在函数定义时使用的参数。它们是占位符,用于接收函数调用时传递给函数的数据。
实参(实际参数)
- 定义:实参是在函数调用时传递给函数的实际值。它们是传递给函数的具体数据。
形参和实参的关系
- 在函数调用时,实参的值会赋给对应的形参,实参的个数和形参要匹配。形参在函数内部使用,而实参是在函数外部传递的实际数据。
- 例子:
def add(a, b): # 形参 a 和 b return a + b result = add(3, 4) # 实参 3 和 4 print(result) # 输出: 7
在这个例子中,a
和 b
是形参,它们在函数 add
的定义中。调用 add(3, 4)
时,实参 3
被传递给 a
,实参 4
被传递给 b
,然后函数返回它们的和。
3.2 默认参数值
- 在定义函数时,可以为参数指定默认值。如果调用时没有提供该参数,函数会使用默认值。有点类似C++中的缺省参数。
- 例子:
def greet(name="stranger"): print(f"Hello, {name}!") greet() # 输出: "Hello, stranger!" greet("Bob") # 输出: "Hello, Bob!"
3.3. 关键字参数
- 函数调用时,可以使用
参数名=值
的形式指定参数,称为关键字参数。这样可以使参数的顺序不那么重要。 - 例子:
def describe_person(name, age): print(f"{name} is {age} years old.") describe_person(age=30, name="Alice") # 输出: "Alice is 30 years old."
3.4. 可变参数
*args
:函数可以接受任意数量的位置参数,使用*args
。args
是一个元组,包含所有传递的位置参数。**kwargs
:函数可以接受任意数量的关键字参数,使用**kwargs
。kwargs
是一个字典,包含所有传递的关键字参数。- 例子:
def sum_all(*args): total = 0 for num in args: total += num return total print(sum_all(1, 2, 3, 4)) # 输出: 10 def print_info(**kwargs): for key, value in kwargs.items(): print(f"{key}: {value}") print_info(name="Alice", age=30, city="New York") # 输出: # name: Alice # age: 30 # city: New York
4. 函数的作用域
- 局部变量:在函数内部定义的变量是局部变量,只能在函数内部访问。
- 全局变量:在函数外部定义的变量是全局变量,可以在函数内部访问和修改。
- 例子:
x = 10 # 全局变量 def change_x(): global x x = 20 # 修改全局变量 change_x() print(x) # 输出: 20
它们之间的命名可以重复,如果冲突了以局部的为优先,但是一般不建议这么做。
5. 匿名函数(Lambda 函数)
- 定义:Python 支持一种简短的函数定义方式,称为
lambda
函数。lambda
函数用于创建小型、单行匿名函数。 - 语法:
lambda arguments: expression
- 例子:
add = lambda x, y: x + y print(add(3, 4)) # 输出: 7
lambda
函数通常在需要简单函数而不想命名时使用,如在排序、过滤等操作中。
6. 函数的嵌套与闭包
- 嵌套函数:可以在一个函数内部定义另一个函数。
- 闭包:如果一个内部函数引用了外部函数的变量,并且外部函数的作用域已经结束,那么这个内部函数就被称为闭包。
- 例子:
def outer_function(msg): def inner_function(): print(msg) return inner_function greet = outer_function("Hello") greet() # 输出: "Hello"
7. 链式调用
- 例子:
# 判定是否是奇数
def isOdd(num):
if num % 2 == 0:
return False
else:
return True
result = isOdd(10)
print(result)
链式写法:
print(isOdd(10))
把一个函数的返回值, 作为另一个函数的参数, 这种操作称为 链式调用
8. 函数递归(难点)
递归是一种在编程中常用的技术,它指的是函数调用自身来解决问题。递归通常用于将一个复杂问题分解成较小的相似问题,从而通过解决这些较小问题来解决原问题。这部分可以先跳过,等有了一定的代码经验后再回来看。
8.1 递归的基本概念
- 定义:递归函数是一个会在其定义内部调用自身的函数。
- 结构:递归一般有两个部分:
- 基准情形(Base Case):用于终止递归的条件,当满足这个条件时,递归停止。
- 递归情形(Recursive Case):函数继续调用自身来解决问题的更小部分。
- 例子:计算阶乘
def factorial(n): if n == 1: # 基准情形 return 1 else: return n * factorial(n - 1) # 递归情形 print(factorial(5)) # 输出: 120
在这个例子中,factorial()
函数计算数字 n
的阶乘。如果 n
是 1,则返回 1(基准情形);否则,函数调用自身计算 n-1
的阶乘,并将结果乘以 n
。
8.2 递归的优点
- 简洁性:递归通常能使代码更加简洁和易于理解,特别是当问题本身具有递归性质时(例如树结构遍历、数学归纳等)。
- 自然表达:递归能够自然地表达某些问题的结构,使代码与问题的数学描述更一致。
- 解决复杂问题:递归能够轻松解决某些分治问题或与树、图等结构相关的问题。
8.3 递归的缺点
- 性能问题:递归的每次调用都会在内存中保留当前函数的状态,这可能会导致较高的内存消耗,特别是在递归深度较大的情况下容易导致栈溢出。
- 效率低:有些递归算法可能会重复计算相同的子问题,导致时间复杂度急剧上升,例如未经优化的斐波那契数列计算。
- 理解难度:对于不熟悉递归的人来说,递归的逻辑可能较难理解,特别是当递归深度较深或涉及复杂的条件判断时。
例子:未优化的斐波那契递归函数的效率问题
# 计算斐波那契数列的第40项
print(fibonacci(40)) # 运行时间可能非常长
由于递归未优化,fibonacci(40)
需要大量重复计算,效率极低。
8.4 递归的优化
- 记忆化:通过缓存已计算的结果来避免重复计算,这种技术被称为记忆化或动态规划。
- 转换为迭代:对于某些递归问题,可以将递归转换为迭代来避免栈溢出问题。
例子:使用记忆化优化斐波那契数列(这部分需要等学习了动态规划部分更好理解)
def fibonacci_memo(n, memo={}):
if n in memo:
return memo[n]
if n <= 1:
return n
memo[n] = fibonacci_memo(n-1, memo) + fibonacci_memo(n-2, memo)
return memo[n]
print(fibonacci_memo(40)) # 运行速度显著提升
8.5 总结
- 递归是一个强大的工具,特别适用于分治问题、树结构操作和自然递归问题。
- 它具有简洁性和自然表达的优点,但也存在性能和内存消耗的问题。
- 通过优化技术,如记忆化或将递归转化为迭代,能够有效改善递归的缺点。
函数是Python编程的核心之一,通过理解和使用函数,你可以编写出模块化、可重用和高效的代码。如果对你有帮助不妨点个赞支持一下~