《从问题到程序:用Python学编程和计算》——2.7 判断和条件控制

简介:

本节书摘来自华章计算机《从问题到程序:用Python学编程和计算》一书中的第2章,第2.7节,作者 裘宗燕,更多章节内容可以访问云栖社区“华章计算机”公众号查看。

2.7 判断和条件控制

数学里有一些表示判断的算符,如表示数值之间的等于或不等于、大于、小于等。Python提供了一些用于描述条件判断的运算符以及一种特殊的语句(称为if语言,条件语句),它能利用条件判断的结果选择执行不同的语句或语句序列。

2.7.1 条件判断和逻辑表达式

对于数值类型,这里有一组比较运算符用于描述基本条件判断,包括:

image

用一个比较运算符和两个数值表达式,可以构造出一个关系表达式,其意义就是判断两个数值之间的特定关系是否成立。

比较运算符也是一类运算符,求值一个关系表达式,也应该得到一个运算结果。Python用两个特殊的逻辑对象表示比较的结果,它们属于内置的逻辑类型bool,是该类型中仅有的两个对象,关键字True和False分别表示这两个逻辑对象。在做比较时,关系成立就会得到True,表示结果是“真”;关系不成立时将得到False,表示比较的结论是“假”。例如,当20 > 15将得到True,而12 >= 15得到False。

用一个关系运算符可以描述两个数值(表达式)之间的一种关系,但是这往往不够。很多时候我们希望考虑若干关系都成立等一些组合情况。例如,对于三角形的三条边,基本要求是它们的值都大于0,为此就需要写一个组合判断。逻辑研究表明,只需要三个逻辑组合运算,就足以描述所有的组合判断,它们是:

1)A与B,表示A和B都成立的组合判断;

2)A或B,表示A与B之中至少有一个成立的组合判断;

3)非A,表示A不成立的组合判断。

Python为上面三个逻辑组合关系提供了三个运算符:

image

其中,or和and是二元运算符,not是一元运算符。假设A和B是具有逻辑值的表达式(比较表达式或组合逻辑表达式),当且仅当A和B都为真时A and B为真;当且仅当A和B中至少一个为真时A or B为真;当且仅当A为假时not A为真。这三个逻辑组合运算符都是关键字,基于关系和逻辑运算符构造起来的表达式称为逻辑表达式。

例如,3 > 2 and 7 <= 10的值是True,因为3 > 2和7 <= 10都是正确的。not 3 > 2 or 7 > 10 or 7 > 5的值也是True,有关情况请读者自己分析。显然这里也有运算符的优先级和结合性问题。

为方便书写,Python允许连续使用比较运算符。例如x > 1 and x < 10可以简单地写为1 < x < 10。实际上,在Python里还可以写10 < x > y2,表示x > 10 and x > y2。这种形式在数学中不常见。

Python关于比较运算符和逻辑运算符的优先级和结合性的规定如下:

  • 比较运算符的优先级低于算术运算符,因此x + y > x2相当于(x + y) > (x2),是合法的关系表达式。所有比较运算符的优先级相同,连续的比较表示对相邻运算对象做关系运算之后用and连接,相互为“与”关系。
  • 三个逻辑运算符中,一元运算符not的优先级最高,但低于比较运算符,or的优先级最低,and介于两者之间。因此,not x2 > 5 or y < 6 and x y > 8相当于not (x2 > 5) or ((y < 6) and (x y > 8))。

例如,变量a、b、c的值构成一个三角形的三条边,条件可以写为:

a > 0 and b > 0 and c > 0 and \
a + b > c and b + c > a and a + c > b

这里假定了a、b、c的值都是数值。由于表达式很长,这里用了续行符,表示描述的是一个表达式,虽然其正文延续了两行。

2.7.2 if语句(条件语句)

要想根据逻辑判断选择不同的处理方式,就要使用if语句,这种语句也常被称为条件语句或者分支语句。if语句有两种基本形式,其一是:

image

