首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >2025年Python新手入门:函数完全指南

2025年Python新手入门:函数完全指南

作者头像
安全风信子
发布2025-11-13 12:59:19
发布2025-11-13 12:59:19
2630
举报
文章被收录于专栏:AI SPPECHAI SPPECH

引言

要点

描述

痛点

代码重复率高?程序结构不清晰?想要提高代码复用性?

方案

本教程详细讲解Python函数的定义、调用和高级特性

驱动

掌握函数是编写高质量Python代码的关键,2025年编程必备技能!

在前几篇教程中,我们学习了Python的基础语法、数据类型和控制流语句。今天,我们将学习Python中的函数。函数是一种可重用的代码块,用于执行特定的任务。使用函数可以使我们的代码更加模块化、可重用和易于维护。在大型程序中,函数是组织和结构化代码的重要工具。

目录

章节

内容

1

函数的定义与调用

2

函数参数

3

函数返回值

4

函数的嵌套

5

变量作用域

6

Lambda函数

7

递归函数

8

函数注解

9

生成器函数

10

装饰器(入门)

1. 函数的定义与调用

1.1 函数的定义

在Python中,使用def关键字来定义函数。函数定义的基本语法如下:

代码语言:javascript
复制
def 函数名(参数1, 参数2, ...):
    """文档字符串(可选)"""
    # 函数体
    return 返回值  # 可选

其中:

  • def是定义函数的关键字
  • 函数名是函数的标识符,需要遵循Python的命名规则
  • 参数1, 参数2, ...是函数的参数列表,用于接收外部传入的数据(可选)
  • """文档字符串"""是对函数功能的描述(可选)
  • 函数体是函数执行的代码块
  • return 返回值用于将结果返回给调用者(可选)

下面是一个简单的函数定义示例:

代码语言:javascript
复制
# 定义一个简单的函数,用于打招呼
def greet():
    """打印问候语"""
    print("Hello, Python!")

# 定义一个带有参数的函数
def greet_person(name):
    """向指定的人打招呼
    
    参数:
        name: 字符串,要打招呼的人的名字
    """
    print(f"Hello, {name}!")

# 定义一个带有返回值的函数
def add(a, b):
    """计算两个数的和并返回结果
    
    参数:
        a: 第一个数
        b: 第二个数
        
    返回:
        两个数的和
    """
    return a + b
1.2 函数的调用

定义函数后,我们可以通过函数名加括号的方式来调用它:

代码语言:javascript
复制
# 调用函数

# 调用不带参数和返回值的函数
greet()  # 输出: Hello, Python!

# 调用带参数的函数
greet_person("Alice")  # 输出: Hello, Alice!

greet_person("Bob")  # 输出: Hello, Bob!

# 调用带返回值的函数
result = add(3, 5)
print(result)  # 输出: 8

# 直接使用函数的返回值
print(add(10, 20))  # 输出: 30

在调用函数时,我们需要按照函数定义时的参数列表提供相应的参数。如果函数有返回值,我们可以将其赋值给变量,或者直接在表达式中使用。

1.3 文档字符串

文档字符串(docstring)是函数定义中的可选部分,用于描述函数的功能、参数和返回值等信息。我们可以使用help()函数或直接访问函数的__doc__属性来查看文档字符串。

代码语言:javascript
复制
# 查看函数的文档字符串

# 使用help()函数
help(greet)
# 输出:
# Help on function greet in module __main__:
# 
# greet()
#     打印问候语

# 直接访问__doc__属性
print(greet_person.__doc__)
# 输出:
# 向指定的人打招呼
#     
#     参数:
#         name: 字符串,要打招呼的人的名字

编写良好的文档字符串是一种良好的编程实践,它可以帮助其他开发者(包括未来的你自己)理解函数的功能和用法。

2. 函数参数

Python提供了多种参数类型,使函数的调用更加灵活。

2.1 位置参数

位置参数是最基本的参数类型,调用时需要按照函数定义时的顺序提供参数。

代码语言:javascript
复制
# 位置参数示例
def describe_pet(animal_type, pet_name):
    """描述宠物的信息
    
    参数:
        animal_type: 宠物类型
        pet_name: 宠物名字
    """
    print(f"我有一只{animal_type}。")
    print(f"我的{animal_type}叫{pet_name}。")

