文章目录

      • 为什么要使用函数?
      • 函数的定义 (`def`)
      • 函数的调用
      • 函数参数 (Parameters vs Arguments)
      • 返回值 (`return`)
      • 变量作用域 (简要了解)
      • 总结
      • 练习题
      • 练习题答案
  • **创作不易,请大家点赞加收藏,关注我,持续更新教程!**

到目前为止,我们已经学习了基本的数据类型、集合类型以及控制程序流程的条件语句和循环。随着程序越来越复杂,我们可能会发现自己反复编写相同的代码块来执行特定任务。这不仅低效,还会导致代码难以阅读和维护。

函数就是解决这个问题的重要工具。它们允许我们将一段代码封装起来,赋予一个名字,然后在需要的时候多次调用。本篇博客将深入讲解如何定义自己的函数、如何调用它们,以及如何使用 return 语句从函数中获取结果。

为什么要使用函数?

使用函数的好处多多:

  1. 代码重用 (Reusability): 避免重复编写相同的代码块。遵循 DRY (Don’t Repeat Yourself) 原则。
  2. 模块化 (Modularity): 将程序分解成更小、更易于管理和理解的部分。每个函数负责一个特定的任务。
  3. 提高可读性 (Readability): 通过有意义的函数名,代码变得更容易理解其目的。
  4. 易于维护和调试 (Maintainability & Debugging): 当需要修改或修复某个功能的代码时,只需在一个地方(函数定义处)进行修改。如果出现错误,更容易定位问题在哪个函数中。

函数的定义 (def)

在 Python 中,使用 def 关键字来定义一个函数。定义函数的基本结构如下:

def function_name(parameter1, parameter2, ...):"""这里是函数的文档字符串 (Docstring)。解释函数的功能、参数和返回值。"""# 函数体 - 执行任务的代码块# ...# return value # 可选的返回值
  • def 关键字: 标记着一个函数的定义开始。
  • function_name: 函数的名字。需要遵循 Python 的命名规则(通常使用小写字母和下划线 _ 组合,称为 snake_case)。函数名应该能够清晰地表明函数的功能。
  • 圆括号 (): 紧跟在函数名后面。里面可以包含参数 (Parameters),用于接收外部传递进来的数据。如果没有参数,圆括号也不能省略。
  • 冒号 :: 标记着函数头部的结束,函数体即将开始。
  • 文档字符串 (Docstring): 使用三引号 """ """''' ''' 包围起来的一段文本。它应该在函数头部的下一行,用于详细说明函数的作用。这是 Python 的一个重要特性,可以通过 help(function_name)function_name.__doc__ 查看。编写良好的文档字符串是好习惯。
  • 函数体: 缩进的代码块,包含了函数执行的实际操作。
  • return 语句: 用于指定函数执行完毕后返回给调用者的值。是可选的。

示例: 定义一个简单的函数,它不接受参数,也不返回值,只打印一条消息。

def greet():"""这是一个简单的打招呼函数。"""print("Hello, welcome to Python functions!")print("This function does not take arguments and does not return a value.")

上面的代码只是定义了一个函数,它还没有被执行。

函数的调用

定义函数后,要让它执行里面的代码,就需要调用它。调用函数非常简单,只需要使用函数名后面加上圆括号 () 即可。如果函数定义时有参数,调用时需要在圆括号中提供相应的实参 (Arguments)

# 调用上面定义的 greet 函数
greet()
greet() # 函数可以被多次调用

输出:

Hello, welcome to Python functions!
This function does not take arguments and does not return a value.
Hello, welcome to Python functions!
This function does not take arguments and does not return a value.

函数参数 (Parameters vs Arguments)

  • 参数 (Parameters): 在函数定义时,圆括号中列出的变量名。它们是函数内部使用的占位符,代表函数期望接收的数据。
  • 实参 (Arguments): 在函数调用时,传递给函数参数的实际值。
# 定义一个接受一个参数的函数
def greet_person(name):"""向指定名字的人打招呼。Args:name: 要打招呼的人的名字 (字符串)。"""print(f"Hello, {name}!")# 调用函数,并传递实参
greet_person("Alice") # "Alice" 是传递给 name 参数的实参
greet_person("Bob")   # "Bob" 是传递给 name 参数的实参

输出:

Hello, Alice!
Hello, Bob!