在这个语句执行时,如果表达式为真,就执行语句组中的语句(可以有一个或多个),全部执行完后if语句结束;表达式为假时什么也不做,if语句直接结束。

第二种形式是:

image

如果语句执行时表达式为真,就执行第一个语句组中的语句;表达式为假时执行第二个语句组中的语句。执行完任一个语句组时整个if语句结束。

现在可以重写基于三边长求三角形面积的程序,加进输入检查:

# Program to calculate area of triangle
from math import sqrt

a = float(input("Length of edge a: "))
b = float(input("Length of edge b: "))
c = float(input("Length of edge c: "))

if a > 0 and b > 0 and c > 0 and \
   a + b > c and b + c > a and a + c > b:
    s = (a + b + c) / 2
    area = sqrt(s * (s - a) * (s - b) * (s - c))
    print("Area of the triangle:", area)
else:
    print(a, b, c, "do not form a triangle!")

本程序一次运行的情况如下:

>>> 
Length of edge a: 2
Length of edge b: 5
Length of edge c: 8
2.0 5.0 8.0 do not form a triangle

程序的第一行就是注释,也常被称为注释行。

if语句和程序格式

对一个if语句,从关键字if开始到相应语句组结束称为该语句的if段,从关键字else开始的部分称为其else段(else段可选,可以没有)。其中的“if 表达式:”部分和“else:”部分称为相应段的头部,语句组称为该段的体。

与前面各种简单语句相对应,if这类具有复杂结构(组合结构)的语句被称为复合语句,其中包含一些部分,有些部分本身也是语句。在if语句两个段的语句组里可以出现一个或多个任意的语句,包括if语句本身。这说明if语句的结构具有递归性,其中一些部分可具有与整体相同的结构,整个结构可以任意复杂。如果某语句组里只有一个语句,Python允许把它直接写在该段的头部之后,但人们不倡导这种写法。

为使程序清晰易读,Python语言对if这类组合结构的写法有严格要求,包括两方面:①处于同一层的不同成分必须相互对齐,②下一层的成分需要统一退格。如果一个子部分包含了顺序的多个语句,这些成分语句也必须相互对齐。

以if语句为例,如果它包含else段,if和else两个关键字必须在同一列上对齐(左对齐)。进而,两个语句块里的成分语句需要统一地退格并相互对齐。上面示例程序里的if语句及其成分都正确对齐了,这是必须的。这些要求是Python语言的特殊规定,多数语言没有这种要求。Python采用强制性的格式规定,是为了使程序里的语句结构清晰,具有较好的可读性。

初看起来贯彻上面的规定似乎很麻烦。但如果用IDLE编辑器(或其他专门针对Python的编辑器),保证格式的工作都很简单。IDLE能自动对齐同一层的语句,对于if等组合结构,它也能自动确定内层结构的对齐位置(多增加几个空格,可以自己设置。默认为4个字符,人们认为4个字符既足够清晰,也不带来大片空白,是比较好的设定)。此外,在IDLE编辑状态下按Tab键,IDLE会把输入光标移到下一对齐位置(通过加入几个空格);如果按Backspace键,IDLE就会把输入光标退到前一层对齐位置。做这两种移动时,光标所在的行不变。应特别注意:在编写Python程序时,不要自己用空格键在一行开始加空格,应直接利用IDLE的默认对齐方式,既方便又不会出错。

在编写Python程序时,应特别注意Tab字符和空格不能混用,因为它们都看不见,不易识别。采用非专门用于Python程序的编辑器编程序时,有可能出现这类错误,应该特别注意。程序里出现对齐错误时,解释器也看作语法错,可以定位和报告。

if语句的扩展形式

程序里也经常需要区分多种(两种以上)不同情况,分别处理。显然,这种需求可以用嵌套的if语句表示,即在一个if语句的语句组里再写if语句。Python为常见情况提供了扩展的if语句形式,允许用一系列逻辑表达式来区分多种情况:

image

