
2.6 常见的运算符与表达式
2.6.1 运算符与表达式概述
1.运算符
运算符是一些特殊的符号,主要用于数学计算、比较大小和逻辑运算等。Python的运算符主要包括算术运算符、赋值运算符、比较(关系)运算符、逻辑运算符和位运算符。
按照运算所需要的操作数目,可以分为单目、双目、三目运算符。
● 单目运算符只需要一个操作数。例如:单目减(-)、逻辑非(not)。
● 双目运算符需要两个操作数。Python大多数运算符是双目运算符。
● 三目运算符需要三个操作数。条件运算是三目运算符,例如:b if a else c。
运算符具有不同的优先级。我们熟知的“先乘除后加减”就是优先级的体现。只不过Python运算符种类很多,优先级也分成了高低不同的很多层次。当一个表达式中有多个运算符时,按优先级从高到低依次运算。
运算符还具有不同的结合性:左结合或右结合。当一个表达式中有多个运算符,且优先级都相同时,就根据结合性来判断运算的先后顺序。
左结合就是自左至右依次计算。Python运算符大多是左结合的。
右结合就是自右至左依次计算。所有的单目运算符和圆括号()是右结合的。实际上圆括号是自右向左依次运算的,即内层的圆括号更优先,从内向外运算。
以上所说的通过优先级、结合性来决定运算次序,只在没有圆括号的情况下成立。使用圆括号可以改变运算符的运算次序。
2.表达式
使用运算符将不同类型的数据按照一定的规则连接起来的式子,称为表达式。例如,使用算术运算符连接起来的式子称为算术表达式,使用逻辑运算符连接起来的式子称为逻辑表达式。
表达式由运算符和参与运算的数(操作数)组成。操作数可以是常量、变量,可以是函数的返回值。
按照运算符的种类,表达式可以分成:算术表达式、关系表达式、逻辑表达式、测试表达式等。
多种运算符混合运算形成复合表达式,按照运算符的优先级和结合性依次进行运算。当存在圆括号时,运算次序会发生变化。
很多运算对操作数的类型有要求,例如,加法“+”要求两个操作数类型一致,当操作数类型不一致时,可能发生隐式类型转换。例如:

运行结果是11。
差别较大的数据类型之间可能不会隐式类型转换,需要进行显式类型转换。例如:

2.6.2 算术运算符与表达式
算术运算符是处理四则运算的符号,在数字的处理中应用得最多。常用的算术运算符如表2-4所示。
表2-4 Python的算术运算符

在算术运算符中使用“%”求余,如果除数(第二个操作数)是负数,那么取得的结果也是一个负值。使用除法(/或//)运算符和求余运算符时,除数不能为0,否则将会出现异常。
注意:在Python中不支持C语言中的自增1(++)和自减1(--)运算符,这是因为+和-也是单目运算符,Python会将--n理解为-(-n)从而得到n,同样++n的结果也是n。
在Python中,“*”运算符还可以用于字符串中,计算结果就是字符串重复指定次数的结果。比如,print(”@”*10),将输出10个@字符。而“+”运算符也可以用于字符串的连接。
算术运算符可以直接对数字进行运算,也可以对变量进行运算。
在Python中进行数学计算时,与数学中的运算符优先级是一致的。先乘除后加减,同级运算符是从左至右计算,可以使用“()”调整计算的优先级。混合运算优先级顺序:“()”高于“**”高于“*”“/”“//”“%”高于“+”“-”。
在相同类型之间的数据运算,算术运算符优先级由高到最低顺序排列如下。
1)第一级:**。
2)第二级:*、/、%、//。
3)第三级:+、-。
如果是不同类型之间的数据运算,会发生隐式类型转换。转换规则是:低类型向高类型转换。可以进行算术运算的各种数据类型,从低到高排列为:bool﹤int﹤float﹤complex。
【例2-17】 计算学生三门计算机类课的成绩平均分。要求:某同学有3门课程成绩分别为:数据库原理:89;Python程序设计:96;Web技术:90。编程实现计算三门课程的平均分。

运行结果:

常用的Python数学运算类的内置函数见表2-5。
表2-5 常用的Python数学运算类的内置函数

math模块中的函数见表2-6。
表2-6 math模块中的函数

math模块中还定义了如下两个常量。
● math.pi:数学常量π,math.pi=3.141592653589793。
● math.e:数学常量e,math.e=2.718281828459045。
使用math模块前要先导入,使用函数时要在函数名前面加上“math.”。例如:math.log(10)。
如果要频繁使用某单一模块中的函数,为避免每次写模块名的麻烦,也可以按下面方式导入。