一个函数可以有多个参数,调用时需要按照参数定义的顺序传递实参。

# 定义一个接受两个参数的函数
def add_numbers(a, b):"""计算两个数字的和。Args:a: 第一个数字。b: 第二个数字。"""sum_result = a + bprint(f"{a} + {b} = {sum_result}")# 调用函数,传递两个实参
add_numbers(5, 3)     # a=5, b=3
add_numbers(10, 20)   # a=10, b=20

输出:

5 + 3 = 8
10 + 20 = 30

调用带有参数的函数时,必须提供正确数量的实参(对于目前我们学习的必需参数)。

返回值 (return)

函数的一个重要作用是执行计算并将结果返回给调用者。使用 return 语句来实现。

  • return value: 函数执行到 return 语句时,会立即停止执行,并将 value 返回给调用者。
  • 如果函数没有 return 语句,或者只有不带值的 return,它会隐式地返回特殊的值 None
  • None 是 Python 中表示“无”或“空”的一个特殊对象。
# 定义一个函数,使用 return 返回计算结果
def multiply(x, y):"""计算两个数字的乘积并返回结果。Args:x: 第一个数字。y: 第二个数字。Returns:两个数字的乘积。"""product = x * yreturn product # 返回计算得到的乘积# 调用函数,并用变量接收返回值
result = multiply(4, 6)
print(f"乘积是: {result}") # 输出: 乘积是: 24another_result = multiply(2.5, 4)
print(f"另一个乘积是: {another_result}") # 输出: 另一个乘积是: 10.0

注意: return 语句一旦执行,函数就会结束。return 后面的代码将不会被执行。

def example_return(num):if num > 10:return "大于 10" # 如果 num > 10,函数在这里结束print("数字不大于 10") # 如果 num <= 10,这行会执行return "小于或等于 10" # 然后返回这个值print(example_return(15)) # 输出: 大于 10
print(example_return(8))  # 输出: 数字不大于 10\n小于或等于 10

隐式返回 None:

def print_message(msg):"""只打印消息,没有 return 语句。"""print(msg)# 隐式地返回 Nonereturn_value = print_message("Hello")
print(f"函数返回的值是: {return_value}") # 输出: Hello\n函数返回的值是: None

返回多个值:

Python 函数可以看似返回多个值,实际上,它是将多个值封装在一个元组 (tuple) 中返回。

def get_name_and_age():"""返回名字和年龄。"""name = "Charlie"age = 25return name, age # 实际上返回 ('Charlie', 25)info = get_name_and_age()
print(f"获取到的信息是: {info}")      # 输出: 获取到的信息是: ('Charlie', 25)
print(f"类型是: {type(info)}")       # 输出: 类型是: <class 'tuple'># 可以使用元组解包来分别获取返回值
person_name, person_age = get_name_and_age()
print(f"名字: {person_name}, 年龄: {person_age}") # 输出: 名字: Charlie, 年龄: 25

变量作用域 (简要了解)

在函数内部定义的变量(包括参数)通常是局部变量 (Local Variables)。它们只存在于函数执行期间,函数结束后就会被销毁,在函数外部无法访问。

def my_function():x = 10 # x 是局部变量print(f"函数内部的 x: {x}")my_function()
# print(x) # 这会引发 NameError,因为 x 在函数外部不存在

全局变量(在函数外部定义的变量)可以在函数内部访问,但不建议在函数内部直接修改全局变量,除非使用 global 关键字(但这通常是初学者应尽量避免的高级用法)。将数据通过参数传递进函数,通过返回值传出,是更好的实践。

总结

函数是 Python 中组织代码、实现重用和模块化的核心工具。本篇我们学习了:

  • 使用 def 关键字定义函数。
  • 理解参数 (Parameters) 和实参 (Arguments) 的区别。
  • 如何调用函数来执行其代码。
  • 使用 return 语句从函数中返回一个或多个值。
  • 函数没有显式返回值时默认返回 None
  • 函数内部变量的局部作用域概念。
  • 编写文档字符串说明函数功能。

练习题

