【python - 函数】

一、纯函数和非纯函数

纯函数(Pure functions):函数有一些输入(参数)并返回一些输出(调用返回结果)。

>>> abs(-2)
2

可以将内置函数 abs 描述为接受输入并产生输出的小型机器。

function_abs

abs  就是纯函数,纯函数在调用时除了返回值外不会造成其他任何影响,而且在使用相同的参数调用纯函数时总是会返回相同的值。

非纯函数(Non-pure functions):除了返回值外,调用一个非纯函数还会产生其他改变解释器和计算机的状态的副作用(side effect)。一个常见的副作用就是使用 print 函数产生(非返回值的)额外输出。

 我们在python解释器上键入-2和用print(-2)打印出的结果是一样的,输入字符串也会得到同样的结果,这是为什么呢?

而我们通过两种方式打印None会有不同的效果,因为python有自动显示键入的任何表达式的规则,None是特殊的,但是我们可以用print(None)来让它出现。

我们还可以打印多个用空格分割的值。

>>> print(1, 2, 3)
1 2 3

虽然  print  和  abs  在这些例子中看起来很相似,但它们的工作方式基本不同。print 返回的值始终为 None,这是一个不代表任何内容的特殊 Python 值。而交互式 Python 解释器并不会自动打印 None 值,所以 print 函数的额外输出就是它的副作用。

function_print

下面这个调用 print 的嵌套表达式就展示了非纯函数的特征。

>>> print(print(1), print(2))
1
2
None None

如果你发现这个输出结果出乎你的意料,可以画一个表达式树来解释求解该表达式会产生特殊输出的原因。

小心使用  print 函数!它返回 None  意味着它不应该用于赋值语句。

>>> two = print(2)
2
>>> print(two)
None

纯函数不能有副作用,或是随着时间推移的改变的限制,但是对其施加这些限制会产生巨大的好处。首先,纯函数可以更可靠地组成复合调用表达式。在上面的示例中可以看到在操作数表达式中使用非纯函数  print  并不能返回有用的结果,但另一方面,我们已经看到  max, pow, sqrt  等函数可以在嵌套表达式中有效使用。

第二,纯函数往往更易于测试。相同的参数列表会返回相同的值,我们可以将其与预期的返回值进行比较。本章后面将更详细地讨论测试。

二、运算符

数学运算符(例如 + 和 -)为我们提供了组合方法的第一个示例,但我们尚未给包含这些运算符的表达式定义求值过程。

带有中缀运算符的 Python 表达式都有自己的求值过程,但你通常可以将它们视为调用表达式的简写形式。当你看到

>>> 2 + 3
5

可以认为简单地将它理解为以下代码

>>> add(2, 3)
5

中缀表示法可以嵌套,就像调用表达式一样。Python 运算符优先级采用了正常数学规则,它规定了如何求解具有多个运算符的复合表达式。

>>> 2 + 3 * 4 + 5
19

它和以下表达式的求解结果完全相同

>>> add(add(2, mul(3, 4)), 5)
19

调用表达式中的嵌套比运算符版本更加明显,但也更难以阅读。Python 还允许使用括号对子表达式进行分组,用以覆盖正常的优先级规则,或使表达式的嵌套结构更加明显。

>>> (2 + 3) * (4 + 5)
45

它和以下表达式的求解结果完全相同

>>> mul(add(2, 3), add(4, 5))
45

对于除法,Python 提供了两个中缀运算符:/ 和 //。前者是常规除法,因此即使除数可以整除被除数,它也会产生 浮点数(十进制小数):

>>> 5 / 4
1.25
>>> 8 / 4
2.0

而后一个运算符 // 会将结果向下舍入到一个整数:

>>> 5 // 4
1
>>> -5 // 4
-2

这两个运算符算是 truediv 和 floordiv 函数的简写。

>>> from operator import truediv, floordiv
>>> truediv(5, 4)
1.25
>>> floordiv(5, 4)
1

你可以在程序中随意使用中缀运算符和圆括号。对于简单的数学运算,Python 惯例上更喜欢使用运算符而不是调用表达式。

