第3章 运算符 在Python中,运算符(operator)是一种特殊的符号,表示应该执行某种计算。运算符 作用的对象称为操作数(operand)。 >>> a = 1 >>> b = 2 >>> a + b #“+”叫作运算符,变量a 和b 叫作操作数 3 用运算符和括号将操作数连接起来的、符合Python语法规则的式子,称为表达式 (expression),如a+b-5。 本章讲述5种运算符,它们分别是算术运算符、比较运算符、逻辑运算符、位运算符和恒 等运算符。 3.1 算术运算符 Python语言中一共有9个算术运算符,如表3-1所示。 表3-1 算术运算符 运算符类 别意 义示 例说 明 + 一元正号 +a 正号 + 二元求和 a+ b 求a与b的和 - 一元负号 -a 负号 - 二元求差 a- b 求a和b的差 * 二元乘法 a* b 求a和b的乘积 / 二元除法 a/b 求a除以b的值,结果为浮点数 % 二元求余数a% b 求a除以b的余数 // 二元求整商a//b 求a除以b的商(下取整) ** 二元幂运算a**b 求a的b次幂 教学课件 第3章 运算符 49 >>> a = 3 >>> b = 2 >>> +a 3> >> -a -3 >>> a + b 5> >> a - b 1> >> a * b 6> >> a / b 1.5 >>> a % b 1> >> a**b 9 注意:(1)除法运算的结果总是一个浮点数。 >>> 6 / 3 #结果不是2 而是2.0,与C 语言不同 2.0 >>> 5 / 2 #与C 语言不同 2.5 (2)求整商“//”的计算结果。 >>> 5 // 2 #2.5 下取整为2 2> >> 5 // -2 #-2.5 下取整为-3 -3 >>> -5 // 2 #-2.5 下取整为-3 -3 >>> -5 // -2 #2.5 下取整为2 2 n% m 的计算结果是[0,m-1]。求余运算的一个应用场景是求一个多位数各个数 位上的数字。 >>> num = 351 >>> num %10 #得到num 个位上的数字 1> >> num // 100 #得到num 百位上的数字 3 50 Python程序设计教程(第2版) >>> num // 10 %10 #得到num 十位上的数字 5 Python语言的内置函数divmod(),可以同时计算整商和余数;函数pow()用来执行幂 运算。 >>> a, b = divmod(41, 7) >>> a #a = 41 // 7 5> >> b #b = 41 % 7 6> >> pow(5, 2) #相当于计算5**2,求幂(Power) 25 >>> pow(5, 2, 3) #相当于计算5**2 %3 1 3.2 比较运算符 Python语言中一共有6个比较运算符,如表3-2所示。 表3-2 比较运算符 运算符意 义示 例说 明 == 等于 a== b 如果a等于b,则结果为True;否则为False != 不等于 a!= b 如果a不等于b,则结果为True;否则为False < 小于 a< b 如果a小于b,则结果为True;否则为False <= 小于或等于a<= b 如果a小于或等于b,则结果为True;否则为False > 大于 a> b 如果a大于b,则结果为True;否则为False >= 大于或等于a>= b 如果a大于或等于b,则结果为True;否则为False >>> a = 1 >>> b = 2 >>> a == b False >>> a != b True >>> a <= b True >>> a >= b False 有些浮点数在计算机内部不能精确地存储。 第3章 运算符 51 >>> x = 1.1 + 2.2 >>> x == 3.3 #不能精确存储,导致两者不相等 False 因此,确定两个浮点数是否“相等”的首选方法,是在给定误差(Tolerance)的情况下,计 算它们是否彼此接近。 >>> tolerance = 0.00001 >>> x = 1.1 + 2.2 >>> abs(x -3.3) < tolerance #求绝对值函数abs() True 此时可以认为x等于3.3。 3.3 逻辑运算符 Python语言中一共有3个逻辑运算符,如表3-3所示。 表3-3 逻辑运算符 运算符示 例说 明 not notx 如果x为False,则结果为True;否则结果为False or xory 如果x和y都为False,则结果为False;否则结果为True and xandy 如果x和y都为True,则结果为True;否则结果为False 在计算逻辑表达式的值时,并不是所有的表达式都会被执行。只有在必须执行下一个 表达式才能得到最终的值时,才会执行这个表达式,否则不执行该表达式,这种特性叫作短 路求值(Short-CircuitEvaluation)。 >>>x =1 >>>not x <2 #x <2 为True,因此结果为False False >>>x <2 or 0 >1 #x <2 为True,因此结果为True True #短路求值,不执行第2 个表达式0 >1 >>>x <0 or 2 <1 #x <0 为False,2 <1 为False,因此结果为False False >>>x <0 and 2 >1 #x <0 为False,因此结果为False False #短路求值,不执行第2 个表达式2 >1 >>>x >0 and 2 >1 #x >0 为True,2 >1 为True,因此结果为True True 下列所有数据都等价于False。 (1)布尔值False; (2)任何零值,如0、0.0、0+0j; 52 Python程序设计教程(第2版) (3)空字符串; (4)空列表、空元组、空集合、空字典; (5)None。 >>>bool(0), bool(0.0), bool(0+0j) #0、0.0 和0+0j 都为False (False, False, False) >>>bool(-1), bool(1.1), bool(1+1j) #-1、1.1 和1+1j 都为True (True, True, True) >>>bool(''), bool(None), bool(False) #空字符串''、None 和False 都为False (False, False, False) >>>bool("fun"), bool(' ') #字符串fun 和空格' '都为True (True, True) >>>bool(list()) #空列表list()为False False >>>bool(tuple()) #空元组tuple()为False False >>>bool(set()) #空集合set()为False False >>>bool(dict(), #空字典dict()为False False 下列逻辑表达式中使用了非布尔操作数。 >>>x =1 >>>y =2 >>>x and y 2> >>x or y #短路求值,因为x 等价于True 1> >>bool(x) #x 的值为1,等价于True True >>>not x False >>>x =0.0 >>>y =1.1 >>>x and y #短路求值 0.0 >>>x or y 1.1 >>>bool(x) #x 的值为0.0,等价于False False >>>not x True 在某些情况下,利用短路求值可以编写出既简洁又高效的代码。假如有两个变量a和 b,想要知道表达式b/a是否大于0,代码如下: 第3章 运算符 53 >>>a =2 >>>b =1 >>>(b / a) >0 True 考虑到a可能为0,此时会引发Python解释器抛出异常。 >>>a =0 >>>b =1 >>>(b / a) >0 Traceback (most recent call last): File "<pyshell#136>", line 1, in <module> (b / a) >0 ZeroDivisionError: division by zero 为了避免发生异常,可以这样修改代码: >>>a !=0 and (b / a) >0 False 当a为0时,a!=0为False,短路求值特性确保第2个表达式(b/a)>0不被执行, 从而避免引发异常。实际上,上述代码还可以编写得更简洁。当a为0时,a本身就等价于 False,因此不需要显式地比较a!=0。 >>>a and (b / a) >0 #a 非0 时,才会执行第2 个表达式 0 3.4 位运算符 位运算符将操作数看作二进制数字序列,并对其逐位操作。Python语言支持的位运算 符如表3-4所示。 表3-4 位运算符 运算符示 例意 义说 明 & a&b 按位与对应位的与运算,只有两者都是1,才为1;否则为0 | a|b 按位或对应位的或运算,只要有一个为1,则为1;否则为0 ~ ~a 按位取反将每一位都逻辑求反,如果为0,则为1;如果为1,则为0 ^ a^b 按位异或对应位的异或运算,如果两者不同,则为1;否则为0 >> a>> n 按位右移将每一位都向右移动n位 << a<< n 按位左移将每一位都向左移动n位 >>> 0b1100 & 0b1010 54 Python程序设计教程(第2版) 8> >> bin(8) #将十进制数8 转换为二进制数 '0b1000' >>> 0b1100 | 0b1010 14 >>> bin(14) #将十进制数14 转换为二进制数 '0b1110' >>> 0b1100 ^ 0b1010 6> >> bin(6) #将十进制数6 转换为二进制数 '0b110' >>> 0b1100 >>2 3> >> bin(3) '0b11' >>> 0b1100 <<2 48 >>> bin(48) '0b110000' >>> ~0b1100 #二进制数1100 等于十进制数12 -13 #因此~12 等于-13 >>> bin(-13) '-0b1101' 读者可以验证一下~12等于-13这一事实。注意,数据在计算机内部是以补码的形式 存储的。 3.5 恒等运算符 Python提供了两个恒等运算符(identityoperator)is和isnot,用于确定两个操作数是 否恒等,即引用同一个对象。下面是两个相等但不相同的对象(不恒等)。 >>> x = 1001 >>> y = 1000+1 >>> print(x, y) 1001 1001 >>> x == y True >>> x is y False >>> y is x False 变量x和y都指向值为1001的对象,它们是相等的,但它们引用的不是同一个对象,这 第3章 运算符 55 可以使用id()函数进行验证。 >>> id(x) 2685066139824 >>> id(y) 2685066141040 由上述可知,变量x的标识为2685066139824,而变量y的标识为2685066141040,显然 两者引用的不是同一个对象。 当执行y=x这样的赋值操作时,Python只创建对同一个对象x的第二个引用y。 >>> a = "just for test" >>> b = a >>> id(a) 2685066109872 >>> id(b) 2685066109872 #变量a 和b 指向同一段内存地址 >>> a is b #变量a 和b 指向同一个对象 True >>> a == b #变量a 和b 的值相等 True 运算符isnot与is的逻辑功能相反。 >>> x = 5 >>> y = 10 >>> x is not y True 3.6 运算符的优先级 在求解表达式的值时,必须按照运算符的优先级以从高到低的顺序执行(括号除外)。 表3-5按照优先级从低到高的顺序列出Python的部分运算符。 表3-5 运算符的优先级 运 算 符说 明 or 逻辑或 and 逻辑与 not 逻辑非 ==,!=,<,<=,>,>=,is,isnot 优先级相同 | 按位或 续表 56 Python程序设计教程(第2版) 运 算 符说 明 ^ 按位异或 & 按位与 <<,>> 按位左移、按位右移 +,- 加、减 *,/,//,% 乘、除、求整商、求余数 +x,-x,~x 正号、负号、按位取反 ** 幂运算 >>> 2 * 3**2 * 4 #先计算3**2,然后自左向右按顺序计算 72 可以使用小括号改变运算符的执行顺序。 >>> 10 + 2 * 5 20 >>> (10 + 2) * 5 60 有时使用小括号不是想要改变计算的先后顺序,而是为了提高代码的可读性,这是一种 好的编程实践,避免了记忆运算符优先级的烦恼。 >>> (a <10) and (b >20) #推荐的做法,尽管小括号是多余的 >>> a <10 and b >20 #不推荐 3.7 复合赋值运算符 在赋值符“=”之前加上其他运算符,就构成了复合赋值运算符。例如,在“=”前加一个 “+”运算符就构成复合赋值运算符“+=”。 a + =1 等价于a = a +1 a % =3 等价于a = a %3 a ^ =5 等价于a = a ^ 5 算术运算符支持此种用法。 +=、-=、*=、/=、%=、//=、**= >>>a =2 第3章 运算符 57 >>>a *=3 -1 #等价于a =a * (3 -1),而不是a =a * 3 -1 >>>a 4 位运算符也支持此种用法。 &=、|=、^=、>>=和<<= >>> a = 1 >>> a += 5 >>> a 6 3.8 小结 本章讲述了各种运算符的用法,包括算术运算符、比较运算符、逻辑运算符、位运算符 等。将赋值符“=”与其他运算符相结合就构成了复合赋值运算符,如“+=”。另外,逻辑运 算符还具有短路求值特性,利用这一特性可以编写更简洁、更高效的代码。 练习题3 1.编程计算下列各表达式的值。 (1)5+6 (2)5-6 (3)5*6 (4)10/4 (5)10//4 (6)10%4 (7)2**4 2.使用divmod()函数计算5除以3的整商和余数。 3.分别使用两种方法计算5的3次幂。 4.已知x=3,执行x*=2+1语句后x的值等于。 5.如果数据在计算机内部用1字节存储,则-5的补码为。 6.代码5>3+2的执行结果是。 7.请举例说明短路求值特性。 8.代码(0.4-0.1)==0.3的执行结果是什么? 为什么会有这样的结果? 9.请写出下列各表达式的值。 (1)bool(1.0+1.0j) (2)bool(0.0) (3)bool(None) (4)bool(list()) (5)bool('hello') (6)bool(1) 10.已知x=5,y=3,求下列各表达式的值。 58 Python程序设计教程(第2版) (1)xory (2)xandy (3)notx 11.已知a=0b110,b=0b101,求下列各表达式的值。 (1)a&b (2)a|b (3)a^b (4)~a (5)a>>1 (6)b<<1 12.已知a= 'hello',b=a,求a== b的执行结果。 13.写出整数254的个位数字、十位数字和百位数字的表达式。