尝试独立完成以下练习题,并通过答案进行对照:

  1. 简单函数定义与调用:

    • 定义一个函数 print_hello(),它不接受参数,只打印 “Hello, Python!”。调用这个函数。
  2. 带参数的函数:

    • 定义一个函数 say_greeting(name),它接受一个字符串参数 name,并打印 “Hello, [name]!”。调用这个函数,传入你的名字。
  3. 带返回值的函数:

    • 定义一个函数 calculate_square(number),它接受一个数字参数 number,计算并返回这个数字的平方。调用这个函数,并打印返回值。
    • 定义一个函数 is_even(number),它接受一个整数参数 number,如果数字是偶数返回 True,否则返回 False。调用这个函数测试几个数字。
  4. 返回多个值的函数:

    • 定义一个函数 divide_and_remainder(a, b),它接受两个数字 ab,计算 a 除以 b 的商和余数,并同时返回这两个结果(作为一个元组)。调用这个函数,并使用元组解包分别获取商和余数,然后打印。
  5. 结合循环和条件的函数:

    • 定义一个函数 count_vowels(text),它接受一个字符串参数 text,遍历字符串,统计其中元音字母(a, e, i, o, u,不区分大小写)的数量,并返回数量。调用这个函数测试一些字符串。
  6. 带文档字符串的函数:

    • 为你前面定义的任何一个函数添加一个清晰的文档字符串,说明其功能、参数和返回值。然后使用 help() 函数查看你写的文档。

练习题答案

1. 简单函数定义与调用:

# 1. 简单函数定义与调用
def print_hello():"""打印一条简单的问候信息。"""print("Hello, Python!")# 调用函数
print_hello()

2. 带参数的函数:

# 2. 带参数的函数
def say_greeting(name):"""向指定名字的人打招呼。Args:name: 要打招呼的人的名字 (字符串)。"""print(f"Hello, {name}!")# 调用函数
say_greeting("Alice")
say_greeting("Bob")

3. 带返回值的函数:

# 3.1 计算平方并返回
def calculate_square(number):"""计算并返回一个数字的平方。Args:number: 需要计算平方的数字。Returns:number 的平方。"""return number ** 2# 调用并打印返回值
result1 = calculate_square(5)
print(f"5 的平方是: {result1}")result2 = calculate_square(3.5)
print(f"3.5 的平方是: {result2}")# 3.2 判断奇偶数并返回布尔值
def is_even(number):"""判断一个整数是否是偶数。Args:number: 需要判断的整数。Returns:如果数字是偶数返回 True,否则返回 False。"""return number % 2 == 0# 调用并测试
print(f"4 是偶数吗? {is_even(4)}")
print(f"7 是偶数吗? {is_even(7)}")
print(f"0 是偶数吗? {is_even(0)}")

4. 返回多个值的函数:

# 4. 返回多个值的函数
def divide_and_remainder(a, b):"""计算两个数字的商和余数。Args:a: 被除数。b: 除数 (不能为 0)。Returns:一个包含商和余数的元组 (quotient, remainder)。如果 b 为 0,返回 None。"""if b == 0:print("错误: 除数不能为零。")return None # 或者根据需要处理错误quotient = a // b  # 整数除法获取商remainder = a % b   # 获取余数return quotient, remainder # 返回一个元组# 调用并解包返回值
result_tuple = divide_and_remainder(10, 3)if result_tuple is not None: # 检查返回值是否为 Nonequotient, remainder = result_tuple # 元组解包print(f"10 除以 3 的商是: {quotient}, 余数是: {remainder}")divide_and_remainder(5, 0) # 测试除数为零的情况

5. 结合循环和条件的函数:

# 5. 结合循环和条件的函数
def count_vowels(text):"""统计字符串中元音字母的数量。Args:text: 输入的字符串。Returns:字符串中元音字母 (a, e, i, o, u, 不区分大小写) 的数量。"""vowels = "aeiouAEIOU" # 元音字母集合vowel_count = 0for char in text: # 遍历字符串中的每个字符if char in vowels: # 检查字符是否在元音字母集合中vowel_count += 1return vowel_count# 调用并测试
sentence1 = "Hello World"
count1 = count_vowels(sentence1)
print(f"'{sentence1}' 中的元音字母数量: {count1}")sentence2 = "Python Programming"
count2 = count_vowels(sentence2)
print(f"'{sentence2}' 中的元音字母数量: {count2}")

6. 带文档字符串的函数:

选择上面任意一个函数,确保你已经添加了文档字符串,然后运行以下代码:

