Skip to content

🛠 函数

Python 中的函数是组织好的、可重复使用的代码块,用来执行某个特定的任务。使用函数可以提高代码的复用性,减少重复的代码,并增强程序的可读性和可维护性。

函数在编程中的主要优点包括:

  1. 代码组织和模块化:把复杂任务拆分成小的、独立的函数,提升代码的结构性。
  2. 复用性:通过函数的复用,避免代码重复,提高效率。
  3. 可读性:函数有助于让代码更具可读性,帮助开发者理解程序的功能。
  4. 可维护性:修改和扩展程序时,只需修改函数内部的实现,不会影响到其他部分。
  5. 易于测试:函数可以独立地进行单元测试,确保功能的正确性。
  6. 灵活性和扩展性:通过参数化,函数可以处理不同的输入,增强灵活性。

通过合理使用函数,可以让程序更简洁、清晰、可复用,从而提升开发效率和代码质量。

一、定义函数

在 Python 中,函数是通过 def 关键字来定义的:

python
def function_name(parameters):
    statement      # 语句
    return result  # 语句:返回结果
  • function_name 是函数的名字。
  • parameters 是函数的参数,可以有多个,参数是可选的。
  • statement是函数内部的代码部分,它包含了函数执行时要完成的具体操作或任务。函数体由一系列语句组成,负责实现函数的功能。
  • return 语句是可选的,用于返回函数的结果。如果没有 return,函数默认返回 None。 示例:
python
def greet(name):
    s = f"Hello, {name}!"
    return s

这个函数 greet 接收一个参数 name,返回一个格式化的字符串。

二、调用函数

函数定义完成后,可以通过函数名来调用它,给它传递所需的参数。

python
message = greet("Alice")
print(message)

输出:

Hello, Alice!

三、参数

在 Python 中,函数的参数可以有多种不同的形式,包括位置参数关键字参数可变参数等。理解这些参数的不同类型和它们的顺序对于编写清晰、灵活的函数非常重要。

1. 位置参数(Positional Arguments)

位置参数是最常见的参数类型,它们是通过传入的值按照定义时的顺序传递给函数的。 示例:

python
def greet(name, age):
    print(f"Hello {name}, you are {age} years old.")
greet("Alice", 30)  # 输出 Hello Alice, you are 30 years old.

在这个例子中,nameage 是位置参数。传入的 "Alice"30 会按照顺序赋给 nameage

2. 关键字参数(Keyword Arguments)

关键字参数是通过指定参数名来传递值,而不依赖于参数的位置。它们通常在调用函数时明确指定每个参数的名字。

python
def greet(name, age):
    print(f"Hello {name}, you are {age} years old.")

greet(age=30, name="Alice")  # 输出 Hello Alice, you are 30 years old.

在这个例子中,age=30name="Alice" 是关键字参数。它们不受顺序的限制,虽然函数定义是 name, age,但可以通过指定名字来传递参数。

3. 默认参数(Default Arguments)

你可以为函数的参数指定默认值。如果调用函数时没有提供某个参数的值,Python 会使用该参数的默认值。

python
def greet(name, age=25):
    print(f"Hello {name}, you are {age} years old.")

greet("Alice")  # 输出 Hello Alice, you are 25 years old.
greet("Bob", 30)  # 输出 Hello Bob, you are 30 years old.

在这个例子中,age 有一个默认值 25。如果没有传入 age,Python 会使用默认值。

4. 可变参数(Variable-Length Arguments)

*args(位置参数-元组)

*args 用于接受任意数量的位置参数。它将所有传入的位置参数收集到一个元组中。

python
def greet(*args):
    for arg in args:
        print(f"Hello {arg}")

greet("Alice", "Bob", "Charlie")  
# 输出:
# Hello Alice
# Hello Bob
# Hello Charlie

在这个例子中,*args 收集了所有传入的参数,并将它们作为元组来处理。

**kwargs(关键字参数-字典)

**kwargs 用于接受任意数量的关键字参数。它将所有传入的关键字参数收集到一个字典中。

python
def greet(**kwargs):
    for name, age in kwargs.items():
        print(f"Hello {name}, you are {age} years old.")

greet(Alice=30, Bob=25, Charlie=35)  
# 输出:
# Hello Alice, you are 30 years old.
# Hello Bob, you are 25 years old.
# Hello Charlie, you are 35 years old.

在这个例子中,**kwargs 收集了所有传入的关键字参数,并将它们作为字典来处理。

*args:就像你传给函数一个元组,其中包含了所有的位置参数,按顺序排列。

**kwargs:就像你传给函数一个字典,字典的是参数名,是参数值。

5. 参数顺序