python还可以从一个函数中返回多个值。假设我们想要商和余数。

我们还可以将python代码写入文件中便于永久保存。我们用VScode演示。

或者我们可以不在代码中写输出语句,而在交互式python中运行来看我们的输出。

三、文档

函数定义通常包括描述函数的文档,称为“文档字符串 docstring”,它必须在函数体中缩进。文档字符串通常使用三个引号,第一行描述函数的任务,随后的几行可以描述参数并解释函数的意图:

>>> def pressure(v, t, n):"""计算理想气体的压力,单位为帕斯卡使用理想气体定律:http://en.wikipedia.org/wiki/Ideal_gas_lawv -- 气体体积,单位为立方米t -- 绝对温度,单位为开尔文n -- 气体粒子"""k = 1.38e-23  # 玻尔兹曼常数return n * k * t / v

当你使用函数名称作为参数调用 help 时,你会看到它的文档字符串(键入 q 以退出 Python help)。

>>> help(pressure)

编写 Python 程序时,除了最简单的函数之外,都要包含文档字符串。要记住,虽然代码只编写一次,但是会在之后阅读多次。Python 文档包含了 文档字符串准则,它会在不同的 Python 项目中保持一致。

注释:Python 中的注释可以附加到 # 号后的行尾。例如,上面代码中的注释 玻尔兹曼常数 描述了 k 变量的含义。这些注释不会出现在 Python 的 help 中,而且会被解释器忽略,它们只为人类而存在。

四、参数默认值

定义通用函数的结果是引入了额外的参数。具有许多参数的函数可能调用起来很麻烦并且难以阅读。

在 Python 中,我们可以为函数的参数提供默认值。当调用该函数时,具有默认值的参数是可选的。如果未提供,则将默认值绑定到形参上。例如,如果程序通常用于计算“一摩尔”粒子的压力,则可以提供此值作为默认值:

>>> def pressure(v, t, n=6.022e23):"""计算理想气体的压力,单位为帕斯卡使用理想气体定律:http://en.wikipedia.org/wiki/Ideal_gas_lawv -- 气体体积,单位为立方米t -- 绝对温度,单位为开尔文n -- 气体粒子,默认为一摩尔"""k = 1.38e-23  # 玻尔兹曼常数return n * k * t / v

= 符号在此示例中表示两种不同的含义,具体取决于使用它的上下文。在 def 语句中,= 不执行赋值,而是指示调用 pressure 函数时使用的默认值。相比之下,函数体中对 k 的赋值语句中将名称 k 与玻尔兹曼常数的近似值进行了绑定。

>>> pressure(1, 273.15)
2269.974834
>>> pressure(1, 273.15, 3 * 6.022e23)
6809.924502

pressure 函数的定义接收三个参数,但上面的第一个调用表达式中只提供了两个。在这种情况下,n 的值取自 def 语句中的默认值。如果提供了第三个参数,默认值将被忽略。

作为准则,函数主体中使用的大多数数据值都应该表示为具名参数(named arguments)的默认值,这样会使它们更易于检查,并且可以被函数调用者更改。一些永远不会改变的值,例如基本常量 k 可以绑定在函数体或全局帧中。

五、控制

5.1、语句

到目前为止,我们虽然主要思考的是如何计算求解表达式,但我们已经见过了三种语句:赋值(assignment)、 def 和 return 语句。尽管这些 Python 代码都包含表达式作为它们的一部分,但它们本身并不是表达式。

语句不会被求解,而会被执行。每个语句都描述了对解释器状态的一些更改,并且执行语句就会应用该更改。正如我们在 return 和赋值语句中看到的那样,执行语句可能涉及求解其包含的子表达式。

表达式也可以作为语句执行,在这种情况下,它们会被求值,但它们的值会被丢弃。执行纯函数没有效果,但执行非纯函数会因为调用函数而产生效果。

思考一下,例如:

>>> def square(x):mul(x, x) # 小心!此调用不返回值。

