当前位置: 首页 > news >正文

速通Python 第四节——函数

一、函数

编程中的函数和数学中的函数有一定的相似之处. 数学上的函数, 比如 y = sin x , x 取不同的值, y 就会得到不同的结果. 编程中的函数, 是一段 可以被重复使用的代码片段
代码示例 : 求一段范围的数的和 , 不使用函数
# 1. 求 1 - 100 的和
sum = 0
for i in range(1, 101):sum += i
print(sum)
# 2. 求 100 - 400 的和
sum = 0
for i in range(100, 401):sum += i
print(sum)
# 3. 求 1 - 1000 的和
sum = 0
for i in range(1, 1001):sum += i
print(sum)
可以发现 , 这几组代码基本是相似的 , 只有一点点差异 . 可以把重复代码提取出来 , 做成一个函数
在实际开发中, 复制粘贴是一种不太好的策略. 实际开发的重复代码可能存在几十份甚至上百份.
一旦这个重复代码需要被修改, 那就得改多次
因此我们可以定义一个函数来解决这些问题
def calcSum(beg, end):sum = 0for i in range(beg, end + 1):sum += iprint(sum)

因此上面的代码最终就是

def calcSum(beg, end):sum = 0for i in range(beg, end + 1):sum += iprint(sum)sum(1, 100)
sum(100, 400)
sum(1, 1000)

1.语法格式

创建函数/定义函数

def 函数名(形参列表):函数体return 返回值
调用函数 / 使用函数
函数名(实参列表)           // 不考虑返回值
返回值 = 函数名(实参列表)   // 考虑返回值
函数定义并不会执行函数体内容 , 必须要调用才会执行 . 调用几次就会执行几次
def test1():print('hello')
如果光是定义函数, 而不调用, 则不会执行
函数必须先定义,在使用
如果还没有执行到定义, 就先执行调用了, 此时就会报错.
例如:
test1()          # 还没有执行到定义, 就先执行调用了, 此时就会报错. 
def test1():print('hello')

2.函数参数

在函数定义的时候 , 可以在 ( ) 中指定 " 形式参数 " ( 简称 形参 ), 然后在调用的时候 , 由调用者把 " 实际参数 " (简称 实参 ) 传递进去 .
这样就可以做到一份函数 , 针对不同的数据进行计算处理
参考前面的代码案例 :
def calcSum(beg, end):sum = 0for i in range(beg, end + 1):sum += iprint(sum)sum(1, 100)
sum(100, 400)
sum(1, 1000)
上面的代码中 , beg, end 就是函数的形参 . 1, 100 / 100, 400 就是函数的实参 .
在执行 sum(1, 100) 的时候, 就相当于 beg = 1, end = 100 , 然后在函数内部就可以针对 1-
100 进行运算.
在执行 sum(300, 400) 的时候, 就相当于 beg = 100, end = 400 , 然后在函数内部就可以针对
100-400 进行运算.
注意 :
一个函数可以有一个形参 , 也可以有多个形参 , 也可以没有形参 .
一个函数的形参有几个 , 那么传递实参的时候也得传几个 . 保证个数要匹配 .
def test(a, b, c):print(a, b, c)
test(10)

C++ / Java 不同 , Python 是动态类型的编程语言 , 函数的形参不必指定参数类型 . 换句话说 , 一个
函数可以支持多种不同类型的参数 .
def test(a, b, c):print(a, b, c)
test(10)
def test(a):print(a)
test(10)
test('hello')
test(True)

3.函数返回值

函数的参数可以视为是函数的 " 输入 ", 则函数的返回值 , 就可以视为是函数的 " 输出 "
下面的代码:
def calcSum(beg, end):sum = 0for i in range(beg, end + 1):sum += iprint(sum)calc(1, 100)
可以转换成
def calcSum(beg, end):sum = 0for i in range(beg, end + 1):sum += ireturn sum
result = calcSum(1, 100)
print(result)
这两个代码的区别就在于 , 前者直接在函数内部进行了打印 , 后者则使用 return 语句把结果返回给函数调用者, 再由调用者负责打印
我们一般倾向于第二种写法.实际开发中我们的一个通常的编程原则, 是 "逻辑和用户交互分离". 而第一种写法的函数中, 既包含了计算逻辑, 又包含了和用户交互(打印到控制台上). 这种写法是不太好的, 如果后续我们需要的是把计算结果保存到文件中, 或者通过网络发送, 或者展示到图形化界面里, 那么第一种写法的函数,就难以胜任了,第二种写法则专注于做计算逻辑, 不负责和用户交互. 那么就很容易把这个逻辑搭配不同的用户交互代码, 来实现不同的效果。