在函数定义时,参数的顺序非常重要。以下是参数的顺序规则:

  1. 位置参数:这些参数必须先于关键字参数和可变参数。
  2. 默认参数:默认参数必须放在位置参数之后。
  3. *args*args 位于其他所有位置参数之后,否则后面的参数只能通过关键字传参。
  4. **kwargs**kwargs 必须位于 *args 后面,并且它通常是最后一个参数。
python
def func(a, b, c=3, *args,**kwargs):
    print(a, b, c, args,kwargs)

func(1, 2, 3, 5, 6, 7,name="Alice", age=25)
  • a, b 是位置参数。
  • c=3 是带默认值的参数。
  • *args 是接受多个位置参数的元组。
  • **kwargs 是接受多个关键字参数的字典。

6. 参数的注意事项

  • 不能重复定义参数名:在同一个函数定义中,不能同时有位置参数和关键字参数的同名参数。
  • *args**kwargs*args 用于捕获额外的位置参数,而 **kwargs 用于捕获额外的关键字参数。它们通常放在最后,且只能有一个 *args和一个 **kwargs

7. 总结

  • 位置参数:传递给函数时按照定义的顺序进行匹配。
  • 关键字参数:通过明确指定参数名来传递,可以不依赖顺序。
  • 默认参数:可以在函数定义时为某些参数提供默认值。
  • *args:接受任意数量的位置参数并将它们作为元组传递。
  • **kwargs:接受任意数量的关键字参数并将它们作为字典传递。 函数的参数机制非常灵活,能够满足各种不同的需求。在编写函数时,理解这些参数的使用顺序和规则,可以让代码更加简洁、可读且高效。

四、变量的作用域

  • 局部作用域:在函数内部定义的变量,只能在函数内部使用。
  • 全局作用域:在函数外部定义的变量,可以在函数内外使用(如果在函数内没有局部变量与之同名)。
python
x = 10  # 全局变量

def my_func():
    x = 5  # 局部变量
    print(f"Inside function: {x}")

my_func()  # 输出 Inside function: 5
print(f"Outside function: {x}")  # 输出 Outside function: 10

如果需要在函数内部修改全局变量,需要使用 global 声明:

python
x = 10  # 全局变量

def my_func():
    global x  # 声明要使用全局变量 x
    x = 5  # 修改全局变量
    print(f"Inside function: {x}")

my_func()  # 输出 Inside function: 5
print(f"Outside function: {x}")  # 输出 Outside function: 5

如果需要在函数内部修改上一层的变量,需要使用 nonlocal 声明:

python
def outer():
    x = 0

    def inner():
        nonlocal x
        x = x + 1
        print(x)

    inner()
    inner()
outer()

程序输出:

1

2

Python 查找变量的规则是LEGB:

层级名称范围 / 例子
L – Local(局部作用域)当前函数内部函数内部定义的变量、参数
E – Enclosing(封闭作用域)外层函数(闭包)如果函数嵌套,上一层函数的变量
G – Global(全局作用域)模块级别当前模块中定义的变量
B – Built-in(内建作用域)Python 内建len(), print(), int

五、Lambda 函数

Lambda 函数是 Python 中的一种匿名函数,通常用于简化代码,尤其是当函数体非常简单时。它允许你在一行代码中定义一个小的函数,而不需要使用 def 来命名函数。语法如下:

python
lambda arguments: expression

lambda 关键字表示定义一个匿名函数。

参数:类似于普通函数的参数,可以是一个或多个。

表达式:该表达式会被计算并返回,它的值是 Lambda 函数的返回值。

示例:

python
square = lambda x: x ** 2
print(square(4))  # 输出 16

Lambda 函数通常用于那些短小、简单的函数场景。它只能包含一个表达式。所以它功能有限,仅适合处理简单的逻辑,不适合复杂的多语句操作。

六、递归函数

函数可以调用自身,这种函数称为递归函数。递归函数通常有一个终止条件,避免无限循环。

python
def factorial(n):
    if n == 0:
        return 1
    else:
        return n * factorial(n - 1)
    
print(factorial(5))  # 输出 120

七、空函数

空函数(也叫占位符函数)是指没有任何实际功能的函数,通常用于结构性设计中,作为占位符或者接口定义,目的是后续填充具体的实现。空函数在程序开发初期、调试阶段或者需要接口定义时非常有用。

在 Python 中,空函数的定义非常简单,通常是通过 pass 语句来实现的。pass 语句是一个空操作,什么都不做,只是占据了语法的位置。

python
def empty_function():
    pass  # 空函数体,什么都不做

在上面的例子中,empty_function 是一个空函数,它没有任何实际操作,调用这个函数时不会执行任何任务。

八、高阶函数

高阶函数(Higher-Order Functions)是指可以接受其他函数作为参数,或者返回一个函数作为结果的函数。它是函数式编程的一个核心概念,广泛应用于许多编程语言中,包括 Python。