这样,就可以像内置函数那样来使用模块函数了。但是多个模块中可能有同名函数,如果都按这种方式导入,会产生名字冲突的问题。
2.6.3 赋值运算符与表达式
赋值运算符主要用来为变量赋值。使用时,可以直接把基本赋值运算符“=”右边的值赋给左边的变量,也可以进行某些运算后再赋值给左边的变量。在Python中常用的赋值运算符如表2-7所示。
表2-7 算术复合赋值运算符

1.赋值运算符
赋值运算符用“=”表示,一般有以下3种形式。

其左边只能是变量,而不能是常量或表达式。例如:5=x或5=2+3都是错误的。
注意:Python的赋值运算是没有返回值的。也就是说,赋值没有运算结果,变量的值被改变了。
混淆“=”和“==”是编程中最常见的错误之一。“=”是赋值运算符,“==”是比较运算符。
程序语句中的y=x不是数学中的方程等式,不代表y恒等于x。赋值是一个瞬间动作。
【例2-18】 输入两个数,交换两个变量的值。

2.复合赋值运算符
复合赋值是运算操作与赋值操作的组合。所有复合赋值运算符的优先级和赋值运算符的一样。其中,+=(加等于),-=(减等于),*=(乘等于),/=(除等于),%=(取余等于),**=(幂等于),/=(整除等于)为算术复合运算符(见表2-8)。
2.6.4 关系运算符与表达式
关系运算符也称为比较运算符。用于对两个数值型或字符串型数据,变量或表达式的结果进行大小、真假等比较,返回一个“真”或“假”的布尔值。
如果比较结果为真,则返回True,如果为假,则返回False。比较运算符通常用在条件语句中作为判断的依据,如表2-8所示。
表2-8 关系运算符

1.关系运算符
一定要注意比较是否相等要用双等号“==”,而不是“=”,这是初学者常犯的错误。
在比较过程中,遵循以下规则。
1)若两个操作数是数值型,则按大小进行比较。
2)若两个操作数是字符串型,则按“字典顺序”进行比较,即:首先取两个字符串的第1个字符进行比较,较大的字符所在字符串更大;如果相同,则再取两个字符串的第2个字符进行比较,其余类推。结果有三种情况:第一种,某次比较分出胜负,较大的字符所在字符串更大;第二种,始终不分胜负,并且两个字符串同时取完所有字符,那么这两个字符串相等;第三种,在分出胜负前,一个字符串已经取完所有字符,那么这个较短的字符串较小。第三种情况也可以认为是空字符和其他字符比较,空字符总是最小。
常用字符的大小关系为:空字符﹤空格﹤“0~9”﹤“A~Z”﹤“a~z”﹤汉字。可以利用ord(字符)查看字符的Unicode码,相反可以利用chr(Unicode码)查看对应的字符。
浮点数比较是否相等时要注意,因为有精度误差,可能产生本应相等但比较结果却不相等的情况。
可以用两个浮点数的差距小于一个极小值来判定是否“应该相等”,这个“极小值”可以根据需要自行指定。例如:

注意:复数不能比较大小,只能比较是否相等。
在Python中,当需要判断一个变量是否介于两个值之间时,可以采用“值1﹤变量﹤值2”的形式,“0﹤a﹤10”。Python允许x﹤y﹤z这样的链式比较,它相当于x﹤y and y﹤z。也可以用x﹤y﹥z,相当于x﹤y and y﹥z。
所有关系运算符的优先级相同。
“is”和“==”操作符的区别是“is”是用来比较两个对象是否是同一个对象,而“==”是用来比较两个对象的值是否相等。在Python中的变量有3个属性:name、id和value。其中name是变量的名字,id是内存地址,value是变量的值。is运算符则是通过id来判断的,如果id是一样的返回True,否则就返回False。
Python对小的整数和字符串做了处理,不管使用==操作符还是is操作符进行比较,最终的结果都是True。
【例2-19】 is与==应用示例。

运行结果:

2.6.5 逻辑运算符与表达式
判断闰年的标准是:年份能被整除4且不能整除100或能整除400,这里就用到了逻辑关系,Python中也提供了这样的逻辑运算符来进行逻辑运算((year%4==0 and year%100!=0)or year%400==0)。逻辑运算符是对真和假两种布尔值进行运算,运算后的结果仍是一个布尔值,Python中的逻辑运算符主要包括and(逻辑与)、or(逻辑或)、not(逻辑非)。
逻辑运算符如表2-9所示。
表2-9 逻辑运算符