1)一个函数中可以有多个 return 语句

例如:
# 判定是否是奇数
def isOdd(num):if num % 2 == 0:return Falseelse:return Trueresult = isOdd(10)
print(result)
执行到 return 语句, 函数就会立即执行结束, 回到调用位置如果 num 是偶数, 则进入 if 之后, 就会触发 return False , 也就不会继续执行 return True

2)一个函数是可以一次返回多个返回值的. 使用 , 来分割多个返回值

例如:

def getPoint():x = 10y = 20return x, y
a, b = getPoint()

3)如果只想关注其中的部分返回值, 可以使用 _ 来忽略不想要的返回值

def getPoint():x = 10y = 20return x, y
_, b = getPoint()

4.变量作用域

def getPoint():x = 10y = 20return x, y
x, y = getPoint()
在这个代码中 , 函数内部存在 x, y, 函数外部也有 x, y.
但是这两组 x, y 不是相同的变量 , 而只是恰好有一样的名字

1)变量只能在所在的函数内部生效.

在函数 内部定义的 x, y 只是在函数内部生效 . 一旦出了函数的范围 , 这两个变量就不再生
效了 .
def getPoint():x = 10y = 20return x, y
getPoint()
print(x, y)

2)在不同的作用域中, 允许存在同名的变量

虽然名字相同 , 实际上是不同的变量
x = 20
def test():x = 10print(f'函数内部 x = {x}')
test()
print(f'函数外部 x = {x}')

注意 :
  • 在函数内部的变量, 也称为 "局部变量"
  • 不在任何函数内部的变量, 也称为 "全局变量"

3)如果函数内部尝试访问的变量在局部不存在, 就会尝试去全局作用域中查找

x = 20
def test():print(f'x = {x}')
test()

4)如果是想在函数内部, 修改全局变量的值, 需要使用 global 关键字声明

x = 20
def test():global xx = 10print(f'函数内部 x = {x}')
test()
print(f'函数外部 x = {x}')

如果此处没有 global , 则函数内部的 x = 10 就会被视为是创建一个局部变量 x, 这样就和全局
变量 x 不相关了

5)if / while / for 等语句块不会影响到变量作用域

换而言之, if / while / for 中定义的变量, 在语句外面也可以正常使用

for i in range(1, 10):print(f'函数内部 i = {i}')
print(f'函数外部 i = {i}')

5.函数执行过程

  • 调用函数才会执行函数体代码. 不调用则不会执行.
  • 函数体执行结束(或者遇到 return 语句), 则回到函数调用位置, 继续往下执行.
def test():print("执行函数内部代码")print("执行函数内部代码")print("执行函数内部代码")
print("1111")
test()
print("2222")
test()
print("3333")

6.链式调用

前面的代码很多都是写作

def isOdd(num):if num % 2 == 0:return Falseelse:return Trueresult = isOdd(10)
print(result)

打印那边实际上也可以简化写作

print(isOdd(10))
把一个函数的返回值 , 作为另一个函数的参数 , 这种操作称为 链式调用

7.嵌套调用

函数内部还可以调用其他的函数, 这个动作称为 "嵌套调用"

def test():print("执行函数内部代码")print("执行函数内部代码")print("执行函数内部代码")
test 函数内部调用了 print 函数 , 这里就属于嵌套调用

1)test 函数内部调用了 print 函数, 这里就属于嵌套调用

函数嵌套的过程是非常灵活的
def a():print("函数 a")
def b():print("函数 b")a()
def c():print("函数 c")b()
def d():print("函数 d")c()
d()

如果把代码稍微调整 , 打印结果则可能发生很大变化 .
例如:
def a():print("函数 a")
def b():a()print("函数 b")
def c():b()print("函数 c")
def d():c()print("函数 d")
d()