# 假设你已经为 calculate_square 函数添加了文档字符串
# 运行以下代码查看文档
help(calculate_square)# 或者直接访问 __doc__ 属性
print("\n--- 通过 __doc__ 属性访问文档字符串 ---")
print(calculate_square.__doc__)

运行 help(calculate_square) 应该会输出你为 calculate_square 函数编写的文档字符串内容(通常会格式化得更漂亮)。

创作不易,请大家点赞加收藏,关注我,持续更新教程!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/79426.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/79426.shtml
英文地址,请注明出处:http://en.pswp.cn/web/79426.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

华为配置篇-RSTP/MSTP实验

MSTP 一、简介二、常用命令总结三、实验 一、简介 RSTP&#xff08;快速生成树协议&#xff09;​ RSTP&#xff08;Rapid Spanning Tree Protocol&#xff09;是 STP 的改进版本&#xff0c;基于 ​​IEEE 802.1w 标准​​&#xff0c;核心目标是解决传统 STP 收敛速度慢的问…

Docker Compose 完全指南:从入门到生产实践

Docker Compose 完全指南&#xff1a;从入门到生产实践 1. Docker Compose 简介与核心价值 Docker Compose 是一个用于定义和运行多容器 Docker 应用程序的工具。通过一个 YAML 文件来配置应用的服务&#xff0c;只需简单命令就能创建和启动所有服务。 核心优势&#xff1a;…

Linux 离线安装 Docker 和 Docker Compose 最新版 的完整指南

一、准备工作 1. 下载安装包​&#xff08;需在有网络的机器操作&#xff09;&#xff1a; Docker 引擎&#xff1a;从官方仓库下载最新二进制包 wget https://download.docker.com/linux/static/stable/x86_64/docker-24.0.6.tgz​Docker Compose&#xff1a;下载最新二进制…

CSS: 选择器与三大特性

标签选择器 标签选择器就是选择一些HTML的不同标签&#xff0c;由于它们的标签需求不同&#xff0c;所以CSS需要设置标签去选择它们&#xff0c;为满足它们的需求给予对应的属性 基础选择器 标签选择器 <!DOCTYPE html> <head><title>HOME</title>…

鸿蒙跨平台开发教程之Uniapp布局基础

前两天的文章内容对uniapp开发鸿蒙应用做了一些详细的介绍&#xff0c;包括配置开发环境和项目结构目录解读&#xff0c;今天我们正式开始写代码。 入门新的开发语言往往从Hello World开始&#xff0c;Uniapp的初始化项目中已经写好了一个简单的demo&#xff0c;这里就不再赘述…

JavaSE核心知识点02面向对象编程02-08(异常处理)

&#x1f91f;致敬读者 &#x1f7e9;感谢阅读&#x1f7e6;笑口常开&#x1f7ea;生日快乐⬛早点睡觉 &#x1f4d8;博主相关 &#x1f7e7;博主信息&#x1f7e8;博客首页&#x1f7eb;专栏推荐&#x1f7e5;活动信息 文章目录 JavaSE核心知识点02面向对象编程02-08&#…

【JVM-GC调优】

一、预备知识 掌握GC相关的VM参数&#xff0c;会基本的空间调整掌握相关工具明白一点&#xff1a;调优跟应用、环境有关&#xff0c;没有放之四海而皆准的法则 二、调优领域 内存锁竞争cpu占用io 三、确定目标 【低延迟】&#xff1a;CMS、G1&#xff08;低延迟、高吞吐&a…

基于单片机的电子法频率计

一、电子计数法测频率原理 通过门控控制闸门开关&#xff0c;闸门时间T自己设定&#xff0c;计数器计数脉冲个数N&#xff08;也就是待测信号&#xff09;&#xff0c;N个脉冲的时间间隔为δt,倒数即为信号的频率f,由此 δtT/N fN/T——信号频率 根据公式&#xff0c;如果考虑…

【C/C++】跟我一起学_C++同步机制效率对比与优化策略

文章目录 C同步机制效率对比与优化策略1 效率对比2 核心同步机制详解与适用场景3 性能优化建议4 场景对比表5 总结 C同步机制效率对比与优化策略 多线程编程中&#xff0c;同步机制的选择直接影响程序性能与资源利用率。 主流同步方式: 互斥锁原子操作读写锁条件变量无锁数据…

判断两台设备是否在同一局域网内的具体方法