# 按照位置顺序传递参数
describe_pet("狗", "小白")
# 输出:
# 我有一只狗。
# 我的狗叫小白。

# 参数顺序很重要
describe_pet("小黑", "猫")  # 这样会导致语义错误
# 输出:
# 我有一只小黑。
# 我的小黑叫猫。
2.2 关键字参数

关键字参数允许我们在调用函数时指定参数名,这样就不必严格按照函数定义时的顺序传递参数。

代码语言:javascript
复制
# 关键字参数示例
def describe_pet(animal_type, pet_name):
    """描述宠物的信息"""
    print(f"我有一只{animal_type}。")
    print(f"我的{animal_type}叫{pet_name}。")

# 使用关键字参数
describe_pet(animal_type="猫", pet_name="小黑")
# 输出:
# 我有一只猫。
# 我的猫叫小黑。

# 可以改变参数顺序
describe_pet(pet_name="小白", animal_type="狗")
# 输出:
# 我有一只狗。
# 我的狗叫小白。
2.3 默认参数

默认参数允许我们为函数参数指定默认值,这样在调用函数时,如果没有提供该参数,就会使用默认值。

代码语言:javascript
复制
# 默认参数示例
def describe_pet(pet_name, animal_type="狗"):
    """描述宠物的信息,默认宠物类型是狗"""
    print(f"我有一只{animal_type}。")
    print(f"我的{animal_type}叫{pet_name}。")

# 不提供默认参数,使用默认值
describe_pet(pet_name="小白")
# 输出:
# 我有一只狗。
# 我的狗叫小白。

# 提供默认参数,覆盖默认值
describe_pet(pet_name="小黑", animal_type="猫")
# 输出:
# 我有一只猫。
# 我的猫叫小黑。

注意:在定义函数时,默认参数必须放在位置参数之后,否则会导致语法错误。

2.4 可变参数(*args)

可变参数允许函数接收任意数量的位置参数。在函数定义中,我们使用星号*来表示可变参数。

代码语言:javascript
复制
# 可变参数示例
def sum_numbers(*args):
    """计算任意数量数字的和
    
    参数:
        *args: 任意数量的数字
        
    返回:
        所有数字的和
    """
    total = 0
    for num in args:
        total += num
    return total

# 传递不同数量的参数
print(sum_numbers(1, 2, 3))  # 输出: 6
print(sum_numbers(1, 2, 3, 4, 5))  # 输出: 15
print(sum_numbers())  # 输出: 0(没有传递参数)

# 传递列表作为可变参数
numbers = [1, 2, 3, 4, 5]
print(sum_numbers(*numbers))  # 在列表前加*,将列表元素作为单独的参数传递 输出: 15

在函数内部,*args会被当作一个元组来处理,我们可以像遍历元组一样遍历它。

2.5 关键字可变参数(**kwargs)

关键字可变参数允许函数接收任意数量的关键字参数。在函数定义中,我们使用两个星号**来表示关键字可变参数。

代码语言:javascript
复制
# 关键字可变参数示例
def print_info(**kwargs):
    """打印任意数量的关键字参数
    
    参数:
        **kwargs: 任意数量的关键字参数
    """
    for key, value in kwargs.items():
        print(f"{key}: {value}")

# 传递不同数量的关键字参数
print_info(name="Alice", age=25, city="New York")
# 输出:
# name: Alice
# age: 25
# city: New York

print_info(product="手机", price=999.99, brand="Apple")
# 输出:
# product: 手机
# price: 999.99
# brand: Apple

# 传递字典作为关键字可变参数
person = {"name": "Bob", "age": 30, "city": "Boston"}
print_info(**person)  # 在字典前加**,将字典的键值对作为关键字参数传递
# 输出:
# name: Bob
# age: 30
# city: Boston

在函数内部,**kwargs会被当作一个字典来处理,我们可以像遍历字典一样遍历它。

2.6 参数组合使用

在实际编程中,我们经常需要组合使用不同类型的参数。参数的顺序应该是:位置参数、可变参数、默认参数、关键字可变参数。

