第6节:函数

随着我们编写的程序越来越复杂,可能会遇到一些问题:

  • 代码重复: 同样或类似的代码片段需要在程序的不同地方多次使用。
  • 难以维护: 如果需要修改某个重复的功能,就得去修改所有用到它的地方,容易出错且效率低下。
  • 结构混乱: 大段的代码堆砌在一起,逻辑不清晰,难以阅读和理解。

我们可以使用Python中的函数来解决这个问题。函数允许我们将一段具有特定功能的代码打包起来,给它起一个名字,然后在需要的地方通过这个名字来调用(执行)它。

1. 定义函数

在 Python 中,使用 def 关键字来定义一个函数。

基本语法:

def 函数名(参数列表):
    """
    (可选) 函数文档字符串 - 描述函数的功能、参数和返回值
    """
    # 函数体 - 实现函数功能的代码块 (必须缩进!)
    语句1
    语句2
    # ...
    return 返回值 # (可选)
  • def 定义函数的关键字。
  • 函数名 给函数起的名字,遵循变量命名规则(小写字母和下划线)。好的函数名应该能清晰地表达函数的功能,例如 greet_user, calculate_sum
  • 参数列表 (Parameters): 括号 () 里是函数的参数,是函数需要接收的外部信息。参数之间用逗号 , 分隔。如果函数不需要接收任何信息,括号也不能省略,但里面是空的,例如 def say_hello():
  • : 参数列表后面必须有冒号。
  • """文档字符串""" 可选。通常是函数定义的第一行,用三引号包裹的多行字符串,用来解释函数的作用、参数含义、返回值等。这是一个好习惯,有助于他人(和未来的你)理解函数。
  • 函数体 实现函数具体功能的代码块,必须缩进
  • return 返回值 可选。return 语句用于指定函数的返回值,也就是函数执行完毕后反馈给调用者的结果。如果函数没有 return 语句,或者 return 后面没有跟任何值,它默认返回一个特殊的值 None

示例:定义一个简单的问候函数

def greet():
    """打印简单的问候语"""
    print("你好!欢迎学习 Python 函数!")

## 定义一个带参数的问候函数
def greet_user(name): # name 是参数,用于接收用户的名字
    """根据提供的名字打印问候语"""
    print("你好, " + name + "!")

## 定义一个计算两个数之和的函数
def add_numbers(num1, num2): # num1 和 num2 是参数
    """计算并返回两个数字的和"""
    result = num1 + num2
    return result # 返回计算结果

注意:定义函数只是创建了这个“积木块”,此时函数体内的代码并不会执行。

2. 调用函数

定义好函数之后,我们需要调用 (Call) 它来执行其中的代码。调用函数很简单,只需要使用函数名加上一对括号 () 即可。如果函数定义时有参数,调用时通常需要提供相应的参数值 (Arguments)

语法:

函数名(参数值列表)

示例:调用上面定义的函数

## 调用 greet() 函数
greet() # 输出: 你好!欢迎学习 Python 函数!

## 调用 greet_user() 函数,并传入参数值 "小明"
greet_user("小明") # 输出: 你好, 小明!
greet_user("莉莉") # 输出: 你好, 莉莉!

## 调用 add_numbers() 函数,并传入参数值 5 和 3
## 函数会返回一个结果,我们可以用一个变量来接收它
sum_result = add_numbers(5, 3)
print("5 和 3 的和是:", sum_result) # 输出: 5 和 3 的和是: 8

## 也可以直接打印函数的返回值
print(add_numbers(10, 20)) # 输出: 30

## 调用没有 return 语句的函数,其返回值是 None
result_from_greet = greet()
print("greet() 函数的返回值:", result_from_greet) # 输出: greet() 函数的返回值: None

3. 参数传递

当调用带参数的函数时,我们需要提供与参数列表对应的值。这些传入的值被称为实际参数 (Arguments),而函数定义时的参数被称为形式参数 (Parameters)

最基本的参数传递方式是位置参数 (Positional Arguments)。调用函数时,提供的参数值会按顺序依次传递给函数定义中的参数。

def describe_pet(animal_type, pet_name):
    """显示宠物的信息"""
    print("我有一只 " + animal_type + "。")
    print("它的名字叫 " + pet_name + "。")

## 调用函数,按位置传递参数
describe_pet("猫", "咪咪") # "猫" 传给 animal_type, "咪咪" 传给 pet_name

## 输出:
## 我有一只 猫。
## 它的名字叫 咪咪。

## 如果顺序搞错,结果可能就不对了
describe_pet("小白", "狗") # "小白" 传给 animal_type, "狗" 传给 pet_name

## 输出:
## 我有一只 小白。
## 它的名字叫 狗。

注意:调用时提供的参数数量通常需要和函数定义时的参数数量一致。

4. 返回值

函数可以通过 return 语句将执行结果返回给调用它的地方。返回值可以是任何数据类型(数字、字符串、列表、字典、布尔值等)。

  • 函数执行到 return 语句时,会立即结束,并将 return 后面的值返回。return 后面的代码不会被执行。
  • 一个函数可以有多个 return 语句(例如在不同的 if 分支中),但一次调用只会执行其中一个 return
  • 如果函数没有 return 语句,或者 return 后面没有值,则默认返回 None
def check_score(score):
    """根据分数判断等级并返回"""
    if score >= 60:
        return "及格" # 执行到这里,函数结束并返回 "及格"
        print("这里不会执行") # 这行代码永远不会被执行
    else:
        return "不及格"

result1 = check_score(75)
print("75分的结果:", result1) # 输出: 75分的结果: 及格

result2 = check_score(50)
print("50分的结果:", result2) # 输出: 50分的结果: 不及格

def no_return_function():
    x = 1 + 1
    # 没有 return 语句

value = no_return_function()
print("没有 return 的函数返回值:", value) # 输出: 没有 return 的函数返回值: None

5. 练习

  1. 定义一个名为 say_goodbye 的函数,它不需要参数,功能是打印一句 "再见!"。然后调用这个函数。
  2. 定义一个名为 square 的函数,它接收一个数字 num 作为参数,并返回这个数字的平方。调用这个函数计算 5 的平方并打印结果。
  3. 定义一个名为 get_greeting 的函数,它接收一个名字 name 作为参数,并返回一个包含问候语的字符串,例如 "你好, [name] 欢迎你!"。调用这个函数,传入你的名字,并将返回的问候语存储在一个变量中,然后打印这个变量。
  4. 定义一个函数 find_max,接收两个数字 ab 作为参数,返回两者中较大的那个数。

函数是 Python 编程中非常核心和重要的概念。通过将代码组织成函数,我们可以编写出更简洁、更清晰、更易于维护的程序。下一章我们将了解如何使用别人已经写好的函数(模块)。