函数之间的调用关系 , Python 中会使用一个特定的数据结构来表示 , 称为 函数调用栈 . 每次函数调用 ,都会在调用栈里新增一个元素, 称为 栈帧 .

2)每个函数的局部变量, 都包含在自己的栈帧中

def a():num1 = 10print("函数 a")
def b():num2 = 20a()print("函数 b")
def c():num3 = 30b()print("函数 c")
def d():num4 = 40c()print("函数 d")
d()

选择不同的栈帧 , 就可以看到各自栈帧中的局部变量 .

8.函数递归

递归是 嵌套调用 中的一种特殊情况, 即一个函数嵌套调用自己.

举个例子,我们通过递归求5!

def factor(n):if n == 1:return 1return n * factor(n - 1)
result = factor(5)
print(result)

上述代码中, 就属于典型的递归操作. factor 函数内部, 又调用了 factor 自身

注意:

  • 存在递归结束条件. 比如 if n == 1 就是结束条件. n 1 的时候, 递归就结束了.
  • 每次递归的时候, 要保证函数的实参是逐渐逼近结束条件的

如果上述条件不能满足, 就会出现 "无限递归" . 这是一种典型的代码错误

递归的优点
  • 递归类似于 "数学归纳法" , 明确初始条件, 和递推公式, 就可以解决一系列的问题.
  • 递归代码往往代码量非常少.

递归的缺点
  • 递归代码往往难以理解, 很容易超出掌控范围
  • 递归代码容易出现栈溢出的情况
  • 递归代码往往可以转换成等价的循环代码. 并且通常来说循环版本的代码执行效率要略高于递归版

9.参数默认值

Python 中的函数, 可以给形参指定默认值.,带有默认值的参数, 可以在调用的时候不传参.

代码示例:计算两个数字的和

def add(x, y, debug=False):if debug:print(f'调试信息: x={x}, y={y}')return x + y
print(add(10, 20))
print(add(10, 20, True))
此处 debug=False 即为参数默认值 . 当我们不指定第三个参数的时候 , 默认 debug 的取值即为 False
注意:带有默认值的参数需要放到没有默认值的参数的后面

10.关键字参数

在调用函数的时候, 需要给函数指定实参. 一般默认情况下是按照形参的顺序, 来依次传递实参的. 但是我们也可以通过 关键字参数, 来调整这里的传参顺序, 显式指定当前实参传递给哪个形参.

def test(x, y):print(f'x = {x}')print(f'y = {y}')
test(x=10, y=20)
test(y=100, x=200)

形如上述 test(x=10, y=20) 这样的操作 , 即为 关键字参数 .

相关文章:

速通Python 第四节——函数

一、函数 编程中的函数和数学中的函数有一定的相似之处. 数学上的函数, 比如 y sin x , x 取不同的值, y 就会得到不同的结果. 编程中的函数, 是一段 可以被重复使用的代码片段 代码示例 : 求一段范围的数的和 , 不使用函数 # 1. 求 1 - 100 的和 sum 0 for i in range(1, …...

如何在Windows系统上安装和配置Maven

Maven是一个强大的构建和项目管理工具,广泛应用于Java项目的自动化构建、依赖管理、项目构建生命周期控制等方面。在Windows系统上安装Maven并配置环境变量,是开发者开始使用Maven的第一步。本文将详细介绍如何在Windows系统上安装和配置Maven&#xff0…...

STM32之GPIO输出与输出

欢迎来到 破晓的历程的 博客 ⛺️不负时光,不负己✈️ 文章目录 一.GPIO输入1.1GPIP简介1.2GPIO基本结构1.3GPIO位结构1.4GPIO的八种模式1.4.1浮空/上拉/下拉输入1.4.2 模拟输入1.4.3 推挽输出\开漏输出 二.GPIO输入2.1.按键介绍2.2传感器模块介绍2.3按键电路 一.G…...

linux定时器操作

目录 1 简单示例2 timer_create方式2.1 SIGEV_SIGNAL信号方式通知2.2 SIGEV_THREAD启动线程方式通知2.3 参数 1 简单示例 #include <stdio.h> #include <stdlib.h> #include <sys/time.h> #include <signal.h> #include <unistd.h>void setup_t…...

重拾设计模式--观察者模式