代码语言:javascript
复制
# 参数组合使用示例
def mixed_params(a, b, *args, c=10, **kwargs):
    """混合使用不同类型的参数
    
    参数:
        a, b: 位置参数
        *args: 可变参数
        c: 默认参数
        **kwargs: 关键字可变参数
    """
    print(f"a = {a}")
    print(f"b = {b}")
    print(f"args = {args}")
    print(f"c = {c}")
    print(f"kwargs = {kwargs}")

# 调用函数
mixed_params(1, 2, 3, 4, 5, c=20, x=100, y=200)
# 输出:
# a = 1
# b = 2
# args = (3, 4, 5)
# c = 20
# kwargs = {'x': 100, 'y': 200}

3. 函数返回值

函数可以通过return语句返回一个或多个值给调用者。

3.1 返回单个值
代码语言:javascript
复制
# 返回单个值示例
def square(x):
    """计算一个数的平方
    
    参数:
        x: 一个数字
        
    返回:
        x的平方
    """
    return x * x

result = square(5)
print(result)  # 输出: 25
3.2 返回多个值

Python允许函数返回多个值,这些值会被自动打包成一个元组返回。

代码语言:javascript
复制
# 返回多个值示例
def get_person_info():
    """返回一个人的信息
    
    返回:
        包含姓名、年龄和城市的元组
    """
    name = "Alice"
    age = 25
    city = "New York"
    return name, age, city  # 多个返回值会被打包成元组

# 接收多个返回值
person_name, person_age, person_city = get_person_info()  # 解包元组
print(f"姓名: {person_name}")  # 输出: 姓名: Alice
print(f"年龄: {person_age}")  # 输出: 年龄: 25
print(f"城市: {person_city}")  # 输出: 城市: New York

# 也可以用一个变量接收所有返回值
person_info = get_person_info()
print(person_info)  # 输出: ('Alice', 25, 'New York')
3.3 提前返回

函数可以在任何位置使用return语句返回结果,一旦执行到return语句,函数就会立即结束,不再执行后面的代码。

代码语言:javascript
复制
# 提前返回示例
def is_positive(number):
    """判断一个数是否为正数
    
    参数:
        number: 一个数字
        
    返回:
        如果number是正数,返回True;否则返回False
    """
    if number > 0:
        return True
    return False  # 如果number <= 0,执行到这里

print(is_positive(5))  # 输出: True
print(is_positive(-3))  # 输出: False
print(is_positive(0))  # 输出: False

# 另一个提前返回的例子
def find_first_negative(numbers):
    """找到列表中的第一个负数
    
    参数:
        numbers: 数字列表
        
    返回:
        第一个负数,如果没有找到,返回None
    """
    for num in numbers:
        if num < 0:
            return num  # 找到第一个负数就返回
    return None  # 如果没有找到负数,执行到这里

numbers = [1, 2, -3, 4, -5]
first_negative = find_first_negative(numbers)
print(f"第一个负数是: {first_negative}")  # 输出: 第一个负数是: -3
3.4 没有return语句的函数

如果函数没有return语句,或者return语句后面没有值,那么函数会返回NoneNone是Python中的一个特殊值,表示"无"或"空"。

代码语言:javascript
复制
# 没有return语句的函数示例
def say_hello():
    """打印问候语,没有返回值"""
    print("Hello!")

result = say_hello()
print(result)  # 输出: None

# return语句后面没有值
def do_nothing():
    """什么都不做,返回None"""
    return

result = do_nothing()
print(result)  # 输出: None

4. 函数的嵌套

在Python中,我们可以在一个函数内部定义另一个函数,这称为函数的嵌套。嵌套函数可以访问外部函数的变量,但外部函数不能访问嵌套函数的变量。

代码语言:javascript
复制
# 函数嵌套示例
def outer_function(x):
    """外部函数
    
    参数:
        x: 一个数字
    """
    def inner_function(y):
        """内部函数
        
        参数:
            y: 一个数字
            
        返回:
            y的平方加上外部函数的x
    """
        return y * y + x  # 内部函数可以访问外部函数的变量
    
    result = inner_function(5)
    print(f"内部函数的结果: {result}")
    
    # 外部函数不能访问内部函数的变量
    # print(y)  # 这行代码会引发错误
    
    return result