这个例子是有效的 Python 代码,但可能不能达到预期。函数体由一个表达式组成。表达式本身是一个有效的语句,但语句的效果是调用 mul 函数,然后把结果丢弃。如果你想对表达式的结果做些什么,你需要用赋值语句存储它或用 return 语句返回它:

>>> def square(x):return mul(x, x)

有时,在调用 print 等非纯函数时,拥有一个主体为表达式的函数确实有意义。

>>> def print_square(x):print(square(x))

在最高层级上,Python 解释器的工作是执行由语句组成的程序。然而,很多有趣的计算工作都来自对表达式的求值。语句用来管理程序中不同表达式之间的关系,以及它们产生的结果。

5.2、复合语句

通常,Python 代码是一系列语句。简单语句是不以冒号结尾的单行,而由其他语句(简单语句和复合语句)组成被称为复合语句。复合语句通常跨越多行,以单行头部(header)开始,并以冒号结尾,其中冒号标识语句的类型。头部和缩进的句体(suite)一起称为子句。复合语句由一个或多个子句组成:

<header>:<statement><statement>...
<separating header>:<statement><statement>...
...

我们可以用这些术语来理解我们之前介绍过的语句。

  • 表达式、返回语句和赋值语句都是简单语句。
  • def 语句是复合语句,def 头后面的句体定义了函数体。

对每类 header 都有专门的求值规则来规定其何时执行以及是否执行其句体中的语句。我们说“the header controls its suite”,例如,在 def 语句中,return 表达式不会立即求值,而是存储起来供以后调用该函数时使用。

我们现在也可以理解多行程序了。

  • 要执行一系列语句,会先执行第一个语句。如果该语句不重定向控制,则继续执行语句序列的其余部分(如果还有的话)。

这个定义揭示了递归定义序列(sequence)的基本结构:一个序列可以分解成它的第一个元素和其余元素。语句序列的“其余部分”本身也是语句序列!因此,我们可以递归地应用这个执行规则。这种将序列视为递归的数据结构的观点将在后面的章节中再次出现。

此规则的重要结论是语句会按顺序执行,但由于重定向控制(redirected control),后面的语句可能永远不会被执行到。

实践指南:缩进句体时,所有行必须以相同的方式缩进相同的量(使用空格,而不是制表符)。缩进的任何变化都会导致错误。

5.3、条件语句

Python 有一个用于计算绝对值的内置函数。

>>> abs(-2)
2

我们希望能够自己实现这样一个函数,但是没有清晰的方法来定义一个具有比较和选择的函数。我们想表达的是,如果 x 为正,则 abs(x) 返回 x ;此外,如果 x 为 0,则 abs(x) 返回 0;否则,abs(x) 返回 -x。在 Python 中,我们可以用条件语句来表达这种选择。

这个 absolute_value 函数的实现提出了几个重要的问题:

条件语句(Conditional statement):Python 中的条件语句由一系列头部和句体组成:必需的 if 子句、可选的 elif 子句序列,最后是可选的 else 子句:

if <expression>:<suite>
elif <expression>:<suite>
else:<suite>

执行条件语句时,每个子句都会按顺序被考虑。执行条件子句的计算过程如下。

  1. 求解头部的表达式
  2. 如果它是真值,则执行该句体。然后,跳过条件语句中的所有后续子句。

如果到达 else 子句(仅当所有 if 和 elif 表达式的计算结果为假值时才会发生),则执行其句体。

布尔上下文(Boolean contexts):上面,执行过程提到了“假值 a false value”和“真值 a true value”。条件块头部语句内的表达式被称为布尔上下文:它们值的真假对控制流很重要,另外,它们的值不会被赋值或返回。Python 包含多个假值,包括 0、 None 和布尔值 False,所有其他数字都是真值。在第二章中,我们将看到 Python 中的每种内置数据都具有真值和假值。

布尔值(Boolean values):Python 有两个布尔值,分别叫做 True 和 False 。布尔值表示逻辑表达式中的真值。内置的比较运算符 >, <, > =, <=, ==, != 会返回这些值。

>>> 4 < 2
False
>>> 5 >= 5
True

第二个例子读作“5 大于或等于 5”,对应于 operator 模块中的函数 ge