or是一个短路运算符,如果左操作数为True,则跳过右操作数的计算,直接得出结果为True。只有在左操作数为False时才会计算右操作数的值。
and也是一个短路运算符,如果左操作数为False,则跳过右操作数的计算,直接得出结果为False。只有在左操作数为True时,才会计算右操作数的值。
短路运算可以节省不必要的计算时间,而且Python会按照“最贪婪”的方式进行短路运算,以至于看上去违反了优先级次序。例如:


在这个例子中,b==2 and c==3整个被短路,并不会因为优先级高而先计算and。
把上面的例子改写成下面的形式。

输出如下。

后面两个函数equal并没有被执行,说明equal(b,2)and equal(c,3)全都被短路了。
逻辑运算符的优先级,按照从低到高的顺序排列为:or﹤and﹤not。
2.6.6 条件(三目)运算符
运算符(三元、三目运算符)语法:语句1 if条件表达式else语句2。
执行流程:条件运算符在执行时,会先对条件表达式进行求值判断。如果判断结果为True,则执行语句1,并返回执行结果;如果判断结果为False,则执行语句2,并返回执行结果。
例如:x='正数'if c﹥0 else'非正数'。
【例2-20】 有两个变量,比较大小。如果变量1大于变量2执行,变量1-变量2;否则变量2-变量1。

运行结果:

2.6.7 位运算符
位运算符是把数字看作二进制数来进行计算的,因此,需要先将要执行运算的数据转换为二进制,然后才能执行运算。Python中的位运算符有位与(&)、位或(|)、位异或(^)、取反(~)、左移位(﹤﹤)和右移位(﹥﹥)运算符。
1.“位与”运算
“位与”运算的运算符为“&”,它的运算法则是:两个操作数据的二进制表示,只有对应位都是1时,结果位才是1,否则为0。如果两个操作数的精度不同,则结果的精度与精度高的操作数相同。
2.“位或”运算
“位或”运算的运算符为“|”,它的运算法则是:两个操作数据的二进制表示,只有对应位都是0,结果位才是0,否则为l。如果两个操作数的精度不同,则结果的精度与精度高的操作数相同。
3.“位异或”运算
“位异或”运算的运算符是“^”,它的运算法则是:当两个操作数的二进制表示相同(同时为0或同时为1)时,结果为0,否则为1。若两个操作数的精度不同,则结果数的精度与精度高的操作数相同。
4.“位取反”运算
位取反运算也称“位非”运算,运算符为“~”。“位取反”运算就是将操作数中对应的二进制数1修改为0,0修改为1。
5.左移位运算符﹤﹤
左移位运算符﹤﹤是将一个二进制操作数向左移动指定的位数,左边(高位端)溢出的位被丟弃,右边(低位端)的空位用0补充。左移位运算相当于乘以2的n次幂。
6.右移位运算符﹥﹥
右移位运算符﹥﹥是将一个二进制操作数向右移动指定的位数,右边(低位端)溢出的位被丢弃,而在填充左边(高位端)的空位时,如果最高位是0(正数),左侧空位填入0;如果最高位是1(负数),左侧空位填入1。右移位运算相当于除以2的n次幂。
2.6.8 运算符的优先级
所谓运算符的优先级,是指在应用中哪一个运算符先计算,哪一个后计算,与数学的四则运算应遵循的“先乘除,后加减”是一个道理。Python运算符的运算规则是:优先级高的运算先执行,优先级低的运算后执行,同一优先级级的操作按照从左到右的顺序进行。也可以像四则运算那样使用小括号,括号内的运算最先执行。同一行中的运算符具有相同优先级,此时它们的结合方向决定求值顺序。
常见运算符的优先级,按照从低到高的顺序排列(同一行优先级相同)总结如下。
● 逻辑运算符:or。
● 逻辑运算符:and。
● 逻辑运算符:not。
● 成员测试:in,not in。
● 同一性测试:is,is not。
● 比较:﹤,﹤=,﹥,﹥=,!=,==。
● 按位或:|。
● 按位异或:^。
● 按位与:&。
● 移位:﹤﹤,﹥﹥。
● 加法与减法:+,-。
● 乘法、除法与取余:*,/,%。
● 正负号:+x,-x。