程序员文章、书籍推荐和程序员创业信息与资源分享平台

网站首页 > 技术文章 正文

告别重复,打造你的代码工具箱:Python函数深度解析

hfteth 2025-06-03 22:05:43 技术文章 4 ℃

嘿!欢迎来到我们的Python学习旅程!

一路走来,你肯定和 print(), input(), len(), int() 这些老朋友打过不少交道了吧?它们都是Python内置的函数—— 想象一下,就像Python为你准备好的各种小工具,开箱即用,非常方便!

但是,我们在写程序的时候,是不是经常会遇到这样的情况:有些功能的代码,写了一遍又一遍?或者为了完成一个小任务,得写好几行代码,而且这个小任务在程序里要做好几次?

这时候你可能就会想:如果我也能像Python一样,把我常用的那几行代码打包成一个“我自己的工具”,然后想用的时候就直接调用它,那该多方便啊!

好消息是:Python完全支持你这样做!这个**“你自己打造的工具”,在Python里就叫做函数**!

今天,我们就来揭开函数的神秘面纱,学习怎么创建和使用我们自己的函数,把你的代码从“写流水账”变成“搭积木”!

什么是Python函数?

到底什么是函数呢?

简单来说,函数就是一段被赋予了名字的、可以重复使用的代码块。你可以把它看作是你给计算机下达的、一个带有特定指令的自定义命令

回想一下,我们之前学过的 print(),它的名字就叫 print,它的功能就是“把信息显示出来”。我们每次想显示信息,就调用 print()。

函数就是让你也能创建这样的“自定义命令”。

为什么你需要自定义函数?