# 调用外部函数
outer_result = outer_function(10)
print(f"外部函数的返回值: {outer_result}")
# 输出:
# 内部函数的结果: 35
# 外部函数的返回值: 35

# 不能直接调用内部函数
# inner_function(5)  # 这行代码会引发错误

函数嵌套的一个常见用途是创建闭包,我们将在后面的章节中介绍。

5. 变量作用域

变量作用域是指变量在程序中可以被访问的范围。Python中有四种作用域:局部作用域、嵌套作用域、全局作用域和内置作用域。

5.1 局部作用域

在函数内部定义的变量具有局部作用域,只能在函数内部访问。

代码语言:javascript
复制
# 局部作用域示例
def my_function():
    """演示局部变量"""
    local_var = "我是局部变量"
    print(local_var)  # 在函数内部可以访问局部变量

my_function()  # 输出: 我是局部变量

# 不能在函数外部访问局部变量
# print(local_var)  # 这行代码会引发错误
5.2 嵌套作用域

在嵌套函数中,内部函数可以访问外部函数的变量,这些变量具有嵌套作用域。

代码语言:javascript
复制
# 嵌套作用域示例
def outer_function():
    """外部函数"""
    outer_var = "我是外部变量"
    
    def inner_function():
        """内部函数"""
        # 内部函数可以访问外部函数的变量
        print(outer_var)
        
        # 但不能修改外部函数的变量(除非使用nonlocal关键字)
        # outer_var = "修改外部变量"  # 这行代码会创建一个新的局部变量,而不是修改外部变量
    
    inner_function()
    print(outer_var)  # 输出原始的外部变量值

outer_function()
# 输出:
# 我是外部变量
# 我是外部变量
5.3 全局作用域

在模块级别定义的变量具有全局作用域,可以在整个模块中访问。

代码语言:javascript
复制
# 全局作用域示例
global_var = "我是全局变量"  # 在模块级别定义的全局变量

def my_function():
    """演示全局变量"""
    # 在函数内部可以访问全局变量
    print(global_var)
    
    # 但不能直接修改全局变量(除非使用global关键字)
    # global_var = "修改全局变量"  # 这行代码会创建一个新的局部变量,而不是修改全局变量

my_function()  # 输出: 我是全局变量
print(global_var)  # 输出: 我是全局变量
5.4 使用global和nonlocal关键字

如果我们需要在函数内部修改全局变量,或者在内部函数中修改外部函数的变量,我们可以使用globalnonlocal关键字。

代码语言:javascript
复制
# 使用global关键字修改全局变量
counter = 0  # 全局变量

def increment_counter():
    """使用global关键字修改全局变量"""
    global counter  # 声明counter是全局变量
    counter += 1
    print(f"计数器的值: {counter}")

increment_counter()  # 输出: 计数器的值: 1
increment_counter()  # 输出: 计数器的值: 2
print(f"全局计数器的值: {counter}")  # 输出: 全局计数器的值: 2

# 使用nonlocal关键字修改外部函数的变量
def outer_function():
    """外部函数"""
    outer_var = "我是外部变量"
    
    def inner_function():
        """内部函数"""
        nonlocal outer_var  # 声明outer_var是外部函数的变量
        outer_var = "修改后的外部变量"
        print(f"内部函数中的outer_var: {outer_var}")
    
    inner_function()
    print(f"外部函数中的outer_var: {outer_var}")

outer_function()
# 输出:
# 内部函数中的outer_var: 修改后的外部变量
# 外部函数中的outer_var: 修改后的外部变量

6. Lambda函数

Lambda函数(也称为匿名函数)是一种小型的、匿名的函数,它可以在一行代码中定义。Lambda函数使用lambda关键字定义,语法如下:

代码语言:javascript
复制
lambda 参数1, 参数2, ...: 表达式

Lambda函数可以接受任意数量的参数,但只能有一个表达式。表达式的结果就是函数的返回值。

6.1 基本用法
代码语言:javascript
复制
# Lambda函数基本用法