文章目录 观察者模式&#xff08;Observer Pattern&#xff09;概述观察者模式UML图作用&#xff1a;实现对象间的解耦支持一对多的依赖关系易于维护和扩展 观察者模式的结构抽象主题&#xff08;Subject&#xff09;&#xff1a;具体主题&#xff08;Concrete Subject&#xf…...

Vue.js前端框架教程7:Vue计算属性和moment.js

文章目录 计算属性(Computed Properties)基本用法缓存机制计算属性 vs 方法使用场景计算属性的 setter 和 getter结论Moment.js 进行时间处理1. 安装 Moment.js2. 在 Vue 组件中引入 Moment.js3. 在全局使用 Moment.js4. 使用 Vue 插件的方式引入 Moment.js5. 常用日期格式化…...

【游戏设计原理】22 - 石头剪刀布

一、游戏基础&#xff1a;拳头、掌心、分指 首先&#xff0c;石头剪刀布&#xff08;又名“Roshambo”&#xff09;看似简单&#xff0c;实际上可是个“深藏玄机”的零和博弈&#xff08;听起来很高深&#xff0c;其实就是输赢相抵消的意思&#xff09;。游戏中有三种手势&…...

3-Gin 渲染 --[Gin 框架入门精讲与实战案例]

在 Gin 框架中&#xff0c;渲染指的是将数据传递给模板&#xff0c;并生成 HTML 或其他格式的响应内容。Gin 支持多种类型的渲染&#xff0c;包括 String HTML、JSON、XML 等。 String 渲染 在 Gin 框架中&#xff0c;String 渲染方法允许你直接返回一个字符串作为 HTTP 响应…...

python小课堂(一)

基础语法 1 常量和表达式2 变量和类型2.1 变量是什么2.2 变量语法 3 变量的类型3.1 动态类型特性 4 注释4.1注释是什么 5 输入输出5.1 print的介绍5.2 input 6 运算符6.1 算术运算符在这里插入图片描述6.2 关系运算符6.3 逻辑运算符6.4赋值运算符 1 常量和表达式 在print()中可…...

GESP202309 二级【小杨的 X 字矩阵】题解(AC)

》》》点我查看「视频」详解》》》 [GESP202309 二级] 小杨的 X 字矩阵 题目描述 小杨想要构造一个 的 X 字矩阵&#xff08; 为奇数&#xff09;&#xff0c;这个矩阵的两条对角线都是半角加号 &#xff0c;其余都是半角减号 - 。例如&#xff0c;一个 5 5 5 \times 5 5…...

@PostConstruct注解解释!!!!

PostConstruct 注解修饰的方法是在 Bean 完成初始化后自动调用的。它是 Java EE 和 Spring 中的一种机制&#xff0c;用于在 Bean 被创建并依赖注入完成后&#xff0c;执行一些初始化的操作。 具体触发时机&#xff1a; 依赖注入完成后&#xff1a;首先&#xff0c;Spring 容器…...

laya游戏引擎中打包之后图片模糊

如下图正常运行没问题&#xff0c;打包之后却模糊 纹理类型中的默认类型都是精灵纹理&#xff0c;改为默认值即可。注意&#xff1a;要点击“应用”才可有效。精灵纹理类型会对图片进行渲染处理&#xff0c;而默认值 平面类型不会处理图片。...

【数据结构练习题】链表与LinkedList

顺序表与链表LinkedList 选择题链表面试题1. 删除链表中等于给定值 val 的所有节点。2. 反转一个单链表。3. 给定一个带有头结点 head 的非空单链表&#xff0c;返回链表的中间结点。如果有两个中间结点&#xff0c;则返回第二个中间结点。4. 输入一个链表&#xff0c;输出该链…...

[项目代码] YOLOv8 遥感航拍飞机和船舶识别 [目标检测]

项目代码下载链接 &#xff1c;项目代码&#xff1e;YOLO 遥感航拍飞机和船舶识别&#xff1c;目标检测&#xff1e;https://download.csdn.net/download/qq_53332949/90163939YOLOv8是一种单阶段&#xff08;one-stage&#xff09;检测算法&#xff0c;它将目标检测问题转化为…...

移动魔百盒中的 OpenWrt作为旁路由 安装Tailscale并配置子网路由实现在外面通过家里的局域网ip访问内网设备