>>> 0 == -0
True

最后一个示例读作“0 等于 -0”,对应于 operator 模块中的 eq。请注意,Python 会区分赋值符号 = 与相等比较符号 ==,这也是许多编程语言共享的约定。

布尔运算符(Boolean operators):Python 中还内置了三个基本的逻辑运算符:

>>> True and False
False
>>> True or False
True
>>> not False
True

逻辑表达式具有相应的求值过程。而这些过程利用了这样一个理论 --> 有时,逻辑表达式的真值可以在不对其所有子表达式求值的情况下确定,这一特性称为短路(short-circuiting)。


求解表达式 <left> and <right> 的步骤如下:

  1. 求解子表达式  <left>
  2. 如果左边的结果为假值 v,则表达式的计算结果就是 v。
  3. 否则,表达式的计算结果为子表达式 <right> 的值。

求解表达式  <left> or <right> 的步骤如下:

  1. 求解子表达式  <left>
  2. 如果左边的结果为真值 v,则表达式的计算结果就是 v。
  3. 否则,表达式的计算结果为子表达式 <right> 的值。

求解表达式  not <exp> 的步骤如下:

  1. 求解  <exp>,如果结果为假值,则值为 True ,否则为 False

这些值、规则和运算符为我们提供了一种组合比较结果的方法。执行比较并返回布尔值的函数通常以 is 开头,后面不跟下划线(例如 isfinite, isdigit, isinstance 等)。

5.4、迭代

除了选择要执行的语句外,控制语句还用于重复。如果我们编写的每一行代码只执行一次,那么编程将是一项非常低效的工作。只有通过重复执行语句,我们才能释放计算机的全部潜力。我们之前已经见过了一种重复形式:一个函数只用定义一次,就可以被多次调用。迭代控制(Iterative control)结构是另一种多次执行相同语句的机制。

思考斐波那契数列,其中每个数都是前两个数的和:

0,1,1,2,3,5,8,13,21,⋯

每个值都是通过重复应用 sum-previous-two 的规则构建的,第一个和第二个值固定为 0 和 1。

我们可以使用 while 语句来枚举 n 项斐波那契数列。我们需要跟踪已经创建了多少个值(k),和第 k 个值(curr)及其前身(pred)。单步执行此函数并观察斐波那契数如何一个一个地演化,并绑定到 curr。

请记住,单行赋值语句可以用逗号分隔多个名称和值同时赋值。该行:

pred, curr = curr, pred + curr

将名称 pred 重新绑定到 curr 的值,同时将 curr 重新绑定到 pred + curr 的值。所有 = 右侧的所有表达式都会在绑定之前计算出来。

在更新左侧的绑定之前求出所有 = 右侧的内容 --> 这种事件顺序对于此函数的正确性至关重要。

while 子句包含一个头部表达式,后跟一个句体:

while <expression>:<suite>

要执行 while 子句:

  1. 求解头部的表达式。
  2. 如果是真值,则执行后面的句体,然后返回第 1 步。

在第 2 步中,while 子句的整个句体在再次计算头部表达式之前执行。

为了防止 while 子句的句体无限期地执行,句体应该总是在每次循环中更改一些绑定。

不会终止的 while 语句被称为无限循环(infinite loop)。按 <Control>-C 可以强制 Python 停止循环。

接下来我们可以用迭代来做一个小测试:求任意正整数的素数因式分解(分解质因数:每个正整数n都有一组素因子,正整数可以由它们的乘积表示,关键在于如何找到一组质数,将它们相乘得到该正整数) - 求n的最小素因子,除以它,再对n除以质因数得到的数再做一次。

我们还可以将代码修改一下,利用循环嵌套,在一个大循环里嵌套循环就可以运行我们的程序,或者说让我们的程序都在一个函数定义里运行。

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

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

相关文章

C# Onnx E2Pose人体关键点检测

C# Onnx E2Pose人体关键点检测 目录 效果 模型信息 项目 代码 下载 效果 模型信息 Inputs ------------------------- name&#xff1a;inputimg tensor&#xff1a;Float[1, 3, 512, 512] --------------------------------------------------------------- Outputs ---…