高阶函数有以下两个关键特点:

  1. 接收函数作为参数:高阶函数可以接受其他函数作为参数,允许我们在调用时传递行为。
  2. 返回一个函数:高阶函数可以返回一个新的函数,使得函数的行为可以动态改变。

九、文档字符串

在 Python 中,文档字符串是一个放在函数体内部第一行的字符串,通常用于解释函数的功能、参数和返回值等信息。文档字符串可以用 help() 来查看。

python
def greet(name):
    """
    Greets the user with a message.

    Parameters:
    name (str): The name of the user to greet.

    Returns:
    str: A greeting message.
    """
    return f"Hello, {name}!"

help(greet)

输出:

python
Help on function greet in module __main__:

greet(name)
    Greets the user with a message.
    
    Parameters:
    name (str): The name of the user to greet.
    
    Returns:
    str: A greeting message.
  • 功能说明:简洁地描述函数做了什么。
  • 参数:列出所有参数的名字和类型,描述它们的作用。
  • 返回值:描述函数的返回值类型和内容。

十、内嵌函数

Python 函数内部可以定义函数,这种做法被称为嵌套函数。嵌套函数是指在一个函数内部定义另一个函数。

python
def outer_function(x):
    def inner_function(y):
        return y + 1
    
    result = inner_function(x)  # 调用内部函数
    return result

print(outer_function(5))  # 输出 6

十一、练习题

  1. 定义一个空函数 do_nothing(),该函数不接受任何参数,也不返回任何内容。
  2. 定义一个函数 greet(),该函数打印 Hello, world!
  3. 定义一个函数 add_numbers(a, b),接受两个参数 ab,返回它们的和。
  4. 定义一个函数 multiply_numbers(a, b),接受两个参数 ab,返回它们的乘积。
  5. 定义一个函数 draw_square(side_length),让海龟画一个正方形,边长由 side_length 决定。
  6. 定义一个函数 calculate_area(radius),计算并返回圆的面积。该函数接收一个参数 radius,表示圆的半径,返回圆的面积。
  7. 定义一个函数 is_even(n),判断一个数字 n 是否为偶数。如果是偶数返回 True,否则返回 False
  8. 定义一个函数 greet_person(name, age),该函数打印一条问候信息:Hello {name}, you are {age} years old.
  9. 定义一个函数 sum_numbers(*numbers),接收任意数量的数字作为位置参数,并返回这些数字的和。
  10. 定义一个函数 print_person_info(**info),接受一个字典类型的参数,打印出所有键值对。
  11. 定义一个函数 draw_circle(radius),让海龟画一个圆,半径由 radius 决定。
  12. 定义一个函数 draw_shapes(*shapes),接收多个形状,支持 circlesquare,并根据传入的大小绘制相应的图形。
  13. 定义一个函数 get_position(x, y),该函数返回一个元组 (x, y),表示坐标。调用此函数并打印返回的坐标。
  14. 定义一个函数 max_of_three(a, b, c),接受三个参数并返回它们中的最大值。
  15. 定义一个函数 get_name_and_age(),返回一个元组 (name, age)。调用该函数并打印返回的值。
  16. 定义一个函数 count_vowels(text),统计文本中元音字母的数量,并返回该数量。
  17. 定义一个函数 draw_multiple_shapes(),它能够绘制多个形状,传入不同的形状(如 circlesquare)和大小。每个形状可以传递颜色作为关键字参数。
  18. 定义一个函数 is_prime(n),判断一个数 n 是否是质数,如果是返回 True,否则返回 False
  19. 定义一个函数 update_person_info(info),接受一个字典参数 info,更新其中的 age35,并返回更新后的字典。
  20. 定义一个函数 convert_to_dict(*args),将传入的任意数量的参数转换为字典,其中每个参数作为键,值为 None。返回该字典。
  21. 定义一个递归函数 factorial(n),计算并返回整数 n 的阶乘。即 n! = n * (n-1) * (n-2) * ... * 1
  22. 定义一个递归函数 fibonacci(n),返回斐波那契数列的第 n 项。斐波那契数列的定义是:f(0) = 0, f(1) = 1,其他项为前两项之和,即 f(n) = f(n-1) + f(n-2)
  23. 定义一个递归函数 sum_of_digits(n),计算并返回数字 n 中各个数字的和。例如,输入 123 应返回 1 + 2 + 3 = 6
  24. 定义一个递归函数 reverse_string(s),返回字符串 s 的反转。例如,输入 hello 应返回 olleh
  25. 定义一个递归函数 power(base, exp),计算并返回 baseexp 次方。即 base**exp

💬 与我联系 QQ:774165314 | 微信:Yonas_Luo