为什么我们要花时间学习自定义函数呢?核心原因在于它能极大地提升你的编程效率和代码质量:

  1. 摆脱重复 (Don't Repeat Yourself - DRY原则): 把重复写的代码封装起来,以后直接调用。想象一下,如果你需要计算不同矩形的面积好几次,每次都得写 宽度 * 高度,是不是很麻烦?把这个计算过程打包成函数,以后调用一次函数就行了。
  2. 让代码更整洁、易读: 把大段的代码或复杂任务拆分成小块,每个函数只做一件事情,整个程序结构会非常清晰,就像把一本大书分成了很多有标题的章节。
  3. 易于维护: 如果某个功能(比如你计算面积的方法)需要修改,你只需要修改对应的函数代码,其他调用它的地方会自动使用新的逻辑,不容易出错。

自定义函数是构建任何非简单程序的基础。

如何定义你的第一个函数

好了,理论讲完了,我们看看怎么动手定义一个函数。Python用 def 这个特殊的关键字来“定义”一个函数。

看看这个最简单的函数结构:

# 用 def 关键字开始定义你的函数
def my_first_function(): # def 关键字,函数名,小括号 (),冒号 :
  # 接下来是函数要执行的代码
  # 记住:函数体内的代码必须缩进!
  print("哇!我自己的函数运行啦!")

# 函数定义完成了,它就像你设计好的一个工具,现在还静静地待在那里。
# 它不会自动运行!

语法是:先写 def,然后给你的函数起一个响亮的名字(比如 my_first_function),接着是一对圆括号 (),最后用一个冒号 : 结束定义行。函数名后面的圆括号是用来放参数的,我们稍后详细讲。

函数定义体内部的代码必须保持统一缩进。这个缩进告诉Python,“这些代码”属于上面那个函数。

调用函数:让它开始工作!

函数定义好了,怎么让它运行起来呢?你需要调用它!就像调用 print() 一样简单,直接写函数名和括号就行了!

# 函数定义 (同上)
def my_first_function():
  print("哇!我自己的函数运行啦!")

# --- 现在,调用函数让它运行 ---

print("--- 准备调用我的第一个函数 ---")
my_first_function() # 直接写函数名和括号即可
print("--- 调用完成 ---")

# 函数可以重复调用!
print("--- 再次调用! ---")
my_first_function()

运行上面这段代码,你会看到函数体内的 print 语句被执行了两次。

函数的输入:参数详解

很多工具都需要“原材料”或“指令”才能工作,比如 print() 需要你告诉它要打印什么信息,len() 需要你给它一个字符串或列表。函数也一样,它可以接收外部传进来的数据,这些数据就叫做参数 (Parameters)

在定义函数时,我们在函数名后面的括号里指定参数的名字,用逗号隔开。就像你写蛋糕食谱,会列出需要的配料:“面粉”、“鸡蛋”。

1. 位置参数 (Positional Arguments)

这是最常见的参数类型。调用函数时,按照参数在定义时的位置顺序传入值。

# 定义一个带一个参数的函数:greet
# name 就是一个参数,代表要问候的名字
def greet(name):
  print(f"Hello, {name}!") # 在函数内部使用参数 name

# 调用 greet 函数,并传入参数值(或者叫“实参”)
greet("Alice") # 把 "Alice" 传给了 name
greet("Bob")   # 把 "Bob" 传给了 name

# 定义一个带两个参数的函数:计算矩形面积
def calculate_rectangle_area(width, height): # width 和 height 是两个参数
  area = width * height # 在函数内部使用参数进行计算
  print(f"宽度为 {width}, 高度为 {height} 的矩形面积是: {area}")

# 调用 calculate_rectangle_area 函数
calculate_rectangle_area(10, 5) # 把 10 传给 width,把 5 传给 height
calculate_rectangle_area(2.5, 8)

运行结果:

Hello, Alice!
Hello, Bob!
宽度为 10, 高度为 5 的矩形面积是: 50
宽度为 2.5, 高度为 8 的矩形面积是: 20.0

调用 greet 函数时,第一个值 "Alice" 传给了 name 参数。调用 calculate_rectangle_area 时,第一个值 10 传给了 width,第二个值 5 传给了 height。参数的顺序很重要!

2. 关键字参数 (Keyword Arguments)

调用函数时,你可以指定参数名来传值。这样就不怕搞错参数的顺序了,而且代码更清晰。

# 继续使用上面的 calculate_rectangle_area 函数
def calculate_rectangle_area(width, height):
  area = width * height
  print(f"宽度为 {width}, 高度为 {height} 的矩形面积是: {area}")

# 使用关键字参数调用函数
calculate_rectangle_area(width=12, height=6)
calculate_rectangle_area(height=4, width=7) # 注意:顺序调换也没关系!

运行结果:

宽度为 12, 高度为 6 的矩形面积是: 72
宽度为 7, 高度为 4 的矩形面积是: 28

使用关键字参数提高了代码的可读性。记住,在一个函数调用中,位置参数必须在关键字参数之前

3. 默认参数 (Default Parameters)

你可以给函数的参数设置一个默认值。如果调用函数时不为这个参数传值,它就会使用默认值。

# 定义一个带默认参数的问候函数,可以指定问候语
# name 是必需的参数,greeting 有默认值 "Hello"
def custom_greet(name, greeting="Hello"):
  print(f"{greeting}, {name}!")

# 调用函数
custom_greet("Alice")     # 只传入 name,greeting 使用默认值 "Hello"
custom_greet("Bob", "Hi")  # 传入 name 和 greeting,覆盖默认值

运行结果:

Hello, Alice!
Hi, Bob!

默认参数非常方便,可以让你的函数更灵活。有默认值的参数必须放在没有默认值的参数后面

进阶参数(了解即可):

  • *args: 用于收集任意数量的位置参数到一个元组。
  • **kwargs: 用于收集任意数量的关键字参数到一个字典。

这两个通常用于你需要创建一个能接受非常灵活输入的函数时。

函数的输出:返回值

函数不仅能接收输入,还能像 len() 那样,计算出结果并给回调用它的地方。这就是通过 return 语句实现的。

print vs return

这是初学者容易混淆的地方。

  • print() 只是把信息显示在屏幕上,函数执行完毕后,你无法在程序中获取这个显示的信息。
  • return 是把函数处理后的结果数据到调用它的地方,你可以用一个变量来接收这个结果,并在后续的代码中使用它。

我们修改一下刚才计算矩形面积的函数,让它返回面积而不是直接打印:

# 只打印结果的函数 (刚才的矩形面积例子)
def calculate_and_print_area(width, height):
  area = width * height
  print(f"打印出的面积是: {area}") # 只是打印出来

# 返回结果的函数 (修改,让它返回面积而不是打印)
def calculate_rectangle_area_and_return(width, height):
  area = width * height
  return area # 把计算结果返回!

# 调用并比较
print("--- 调用 calculate_and_print_area ---")
calculate_and_print_area(10, 5) # 它自己打印,函数调用本身没有“值”

print("\n--- 调用 calculate_rectangle_area_and_return ---")
# 调用函数,用一个变量来接收它的返回值
room_area = calculate_rectangle_area_and_return(10, 5)
print(f"我用变量接收到的房间面积是: {room_area}")

# 接收到返回值后,我可以继续用它做别的计算,比如计算总成本
cost_per_sq_meter = 100
total_cost = room_area * cost_per_sq_meter
print(f"总成本是: {total_cost} 元")

运行结果:

--- 调用 calculate_and_print_area ---
打印出的面积是: 50

--- 调用 calculate_rectangle_area_and_return ---
我用变量接收到的房间面积是: 50
总成本是: 5000 元

看到了吗? calculate_and_print_area 帮你把结果打印出来了,但你无法在程序中获取到 50 这个值用于后续计算总成本。而
calculate_rectangle_area_and_return 则把 50 这个值“吐”出来了,你可以用 room_area 变量接住它,之后想怎么用它都可以!

没有 return 怎么办?

如果函数没有 return 语句,或者只有 return 后面不跟值,这种情况下,函数会默认返回一个特殊的值:None。它表示“空”或者“没有明确的返回值”。

# 没有 return 的函数
def just_do_something():
  print("我做了一些事")
  # 没有 return 语句

result_of_doing = just_do_something()
print(f"这个函数返回了: {result_of_doing}")

运行结果:

我做了一些事
这个函数返回了: None

返回多个值

函数可以返回任何类型的数据,包括数字、字符串、列表、字典,甚至其他函数!函数还可以一次返回多个值!只需要用逗号隔开,Python会把它们打包成一个元组 (tuple) 返回给你。

# 返回多个值的函数,比如同时返回面积和周长
def calculate_area_and_perimeter(width, height):
  # 简单的检查,避免输入无效
  if width <= 0 or height <= 0:
    print("警告: 宽度和高度必须大于0")
    return None, None # 返回两个 None 表示计算失败

  area = width * height
  perimeter = 2 * (width + height)
  return area, perimeter # 返回面积和周长 (作为一个元组)

# 调用函数并接收多个返回值
# 使用多个变量接收返回值
rectangle_area, rectangle_perimeter = calculate_area_and_perimeter(10, 5)
print(f"矩形的面积是: {rectangle_area}, 周长是: {rectangle_perimeter}")

# 也可以用一个变量接收整个元组
result_tuple = calculate_area_and_perimeter(3, 4)
print(f"另一个矩形的结果元组是: {result_tuple}")

运行结果:

矩形的面积是: 50, 周长是: 30
另一个矩形的结果元组是: (12, 14)

用多个变量 = 函数调用的方式,可以直接把元组里的值解包赋给不同的变量,非常实用!

变量作用域:函数中的“界限”

在函数内部创建的变量(比如我们函数里的 area 或 result),通常只能在函数内部使用,函数外面是访问不到的。这叫做局部作用域 (Local Scope)

而在函数外面定义的变量,在函数内部通常是可以访问的(叫做全局作用域 (Global Scope))。

global_message = "我是一个全局变量"

def show_scope():
  local_message = "我是一个局部变量" # 这个变量只存在于这个函数里
  print(global_message) # 函数内部可以访问全局变量
  print(local_message)  # 函数内部可以访问自己的局部变量

# --- 调用函数 ---
show_scope()

# --- 尝试在函数外部访问局部变量 ---
# print(local_message) # 如果取消这行注释,会报错!因为 local_message 只在函数内部存在

运行上面的代码,你会看到函数内部打印出了两个变量的值。但是,尝试在函数外部打印 local_message 会导致 NameError,因为这个变量只在 show_scope 函数运行时存在。

理解作用域很重要,它能帮助你更好地组织变量,避免不同代码块之间的变量名冲突和意外修改。

给你的工具写说明书:文档字符串 (Docstrings)

就像你买工具会有说明书一样,给你自己写的函数加上说明是非常好的习惯!用文档字符串 (Docstrings) 可以做到这一点。文档字符串紧跟在函数定义行的下一行,用三个双引号 """Docstring""" 包围。

它应该解释函数做什么、接受什么参数、返回什么。

def calculate_area_and_perimeter(width, height):
  """
  计算矩形的面积和周长。

  参数:
    width: 矩形的宽度 (必须 > 0 的数字)
    height: 矩形的高度 (必须 > 0 的数字)

  返回:
    如果输入有效,返回一个包含 (面积, 周长) 的元组 (tuple)。
    如果输入无效,返回 (None, None)。
  """
  if width <= 0 or height <= 0:
    print("警告: 宽度和高度必须大于0")
    return None, None

  area = width * height
  perimeter = 2 * (width + height)
  return area, perimeter

写上文档字符串,以后你自己或者其他人在使用你的函数时,一看说明就知道怎么用,它做什么,需要什么输入,会给出什么输出。你可以使用内置的 help() 函数或者访问函数的 .__doc__ 属性来查看文档字符串。

总结与挑战

好了!我们今天一起深入学习了Python函数的创建和使用!从我们熟悉的内置函数出发,到创建自己的函数,理解参数的传递(位置、关键字、默认),学会通过 return 获取函数的计算结果,还了解了变量作用域和文档字符串。

函数是构建复杂程序的基石之一,掌握它,你的代码会变得更简洁、更灵活、更强大!

现在,你已经拥有了打造自己代码“工具箱”的能力!试着回顾一下你之前写的小程序,有没有哪些重复的代码段?有没有哪些完成特定小任务的代码(比如格式化输出、简单的验证、计算某个值)?把它们变成你自己的函数吧!这是巩固学习最好的方式。

希望这篇文章能帮助你迈出自定义函数的第一步!函数的世界还有更多可以探索,比如递归、匿名函数lambda、高阶函数等等,但掌握了今天的内容,你就打下了坚实的基础!

有什么问题或心得,欢迎在评论区交流!别忘了点赞和分享,也请关注我,获取更多精彩的Python教程!

最近发表
标签列表