电商API商品数据采集接口||助力电商企业采集商品大数据提高开发效率

提高开发效率&#xff1a;电商API接口允许不同的应用程序之间高效地进行交互&#xff0c;节省了大量的人力物力成本&#xff0c;使得开发者可以将更多时间和精力集中于自身的核心业务。 增加数据安全性&#xff1a;通过对数据进行安全加密&#xff0c;API接口实现了对数据的保护…

JVM参数配置

JVM参数的三种表示方法 在jvm中&#xff0c;jvm虚拟机参数有以下三种表示方法&#xff1a; 标准参数&#xff08;-&#xff09;所有的JVM实现都必须实现这些参数的功能&#xff0c;而且向后兼容非标准参数&#xff08;-X&#xff09;&#xff0c;默认jvm实现这些参数的功能&…

罗永浩创业史!普通人也能逆袭!2024轻资产创业项目!2024普通人的出路! 2024普通人做什么行业赚钱!

罗永浩出身草根&#xff0c;一路打拼至今&#xff0c;虽然屡屡受挫但是从未妥协&#xff0c;罗永浩真正的诠释了什么叫“彪悍的人生不需要解释”&#xff01; 回顾罗永浩的传奇创业史: 1. 从新东方出来做牛博网--失败 2.创办老罗英语培训学校--失败 3.致敬乔布斯做锤子科技-…

写一个盲盒模拟器

最近想写一个小程序&#xff0c;随便写一个玩吧&#xff0c;先想了下功能&#xff1a; 1.有很多盲盒&#xff0c;可以选择模拟开启 2.自定义盲盒&#xff0c;我们可以自定义制作盲盒自己玩 3.用户界面&#xff0c;记录盲盒历史&#xff0c;可以给坏越提意见 所用技术栈&…

django 旅游服务系统-计算机毕业设计源码88939

摘 要 旅游服务系统采用采用django框架、python语言、以及Mysql数据库等技术。系统主要分为管理员和用户两部分&#xff0c;管理员管理主要功能包括&#xff1a;首页、轮播图&#xff08;轮播图管理&#xff09;、公告信息管理&#xff08;公告信息&#xff09;、资源管理&…

开源模型应用落地-LangSmith试炼-入门初体验-监控和自动化(五)

一、前言 在许多应用程序中&#xff0c;特别是在大型语言模型(LLM)应用程序中&#xff0c;收集用户反馈以了解应用程序在实际场景中的表现是非常重要的。 LangSmith可以轻松地将用户反馈附加到跟踪数据中。通常最好提供一个简单的机制(如赞成和反对按钮)来收集用户对应用程序响…

neo4j入门并使用案例说明

1、neo4j是什么 Neo4j是一个高性能的NoSQL图形数据库&#xff0c;它将结构化数据存储在网络&#xff08;在数学角度称为图&#xff09;上&#xff0c;而不是传统的表中。Neo4j是一个嵌入式的、基于磁盘的、具备完全的事务特性的Java持久化引擎。它因其高性能、轻量级、易嵌入和…

大模型时代的具身智能系列专题(九)

NYU Lerrel Pinto团队 Lerrel Pinto是NYU Courant的计算机科学助理教授&#xff0c;也是用机器人和人工智能实验室(CILVR小组)的一员。在加州大学伯克利分校读博士后&#xff0c;在CMU机器人研究所读博士&#xff0c;在印度理工学院古瓦哈蒂读本科。研究目标是让机器人在我们生…

Linux 35.5 + JetPack v5.1.3@FUEL编译安装

Linux 35.5 JetPack v5.1.3FUEL编译安装 1. 源由2. 编译&安装Step 1&#xff1a;依赖库安装Step 2&#xff1a;建立工程Step 3&#xff1a;编译工程Step 4&#xff1a;安装工程 3. 问题汇总3.1 fuel_planner/exploration_manager - dw3.2 fuel_planner/plan_env - OpenCV库…

找不到d3dx9_43.dll怎么修复?这个几种修复方法轻松解决