# 定义一个简单的lambda函数,计算两个数的和
sum_lambda = lambda x, y: x + y
print(sum_lambda(3, 5))  # 输出: 8

# 定义一个lambda函数,计算一个数的平方
square_lambda = lambda x: x * x
print(square_lambda(4))  # 输出: 16

# 定义一个lambda函数,检查一个数是否为偶数
is_even_lambda = lambda x: x % 2 == 0
print(is_even_lambda(6))  # 输出: True
print(is_even_lambda(7))  # 输出: False
6.2 与内置函数一起使用

Lambda函数通常与map()filter()sorted()等内置函数一起使用,使代码更加简洁。

代码语言:javascript
复制
# Lambda函数与内置函数一起使用

# 与map()函数一起使用,将列表中的每个元素平方
numbers = [1, 2, 3, 4, 5]
squared_numbers = list(map(lambda x: x * x, numbers))
print(squared_numbers)  # 输出: [1, 4, 9, 16, 25]

# 与filter()函数一起使用,过滤出列表中的偶数
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
even_numbers = list(filter(lambda x: x % 2 == 0, numbers))
print(even_numbers)  # 输出: [2, 4, 6, 8, 10]

# 与sorted()函数一起使用,根据指定的键进行排序
students = [
    {"name": "Alice", "score": 90},
    {"name": "Bob", "score": 85},
    {"name": "Charlie", "score": 95},
    {"name": "David", "score": 80}
]

# 按分数降序排序
sorted_students = sorted(students, key=lambda student: student["score"], reverse=True)
for student in sorted_students:
    print(f"{student['name']}: {student['score']}")
# 输出:
# Charlie: 95
# Alice: 90
# Bob: 85
# David: 80

# 与reduce()函数一起使用,计算列表中所有元素的和
from functools import reduce
numbers = [1, 2, 3, 4, 5]
sum_result = reduce(lambda x, y: x + y, numbers)
print(sum_result)  # 输出: 15
6.3 作为函数参数传递

Lambda函数可以作为参数传递给其他函数,使代码更加灵活。

代码语言:javascript
复制
# Lambda函数作为函数参数传递
def apply_operation(x, y, operation):
    """对两个数应用指定的操作
    
    参数:
        x: 第一个数
        y: 第二个数
        operation: 要应用的操作(函数)
        
    返回:
        操作的结果
    """
    return operation(x, y)

# 使用lambda函数作为参数
addition = apply_operation(5, 3, lambda x, y: x + y)
subtraction = apply_operation(5, 3, lambda x, y: x - y)
multiplication = apply_operation(5, 3, lambda x, y: x * y)
division = apply_operation(5, 3, lambda x, y: x / y)

print(f"加法结果: {addition}")  # 输出: 加法结果: 8
print(f"减法结果: {subtraction}")  # 输出: 减法结果: 2
print(f"乘法结果: {multiplication}")  # 输出: 乘法结果: 15
print(f"除法结果: {division}")  # 输出: 除法结果: 1.6666666666666667

7. 递归函数

递归函数是指在函数内部调用自身的函数。递归是一种强大的编程技巧,可以用来解决许多复杂的问题。

7.1 基本用法
代码语言:javascript
复制
# 递归函数基本用法

def factorial(n):
    """计算n的阶乘(递归实现)
    
    参数:
        n: 非负整数
        
    返回:
        n的阶乘
    """
    # 基本情况(递归终止条件)
    if n == 0 or n == 1:
        return 1
    # 递归调用
    return n * factorial(n - 1)

# 测试函数
print(factorial(0))  # 输出: 1
print(factorial(1))  # 输出: 1
print(factorial(5))  # 输出: 120
print(factorial(10))  # 输出: 3628800

在上面的示例中,factorial()函数计算一个数的阶乘。当n为0或1时,函数返回1(基本情况);否则,函数返回n * factorial(n - 1)(递归调用)。

7.2 递归的基本要素

递归函数必须包含以下两个要素:

  1. 基本情况(Base Case):当满足某个条件时,函数不再调用自身,而是直接返回一个值。这是防止无限递归的关键。
  2. 递归调用(Recursive Call):函数调用自身,但传入的参数应该更接近基本情况。