也就是说,在语句的if段之后可以包含任意多个elif段,每个段包含形式为“elif 表达式:”的头部和一个语句块体。最后是else段。在执行这种if语句时,解释器先求值第一个表达式,如果其值为真就执行第一个语句组,然后整个if结束。如果第一个表达式的值是假,解释器就转去求值随后的elif段头部的表达式,如果其值为真就执行该elif段的语句组,然后整个if结束。如果被求值表达式还是假,解释器就继续考虑下一个elif段,直到在某步求得表达式的值为真,转去执行相应语句组。遇到所有表达式都是假的情况,解释器将执行else段的语句组(如果有这个段)。注意,无论有多少个elif段(及最后的else段),在if语句执行中至多执行一个段里的语句块。

下面将看到这种扩展结构的使用。显然,检查输入只是逻辑判断与条件语句的一种用途,正常计算中也经常需要分情况处理,这时就应该用条件语句。

2.7.3 编程实例

现在考虑几个编程实例。

求二次函数的根

计算二次函数的根是一项很常见的计算:给定二次函数的三个系数,根据公式算出函数的根。这里需要根据判别式的值区分三种情况,可能存在两个实根,或者存在一个重根,或者是无实根(存在一对共轭的复根)。下面只考虑实根的情况。

完成这一计算,应该先求出判别式的值,然后根据这个值分情况处理。根据二次函数的求根公式,不难写出下面的程序:

from math import sqrt

print("Program for root(s) of quadratic equetions.")
a = float(input("Coefficient of x**2: "))
b = float(input("Coefficient of x: "))
c = float(input("Constant: "))

d = b**2 - 4 * a * c
if d > 0:
    tmp = sqrt(d)
    print("Two roots:", (-b + tmp)/2/a,  (-b - tmp)/2/a)
elif d == 0:
    print("One root:", -b/2/a)
else:
    print("No real root")

这里增加了第一个打印语句,告知用户这是什么程序,是一种提示。程序里使用了扩展的if语句,分三种情况分别处理。还需要注意的是除以2a的写法。

读者在前面已经看了不少程序执行情况。为了减少页面占用,今后除一些特殊情况外,书中将不再给出程序执行的情况。请读者自己运行程序查看效果。

简单总计

买一种货品需要从单价和数量算出总货款。考虑写一个程序完成这一简单计算。显然,计算中也需要输入数据。不难写出下面程序,其中做了必要的检查:

# A program calculating total price of some goods

name = input("Please give the name of the good: ")
price = float(input("Price of one piece of the good: "))
amount = int(input("Amount: "))

if price > 0 and amount > 0:
    print(amount, "pieces of", name, 
          "totally: ", price * amount)
else:
    print("Error. Price and amount should be positive.")

在这个程序里可以看到字符串的使用,以及如何结合使用字符串(字面量和保存在变量的字符串)和数值,生成较为复杂的输出形式。

当然,也可以利用字符串操作生成出同样的字符串,令print输出构造好的串。如果只是为了产生输出,仅利用print输出多个参数值的功能就能满足需要,像上面这样直接输出可能更方便。作为练习,请读者修改程序,利用字符串操作构造出同样的或更符合自己想法的字符串,而后调用print输出该串。

