【Python】def函数

Python 函数定义深度剖析:def 关键字的奥秘与实践

def 关键字是 Python 中定义函数的基石。函数是组织代码、提高复用性、实现模块化的基本单元。深入理解 def 的使用及其背后的机制,对于编写高质量、可维护的 Python 代码至关重要。

第一章:函数定义的基础:def 语法与基本结构

使用 def 关键字定义函数的基本语法如下:

def function_name(parameter1, parameter2, ...):
    """
    Docstring: 函数的说明文档,解释函数的功能、参数、返回值等。
    这部分是可选的,但强烈推荐编写。
    """
    # 函数体:包含执行任务的代码块
    # 函数体必须缩进
    statement1
    statement2
    # ...
    return result # 可选的返回值

1.1 def 关键字

def 是 define 的缩写,用于告诉 Python 解释器你正在定义一个函数。当解释器看到 def 时,它会创建一个函数对象,并将该对象赋值给后面指定的函数名。

1.2 函数名 (function_name)

  • 函数名是标识函数的名称,必须遵循 Python 的命名规则(以字母或下划线开头,后接字母、数字或下划线)。
  • 函数名应具有描述性,清晰地表明函数的功能。
  • 函数名是大小写敏感的。
  • 约定俗成地,函数名使用小写字母和下划线分隔单词(snake_case)。

示例 1.2.1:合法的和非法的函数名

def calculate_total(): # 合法且符合规范
    pass

def processData(): # 合法,但不太符合 Python 规范 (CamelCase)
    pass

def _helper_function(): # 合法,以下划线开头通常表示内部或私有函数 (约定)
    pass

# def 123_function(): # 非法,以数字开头
#     pass

# def my-function(): # 非法,包含连字符
#     pass

1.3 圆括号 ()

紧跟在函数名后面的圆括号用于包含函数的参数。即使函数没有参数,也必须保留这对圆括号。

示例 1.3.1:有参数和无参数的函数定义

def say_hello(): # 无参数
    print("Hello!")

def greet(name): # 一个参数
    print(f"Hello, {
     name}!")

def add(a, b): # 两个参数
    return a + b

1.4 参数列表 (parameter1, parameter2, ...)

  • 参数是在调用函数时传递给函数的值的占位符。
  • 参数是局部变量,只在函数内部有效。
  • 参数之间用逗号分隔。
  • Python 的参数非常灵活,支持多种类型,我们将在后续章节深入讲解。

1.5 冒号 :

函数定义的最后必须加上冒号,它标志着函数头的结束和函数体的开始。

1.6 函数体 (Indented Block)

  • 冒号之后,下一行开始是函数体。
  • 函数体必须缩进(通常是 4 个空格)。Python 使用缩进而不是大括号 {} 来标识代码块的归属。
  • 所有属于同一个函数的语句必须有相同的缩进级别。
  • 函数体包含函数执行时要运行的所有语句。

示例 1.6.1:缩进示例

def example_function():
    print("This line is inside the function.") # 缩进 4 个空格
    x = 10                                    # 缩进 4 个空格
    if x > 5:
        print("x is greater than 5.")         # 在 if 块内,需要更多缩进
    print("This line is also inside the function, but outside the if block.") # 回到函数体的主缩进级别
# print("This line is outside the function.") # 没有缩进,不属于函数体

1.7 文档字符串 (Docstring)

  • 函数体第一行可以使用一个字符串字面量作为文档字符串。
  • 文档字符串用于描述函数的功能、参数、返回值、可能抛出的异常等,是对函数进行说明的规范方式。
  • 可以使用单行或多行字符串。多行文档字符串通常使用三重引号 """Docstring content"""
  • 可以使用内置的 help() 函数或访问函数的 __doc__ 属性来查看文档字符串。

示例 1.7.1:文档字符串示例

def multiply(a, b):
    """
    这个函数计算两个数字的乘积。

    Args:
        a: 第一个数字。
        b: 第二个数字。

    Returns:
        a 和 b 的乘积。
    """
    return a * b

print(help(multiply)) # 查看函数的文档
print(multiply.__doc__) # 访问 __doc__ 属性

良好的文档字符串是编写易于理解和维护的代码的重要组成部分。

1.8 return 语句

  • return 语句用于从函数中退出,并将一个值返回给函数调用者。
  • 一个函数可以没有 return 语句。在这种情况下,函数执行完毕后,默认返回 None
  • return 语句可以出现在函数体的任何位置。一旦执行到 return,函数会立即终止。
  • return 后面可以跟一个表达式或多个表达式(此时会返回一个元组)。

示例 1.8.1:return 语句的使用

def greet_and_return(name):
    print(f"Hello, {
     name}!")
    return f"Greeting completed for {
     name}" # 返回一个字符串

result = greet_and_return("Alice")
print(f"函数返回的结果: {
     result}")

def no_return_function():
    print("This function does not have a return statement.")

result2 = no_return_function()
print(f"没有 return 语句的函数返回的结果: {
     result2}") # 输出 None