代码语言:javascript
复制
# 递归的两个要素示例
def fibonacci(n):
    """计算斐波那契数列的第n项(递归实现)
    
    参数:
        n: 正整数
        
    返回:
        斐波那契数列的第n项
    """
    # 基本情况
    if n == 1 or n == 2:
        return 1
    # 递归调用
    return fibonacci(n - 1) + fibonacci(n - 2)

# 测试函数
print(fibonacci(1))  # 输出: 1
print(fibonacci(2))  # 输出: 1
print(fibonacci(3))  # 输出: 2
print(fibonacci(4))  # 输出: 3
print(fibonacci(5))  # 输出: 5
print(fibonacci(10))  # 输出: 55
7.3 递归的优缺点

优点

  • 递归可以使代码更加简洁和优雅,特别是对于某些问题(如树结构遍历、分治算法等)
  • 递归可以更好地表达问题的本质

缺点

  • 递归可能导致栈溢出,如果递归深度过大
  • 递归可能导致重复计算,降低效率
7.4 尾递归优化

在一些编程语言中,编译器会对尾递归进行优化,避免栈溢出。尾递归是指递归调用是函数的最后一个操作。不过,需要注意的是,Python的解释器并不会对尾递归进行优化。

代码语言:javascript
复制
# 尾递归示例
def factorial_tail(n, accumulator=1):
    """计算n的阶乘(尾递归实现)
    
    参数:
        n: 非负整数
        accumulator: 累加器,用于存储中间结果
        
    返回:
        n的阶乘
    """
    if n == 0:
        return accumulator
    return factorial_tail(n - 1, n * accumulator)

# 测试函数
print(factorial_tail(0))  # 输出: 1
print(factorial_tail(1))  # 输出: 1
print(factorial_tail(5))  # 输出: 120

虽然这个函数使用了尾递归的形式,但由于Python解释器不会对尾递归进行优化,所以对于大的n值,仍然可能会导致栈溢出。

8. 函数注解

函数注解是Python 3引入的一个特性,允许我们为函数的参数和返回值添加类型提示。函数注解不会影响函数的执行,但可以提高代码的可读性和可维护性。

8.1 基本用法
代码语言:javascript
复制
# 函数注解基本用法
def greet(name: str) -> str:
    """向指定的人打招呼
    
    参数:
        name: 字符串,要打招呼的人的名字
        
    返回:
        包含问候语的字符串
    """
    return f"Hello, {name}!"

# 调用函数
message = greet("Alice")
print(message)  # 输出: Hello, Alice!

在上面的示例中,name: str表示name参数的类型应该是字符串,-> str表示函数的返回值类型应该是字符串。

8.2 复杂注解

我们还可以为函数的参数添加默认值,并为复杂类型添加注解。

代码语言:javascript
复制
# 复杂函数注解示例
from typing import List, Dict, Tuple, Optional

def process_data(data: List[int], threshold: int = 10) -> Dict[str, List[int]]:
    """处理数据列表
    
    参数:
        data: 整数列表
        threshold: 阈值,默认值为10
        
    返回:
        包含处理结果的字典
    """
    result = {
        "below_threshold": [],
        "above_or_equal_threshold": []
    }
    
    for num in data:
        if num < threshold:
            result["below_threshold"].append(num)
        else:
            result["above_or_equal_threshold"].append(num)
    
    return result

# 测试函数
data = [5, 10, 15, 20, 2, 8, 12]
processed_data = process_data(data)
print(processed_data)
# 输出:
# {
#     'below_threshold': [5, 2, 8], 
#     'above_or_equal_threshold': [10, 15, 20, 12]
# }

# 带有可选参数的函数注解
def find_item(items: List[str], target: str) -> Optional[int]:
    """在列表中查找指定的元素
    
    参数:
        items: 字符串列表
        target: 要查找的目标字符串
        
    返回:
        目标元素的索引,如果未找到则返回None
    """
    if target in items:
        return items.index(target)
    return None

# 测试函数
fruits = ["apple", "banana", "orange", "grape"]
index = find_item(fruits, "orange")
print(f"orange的索引: {index}")  # 输出: orange的索引: 2