在计算机使用过程中&#xff0c;我们常常会遇到一些错误提示&#xff0c;其中之一就是“d3dx943.dll丢失”。这个问题通常会导致某些游戏或应用程序无法正常运行。为了解决这个问题&#xff0c;我总结出了以下五种解决方法&#xff0c;希望能对遇到类似问题的朋友们有所帮助。 …

QNX 7.0.0开发总结

1 QNX编译 1.1 基本概念 QNX可以直接使用Linux Makefile编译库和二进制&#xff0c;在Makefile文件中指定CCaarch64-unknown-nto-qnx7.0.0-g&#xff0c;或者CCx86_64-pc-nto-qnx7.0.0-g&#xff0c;保存退出后&#xff0c;运行source /qnx_sdk_path/qnxsdp-env.sh&#xff0c;…

前端canvas绘图,利用canvas在图片上面绘制标记以及给canvas添加点击事件。

前端canvas绘图&#xff0c;利用canvas在图片上面绘制标记以及给canvas添加点击事件。 需要实现的效果如下图: 首先需要一个承载的核心画布 <canvas id"canvas" width"800" height"600"></canvas>全部代码&#xff1a; <!DOCT…

LabVIEW减压阀和温控阀综合测试系统

在使用LabVIEW开发阀门测试软件时&#xff0c;特别是针对减压阀和温控阀&#xff0c;测试内容和注意事项包括以下方面&#xff1a; 测试内容 压力测试&#xff1a; 入口压力&#xff1a;测量阀门在不同入口压力下的表现。 出口压力&#xff1a;确保减压阀能够将出口压力控制在…

systemctlm-cosim-demo项目分析

概述 systemctlm-cosim-demo项目是Xilinx的systemc库的demo工程。 环境安装 qemu安装 cd xilinx_proj/Downloads git clone https://github.com/Xilinx/qemu.git cd qemu git checkout 74d70f8008# Configure and build # zynq7000 # ./configure --target-list"arm-s…

【乐吾乐3D可视化组态编辑器】用开关控制巡检车和路灯

一、运动设备开关控制 3D组态编辑器地址&#xff1a;3D可视化组态 - 乐吾乐Le5le 1.在场景中新建模拟运动设备及控制面板&#xff1a;启动/停止 2.单击巡检车设备新建模拟动画 3.设置模拟动画属性 4.单击启动面板&#xff0c;新建交互事件 5.设置交互触发类型&#xff0c;新建…

PS系统教程11

HUD拾色器 作用&#xff1a;它可以帮助使用者更加高效地选择和使用颜色&#xff0c;从而提高工作效率和设计质量。 先确定色相值改变饱和度改变亮度使用HUD拾色器选中画笔工具画笔模式-正常shiftAlt右键 色相轮 上下移动从黑到白亮度变化左右移动从浅到深饱和度的变化选中颜…

数据分析必备:一步步教你如何用Pandas做数据分析(17)

1、Pandas 连接 Pandas 连接的操作实例 Pandas具有与SQL等关系数据库非常相似的功能齐全的高性能内存中连接操作。 Pandas提供单个功能merge作为DataFrame对象之间所有标准数据库联接操作的入口点 pd.merge(left, right, howinner, onNone, left_onNone, right_onNone,left_i…

新手必看!现货伦敦金新手容易犯的两个错

对很多刚进入现货伦敦金市场的朋友来说&#xff0c;炒伦敦金是十分令人兴奋的&#xff0c;但兴奋归兴奋&#xff0c;我们还是要注意&#xff0c;由于现货伦敦金投资者过分的热情&#xff0c;很容易让自己跌入一些陷阱&#xff0c;犯下一些错误&#xff0c;下面我们就来介绍两个…

智能楼宇安防3D数据可视化平台满足日益增长的安防需求

在当今社会&#xff0c;安全是每个人和企业最为关心的问题。为满足日益增长的安防需求&#xff0c;3D可视化公司深圳华锐视点隆重推出安防平台3D可视化管理系统&#xff0c;以先进的三维技术为您的安全保驾护航。 安防平台3D可视化管理系统通过创新的三维可视化技术&#xff0c…