def early_exit(x):
    if x < 0:
        print("输入是负数,提前退出。")
        return "Error: Negative input" # 遇到负数时提前返回
    print("输入是非负数,继续计算。")
    return x * 2

print(early_exit(5))
print(early_exit(-3))

def return_multiple_values():
    return 1, "hello", [3, 4] # 返回一个元组

a, b, c = return_multiple_values()
print(f"返回的多个值: a={
     a}, b={
     b}, c={
     c}")

理解 return 如何控制函数执行流程和传递结果是掌握函数使用的基础。

第二章:函数参数的深度解析

Python 函数的参数机制非常灵活,支持多种参数类型,可以应对各种调用场景。

2.1 位置参数 (Positional Arguments)

位置参数是最常见的参数类型。在函数调用时,实参的值按照它们在参数列表中的位置顺序与函数定义中的形参一一对应。

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

print("--- 位置参数调用示例 ---")
describe_pet('仓鼠', '哈姆太郎') # '仓鼠' 对应 animal_type, '哈姆太郎' 对应 pet_name

# 如果位置不匹配,会导致错误
# describe_pet('哈姆太郎', '仓鼠') # 顺序错误,输出 "我有一只 哈姆太郎。"
# describe_pet('狗') # 参数数量不够,会引发 TypeError
# describe_pet('猫', '加菲', '加多宝') # 参数数量过多,会引发 TypeError

调用时提供的实参数量和顺序必须与函数定义中的形参数量和顺序严格匹配(除非使用了其他参数类型)。

2.2 关键字参数 (Keyword Arguments)

关键字参数允许你在调用函数时,通过形参的名称来指定实参的值,而不必关心实参的顺序。

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

print("\n--- 关键字参数调用示例 ---")
describe_pet(animal_type='仓鼠', pet_name='哈姆太郎') # 使用关键字指定
describe_pet(pet_name='哈姆太郎', animal_type='仓鼠') # 改变顺序也可以,因为指定了关键字

结合使用位置参数和关键字参数时,需要注意:所有位置参数必须出现在关键字参数之前。

# 合法的组合调用
describe_pet('仓鼠', pet_name='哈姆太郎')

# 非法的组合调用 (位置参数在关键字参数之后)
# describe_pet(pet_name='哈姆太郎', '仓鼠') # SyntaxError: positional argument follows keyword argument

2.3 默认参数 (Default Arguments)

你可以在函数定义时为参数指定默认值。如果调用函数时没有为该参数提供实参,就会使用默认值。带有默认值的参数必须放在没有默认值的参数后面。

def describe_pet(pet_name, animal_type='狗'): # animal_type 具有默认值,放在 pet_name 后面
    """显示宠物的信息,默认动物类型是狗。"""
    print(f"我有一只 {
     animal_type}。")
    print(f"它的名字叫 {
     pet_name}。")

print("\n--- 默认参数调用示例 ---")
describe_pet('旺财')            # animal_type 使用默认值 '狗'
describe_pet('咪咪', '猫')      # 为 animal_type 提供实参,覆盖默认值
describe_pet(pet_name='小黄')   # 使用关键字参数调用,animal_type 使用默认值
describe_pet(pet_name='大白', animal_type='兔') # 使用关键字参数覆盖默认值

# 错误的默认参数位置
# def greet(name='Guest', message): # 非法:没有默认值的参数在有默认值的参数之后
#     print(f"{message}, {name}!")

默认参数的陷阱 (可变默认参数): 默认值在函数定义时只计算一次。如果默认值是可变对象(如列表、字典或集合),并且在函数体内修改了这个默认值,那么在后续调用中,这个修改会保留下来。

# 错误的示例:使用可变对象作为默认参数
def append_to_list(value, my_list=[]):
    my_list.append(value)
    return my_list

print("\n--- 可变默认参数陷阱示例 ---")
print(append_to_list(1)) # 输出: [1]
print(append_to_list(2)) # 输出: [1, 2] - 意料之外!使用了同一个列表
print(append_to_list(3)) # 输出: [1, 2, 3]

# 正确的做法是使用不可变对象(如 None)作为默认值,并在函数体内检查并创建新的可变对象
def append_to_list_correct(value, my_list=None):
    if my_list is None:
        my_list = [] # 在函数被调用时创建新的列表
    my_list.append(value)
    return my_list

print("\n--- 正确处理可变默认参数 ---")
print(append_to_list_correct(1)) # 输出: [1]
print(append_to_list_correct(2)) # 输出: [2] - 现在每次调用都使用新的列表
print(append_to_list_correct(3)) # 输出: [3]

这是 Python 中一个常见但重要的陷阱,务必引起注意。

2.4 任意数量的位置参数 (*args)

有时你不知道函数会接收多少个位置参数。可以使用 *args 来收集任意数量的位置参数,它们会被存储在一个元组中。

def sum_all(*args):
    """计算所有位置参数的和。"""
    print(f"\n--- sum_all 接收到参数: {
     args} (类型: {
     type(args

你可能感兴趣的:(python,开发语言)