index = find_item(fruits, "watermelon")
print(f"watermelon的索引: {index}")  # 输出: watermelon的索引: None

在上面的示例中,我们使用了typing模块中的类型,如ListDictTupleOptional,来为复杂类型添加注解。

9. 生成器函数

生成器函数是一种特殊的函数,它使用yield语句而不是return语句来返回值。生成器函数返回一个生成器对象,我们可以使用next()函数或for循环来迭代生成器对象,获取生成器函数产生的值。

9.1 基本用法
代码语言:javascript
复制
# 生成器函数基本用法
def count_up_to(n):
    """生成从1到n的数字
    
    参数:
        n: 上限
        
    生成:
        从1到n的整数
    """
    i = 1
    while i <= n:
        yield i  # 使用yield语句产生值
        i += 1

# 创建生成器对象
counter = count_up_to(5)

# 使用next()函数获取生成器产生的值
print(next(counter))  # 输出: 1
print(next(counter))  # 输出: 2
print(next(counter))  # 输出: 3
print(next(counter))  # 输出: 4
print(next(counter))  # 输出: 5
# print(next(counter))  # 这行代码会引发StopIteration异常

# 使用for循环迭代生成器对象
for num in count_up_to(5):
    print(num, end=" ")
# 输出: 1 2 3 4 5
9.2 生成器函数的特点

生成器函数有以下几个特点:

  1. 生成器函数使用yield语句返回值,而不是return语句
  2. 生成器函数返回一个生成器对象,而不是直接返回值
  3. 生成器函数在每次调用next()函数时,会从上次暂停的地方继续执行,直到遇到下一个yield语句或函数结束
  4. 生成器函数可以节省内存,因为它不会一次性生成所有的值,而是在需要时才生成
代码语言:javascript
复制
# 生成器函数的特点示例
def fibonacci_generator(n):
    """生成斐波那契数列的前n项
    
    参数:
        n: 项数
        
    生成:
        斐波那契数列的前n项
    """
    a, b = 0, 1
    count = 0
    while count < n:
        yield b
        a, b = b, a + b
        count += 1

# 使用生成器函数生成斐波那契数列
print("斐波那契数列的前10项:")
for num in fibonacci_generator(10):
    print(num, end=" ")
# 输出: 1 1 2 3 5 8 13 21 34 55

# 生成器表达式(类似于列表推导式,但使用圆括号)
squares = (x * x for x in range(10))
print("0到9的平方:")
for square in squares:
    print(square, end=" ")
# 输出: 0 1 4 9 16 25 36 49 64 81

10. 装饰器(入门)

装饰器是一种特殊的函数,它可以修改其他函数的行为。装饰器可以在不修改原函数代码的情况下,为函数添加额外的功能。

10.1 基本用法
代码语言:javascript
复制
# 装饰器基本用法
def my_decorator(func):
    """一个简单的装饰器
    
    参数:
        func: 要装饰的函数
        
    返回:
        装饰后的函数
    """
    def wrapper():
        """装饰器的包装函数"""
        print("在函数调用之前执行的代码")
        func()  # 调用原函数
        print("在函数调用之后执行的代码")
    return wrapper

# 使用装饰器
@my_decorator  # 这等同于 greet = my_decorator(greet)
def greet():
    """打印问候语"""
    print("Hello, Python!")

# 调用装饰后的函数
greet()
# 输出:
# 在函数调用之前执行的代码
# Hello, Python!
# 在函数调用之后执行的代码

在上面的示例中,my_decorator是一个装饰器函数,它接受一个函数作为参数,并返回一个包装函数wrapperwrapper函数在调用原函数之前和之后执行一些额外的代码。通过使用@my_decorator语法,我们将greet函数传递给my_decorator函数,并将返回的包装函数赋值给greet

10.2 带参数的装饰器

我们还可以定义带参数的装饰器,使装饰器更加灵活。

代码语言:javascript
复制
# 带参数的装饰器
import time

def timing_decorator(func):
    """计算函数执行时间的装饰器
    
    参数:
        func: 要装饰的函数
        
    返回:
        装饰后的函数
    """
    def wrapper(*args, **kwargs):
        """装饰器的包装函数"""
        start_time = time.time()  # 记录开始时间
        result = func(*args, **kwargs)  # 调用原函数
        end_time = time.time()  # 记录结束时间
        print(f"函数{func.__name__}执行时间: {end_time - start_time:.6f}秒")
        return result
    return wrapper