移动魔百盒中的 OpenWrt作为旁路由 安装Tailscale并配置子网路由实现在外面通过家里的局域网ip访问内网设备 一、前提条件 确保路由器硬件支持&#xff1a; OpenWrt 路由器需要足够的存储空间和 CPU 性能来运行 Tailscale。确保设备架构支持 Tailscale 二进制文件&#xff0c;例…...

JVM对象分配内存如何保证线程安全?

大家好&#xff0c;我是锋哥。今天分享关于【JVM对象分配内存如何保证线程安全&#xff1f;】面试题。希望对大家有帮助&#xff1b; JVM对象分配内存如何保证线程安全&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在JVM中&#xff0c;对象的内存分配…...

ArcGIS计算土地转移矩阵

在计算土地转移矩阵时&#xff0c;最常使用的方法就是在ArcGIS中将土地利用栅格数据转为矢量&#xff0c;然后采用叠加分析计算&#xff0c;但这种方法计算效率低。还有一种方法是采用ArcGIS中的栅格计算器&#xff0c;将一个年份的地类编号乘以个100或是1000再加上另一个年份的…...

数据库 MYSQL的概念

数据库的概念 数据库是按照数据结 构来组织、存储和管理数据的系统&#xff0c;它允许用户高效地存储、检索、更新和管理数据 database&#xff1a;用来组织&#xff0c;存储&#xff0c;管理数据的仓库 数据库的管理系统&#xff1a;DBMS&#xff0c;实现对数据的有效储值&am…...

Node.js后端程序打包问题汇总(webpack、rsbuild、fastify、knex、objection、sqlite3、svg-captcha)

背景说明 场景 使用 node.js 进行后端开发&#xff0c;部署时通常需要打包为单文件&#xff0c;然后放到服务器运行。 这里记录我在打包过程中&#xff0c;碰到的各类问题及解决方案&#xff0c;希望能够帮助到更多道友&#x1f604; 提示 此文持续更新&#xff0c;可以收藏⭐…...

部署 Apache Samza 和 Apache Kafka

部署 Apache Samza 和 Apache Kafka 的流处理系统可以分为以下几个步骤,涵盖环境准备、部署细节和生产环境的优化。 1. 环境准备 硬件要求 Kafka Broker:至少 3 台服务器,建议每台服务器配备 4 核 CPU、16GB 内存和高速磁盘。Samza 部署节点:根据任务规模,至少准备 2 台…...

Chapter03-Authentication vulnerabilities

文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...

Leetcode 3577. Count the Number of Computer Unlocking Permutations

Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接&#xff1a;3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯&#xff0c;要想要能够将所有的电脑解锁&#x…...

2.Vue编写一个app

1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...

基于数字孪生的水厂可视化平台建设:架构与实践

分享大纲&#xff1a; 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年&#xff0c;数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段&#xff0c;基于数字孪生的水厂可视化平台的…...

P3 QT项目----记事本(3.8)

3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...

Linux-07 ubuntu 的 chrome 启动不了

文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了&#xff0c;报错如下四、启动不了&#xff0c;解决如下 总结 问题原因 在应用中可以看到chrome&#xff0c;但是打不开(说明&#xff1a;原来的ubuntu系统出问题了&#xff0c;这个是备用的硬盘&a…...

精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南

精益数据分析&#xff08;97/126&#xff09;&#xff1a;邮件营销与用户参与度的关键指标优化指南 在数字化营销时代&#xff0c;邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天&#xff0c;我们将深入解析邮件打开率、网站可用性、页面参与时…...

C# 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

【JavaSE】多线程基础学习笔记

多线程基础 -线程相关概念 程序&#xff08;Program&#xff09; 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序&#xff0c;比如我们使用QQ&#xff0c;就启动了一个进程&#xff0c;操作系统就会为该进程分配内存…...

接口自动化测试:HttpRunner基础

相关文档 HttpRunner V3.x中文文档 HttpRunner 用户指南 使用HttpRunner 3.x实现接口自动化测试 HttpRunner介绍 HttpRunner 是一个开源的 API 测试工具&#xff0c;支持 HTTP(S)/HTTP2/WebSocket/RPC 等网络协议&#xff0c;涵盖接口测试、性能测试、数字体验监测等测试类型…...