相关文章
|
1月前
|
人工智能 数据可视化 数据挖掘
探索Python编程:从基础到高级
在这篇文章中,我们将一起深入探索Python编程的世界。无论你是初学者还是有经验的程序员,都可以从中获得新的知识和技能。我们将从Python的基础语法开始,然后逐步过渡到更复杂的主题,如面向对象编程、异常处理和模块使用。最后,我们将通过一些实际的代码示例,来展示如何应用这些知识解决实际问题。让我们一起开启Python编程的旅程吧!
|
1月前
|
存储 数据采集 人工智能
Python编程入门:从零基础到实战应用
本文是一篇面向初学者的Python编程教程,旨在帮助读者从零开始学习Python编程语言。文章首先介绍了Python的基本概念和特点,然后通过一个简单的例子展示了如何编写Python代码。接下来,文章详细介绍了Python的数据类型、变量、运算符、控制结构、函数等基本语法知识。最后,文章通过一个实战项目——制作一个简单的计算器程序,帮助读者巩固所学知识并提高编程技能。
|
26天前
|
Unix Linux 程序员
[oeasy]python053_学编程为什么从hello_world_开始
视频介绍了“Hello World”程序的由来及其在编程中的重要性。从贝尔实验室诞生的Unix系统和C语言说起,讲述了“Hello World”作为经典示例的起源和流传过程。文章还探讨了C语言对其他编程语言的影响,以及它在系统编程中的地位。最后总结了“Hello World”、print、小括号和双引号等编程概念的来源。
107 80
|
8天前
|
存储 NoSQL 数据库连接
在Python程序中实现LevelDB的海量key的分批次扫描
通过本文的步骤,您可以在Python程序中实现对LevelDB海量key的分批次扫描。这样不仅能够有效地管理大规模数据,还可以避免一次性加载过多数据到内存中,提高程序的性能和稳定性。希望这篇指南能为您的开发工作提供实用的帮助。
53 28
|
15天前
|
Python
[oeasy]python055_python编程_容易出现的问题_函数名的重新赋值_print_int
本文介绍了Python编程中容易出现的问题,特别是函数名、类名和模块名的重新赋值。通过具体示例展示了将内建函数(如`print`、`int`、`max`)或模块名(如`os`)重新赋值为其他类型后,会导致原有功能失效。例如,将`print`赋值为整数后,无法再用其输出内容;将`int`赋值为整数后,无法再进行类型转换。重新赋值后,这些名称失去了原有的功能,可能导致程序错误。总结指出,已有的函数名、类名和模块名不适合覆盖赋新值,否则会失去原有功能。如果需要使用类似的变量名,建议采用其他命名方式以避免冲突。
34 14
|
27天前
|
安全 API C语言
Python程序的安全逆向(关于我的OPENAI的APIkey是如何被盗的)
本文介绍了如何使用C语言编写一个简单的文件加解密程序,并讨论了如何为编译后的软件添加图标。此外,文章还探讨了Python的.pyc、.pyd等文件的原理,以及如何生成和使用.pyd文件来增强代码的安全性。通过视频和教程,作者详细讲解了生成.pyd文件的过程,并分享了逆向分析.pyd文件的方法。最后,文章提到可以通过定制Python解释器来进一步保护源代码。
73 6
|
25天前
|
分布式计算 大数据 数据处理
技术评测:MaxCompute MaxFrame——阿里云自研分布式计算框架的Python编程接口
随着大数据和人工智能技术的发展,数据处理的需求日益增长。阿里云推出的MaxCompute MaxFrame(简称“MaxFrame”)是一个专为Python开发者设计的分布式计算框架,它不仅支持Python编程接口,还能直接利用MaxCompute的云原生大数据计算资源和服务。本文将通过一系列最佳实践测评,探讨MaxFrame在分布式Pandas处理以及大语言模型数据处理场景中的表现,并分析其在实际工作中的应用潜力。
62 2
|
1月前
|
Python
Python中的函数是**一种命名的代码块,用于执行特定任务或计算
Python中的函数是**一种命名的代码块,用于执行特定任务或计算
52 18
|
1月前
|
小程序 开发者 Python
探索Python编程:从基础到实战
本文将引导你走进Python编程的世界,从基础语法开始,逐步深入到实战项目。我们将一起探讨如何在编程中发挥创意,解决问题,并分享一些实用的技巧和心得。无论你是编程新手还是有一定经验的开发者,这篇文章都将为你提供有价值的参考。让我们一起开启Python编程的探索之旅吧!
50 10
|
1月前
|
机器学习/深度学习 人工智能 数据挖掘
探索Python编程的奥秘
在数字世界的海洋中,Python如同一艘灵活的帆船,引领着无数探险者穿梭于数据的波涛之中。本文将带你领略Python编程的魅力,从基础语法到实际应用,一步步揭开Python的神秘面纱。
46 12