# 使用装饰器
@timing_decorator
def calculate_sum(n):
    """计算从1到n的和"""
    total = 0
    for i in range(1, n + 1):
        total += i
    return total

# 调用装饰后的函数
result = calculate_sum(1000000)
print(f"计算结果: {result}")
# 输出类似:
# 函数calculate_sum执行时间: 0.046875秒
# 计算结果: 500000500000

在上面的示例中,timing_decorator装饰器可以计算被装饰函数的执行时间。装饰器的包装函数接受任意数量的位置参数和关键字参数,并将它们传递给原函数。

实践练习

  1. 练习1:函数基础练习
    • 编写一个函数,计算一个数的绝对值
    • 编写一个函数,判断一个字符串是否是回文(正读和反读都一样)
    • 编写一个函数,将华氏温度转换为摄氏温度
  2. 练习2:函数参数练习
    • 编写一个函数,接受任意数量的数字参数,返回它们的平均值
    • 编写一个函数,接受一个人的信息(姓名、年龄、城市等),并以格式化的方式打印出来
    • 编写一个函数,接受一个列表和一个可选的排序关键字,返回排序后的列表
  3. 练习3:高级函数练习
    • 编写一个递归函数,计算斐波那契数列的第n项
    • 编写一个生成器函数,生成无限序列(如自然数序列)
    • 使用lambda函数和内置函数(如map、filter、sorted)解决一些简单问题

结论

要点

描述

价值

掌握Python函数的定义、调用和高级特性,编写更加模块化、可重用和易于维护的代码

行动

学习Python的模块和包,将函数组织成更大的代码单元

恭喜你完成了Python函数的学习!通过本教程,你已经了解了Python函数的定义和调用、函数参数(位置参数、关键字参数、默认参数、可变参数、关键字可变参数)、函数返回值、函数嵌套、变量作用域、Lambda函数、递归函数、函数注解、生成器函数和装饰器等内容。

函数是Python编程的重要组成部分,掌握好函数可以使你的代码更加模块化、可重用和易于维护。在下一篇教程中,我们将学习Python的模块和包,这将帮助你将函数组织成更大的代码单元,进一步提高代码的组织性和可重用性。

记住,编程是一门需要实践的技能,所以请务必多写代码、多做练习,巩固所学的知识!

参考

来源

描述

Python官方文档

提供权威的Python函数说明

菜鸟教程

适合初学者的Python函数教程

W3School

提供Python函数的详细讲解和实例

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-11-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 引言
  • 目录
  • 1. 函数的定义与调用
    • 1.1 函数的定义
    • 1.2 函数的调用
    • 1.3 文档字符串
  • 2. 函数参数
    • 2.1 位置参数
    • 2.2 关键字参数
    • 2.3 默认参数
    • 2.4 可变参数(*args)
    • 2.5 关键字可变参数(**kwargs)
    • 2.6 参数组合使用
  • 3. 函数返回值
    • 3.1 返回单个值
    • 3.2 返回多个值
    • 3.3 提前返回
    • 3.4 没有return语句的函数
  • 4. 函数的嵌套
  • 5. 变量作用域
    • 5.1 局部作用域
    • 5.2 嵌套作用域
    • 5.3 全局作用域
    • 5.4 使用global和nonlocal关键字
  • 6. Lambda函数
    • 6.1 基本用法
    • 6.2 与内置函数一起使用
    • 6.3 作为函数参数传递
  • 7. 递归函数
    • 7.1 基本用法
    • 7.2 递归的基本要素
    • 7.3 递归的优缺点
    • 7.4 尾递归优化
  • 8. 函数注解
    • 8.1 基本用法
    • 8.2 复杂注解
  • 9. 生成器函数
    • 9.1 基本用法
    • 9.2 生成器函数的特点
  • 10. 装饰器(入门)
    • 10.1 基本用法
    • 10.2 带参数的装饰器
  • 实践练习
  • 结论
  • 参考
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档