以下是判断两台设备是否在同一局域网内的具体方法&#xff1a; 1. 检查IP地址和子网掩码 操作步骤&#xff1a; Windows系统&#xff1a; 按 Win R 键&#xff0c;输入 cmd 并回车。输入 ipconfig&#xff0c;查看 IPv4 地址 和 子网掩码&#xff08;如 192.168.1.5/255.255.2…

在R语言中如何将列的名字改成别的

在 R 中&#xff0c;更改数据框&#xff08;data frame&#xff09;中列的名字可以通过多种方法实现。以下是几种常见的方法&#xff1a; 方法 1&#xff1a;使用 names() 函数 names() 函数可以获取或设置数据框的列名。 示例 假设我们有一个数据框 data&#xff1a; dat…

JUC并发编程(上)

一、JUC学习准备 核心知识点&#xff1a;进程、线程、并发&#xff08;共享模型、非共享模型&#xff09;、并行 预备知识&#xff1a; 基于JDK8,对函数式编程、lambda有一定了解 采用了slf4j打印日志 采用了lombok简化java bean编写 二、进程与线程 进程和线程概念 两者对比…

单地平面6层PCB设计实战:如何兼顾电源与信号完整性?

摘要&#xff1a;面对复杂系统&#xff08;SDRAM、WiFi、电机驱动等&#xff09;且仅有1层地平面的6层板设计挑战&#xff0c;本文从层叠规划、电源噪声抑制、高速信号处理等角度&#xff0c;总结可落地的设计技巧与避坑指南。 一、层叠设计&#xff1a;6层板如何“挤”出最优布…

spark:map 和 flatMap 的区别(Scala)

场景设定 假设有一个包含句子的 RDD&#xff1a; scala val rdd sc.parallelize(List("Hello World", "Hi Spark")) 目标是&#xff1a;将每个句子拆分成单词。 1. 用 map 的效果 代码示例 scala val resultMap rdd.map(sentence > sentence…

基于VSCode+PlatformIO环境的ESP8266的HX1838红外模块

以下是针对ESP8266开发板的红外遥控解码系统开发教程&#xff0c;基于VSCodePlatformIO环境编写 一、概述 本实验通过ESP8266开发板实现&#xff1a; 红外遥控信号解码自定义按键功能映射串口监控输出基础设备控制&#xff08;LED&#xff09; 硬件组成&#xff1a; NodeMC…

Kubernetes排错(十四):Pod状态异常排查手册

当你在凌晨三点收到告警&#xff0c;发现Pod在崩溃循环中挣扎时&#xff0c;如何快速定位问题&#xff1f;本文将为你梳理一套生产环境通用的Pod排错流程&#xff0c;并附上救火队员必备的实用命令清单&#xff01; 一、5分钟快速定位&#xff1a;四步锁定问题方向 步骤1&…

医院药品管理系统(准备工作)

准备工作 创建数据库表 搭建Springboot框架 创建工程 定位maven 其他准备工作 创建数据库表 建了九张表 搭建Springboot框架 创建工程 定位maven 把镜像改为国内的 其他准备工作 安装Lombok插件 额外添加依赖 如果添加依赖的过程中一直爆红&#xff0c;可以刷新…

SpringBoot异步处理@Async深度解析:从基础到高阶实战

一、异步编程基础概念 1.1 同步 vs 异步 特性同步异步执行方式顺序执行&#xff0c;阻塞调用非阻塞&#xff0c;调用后立即返回线程使用单线程完成所有任务多线程并行处理响应性较差&#xff0c;需等待前任务完成较好&#xff0c;可立即响应新请求复杂度简单直观较复杂&#…

简单的强化学习举例

1&#xff0c;定义奖励函数 首先&#xff0c;需要根据具体的任务需求来定义奖励函数。例如&#xff0c;对于机器人导航任务&#xff0c;可以根据机器人与目标点的距离来定义奖励函数&#xff1a; import numpy as npdef navigation_reward(robot_position, target_position):…

css背景相关

背景书写 background: url(src); // 注意&#xff1a;在写动态样式时&#xff0c;backgournd赋值格式错误&#xff0c;是不会在浏览器dom的style上显示的 // 但是可以创建不可见的img&#xff0c;预加载来提高性能背景也会加载图片资源 同img的src一样&#xff0c;background也…