2.3.3 表达式
表达式一般由运算符和操作数/操作对象组成。例如表达式1+2,+称为运算符,1和2称为操作数。
有关的运算符和表达式见表2.2。
表2.2 运算符与表达式
这里需要说明的是:
(1)+运算符不支持不同类型对象之间的连接。
(2)∗运算符可以用于列表、元组或字符串与整数的相乘,用于将这些序列重复整数所指定的次数。它不适用于字典和集合与整数的相乘。
(3)∗∗运算符与带有两个参数的内置函数pow()的功能相同,表示幂运算。
另外请读者思考一下,带有三个参数的内置函数pow()的功能是什么呢?你能想到利用前面提到过的哪个知识来得到答案吗?
(4)利用关系运算符比较大小首先要保证操作数之间是可比较大小的;另外关系运算符可以连用。
在Python3中,所有的字符串都是Unicode字符串;对于单个字符的编码,可以通过ord()函数获取该字符的Unicode码,通过chr()函数把编码转换为对应的字符。
对于字符串的比较,是通过从左到右依次比较每个字符的编码的大小来得到字符串的大小,直到找到一个不同的字符为止。
因此'a''A'的结果为True。
同样的道理,'a''我'的结果为True。
比较字符串'abcae'和'abcAb'时,从左到右依次比较'a'、'b'、'c'的编码,大小均相同,再比较'a'和'A',发现'a'的编码大于'A'的编码,则'abcae'<'abcAb'的结果为False。其实如果仅仅是对于大小写英文字母、数字和一些符号来比较大小,完全可以直接通过ASCII编码来比较大小。因为Unicode通常用两个字节表示一个字符,原有的英文编码从单字节变成双字节,只是把高字节全部填为0。在ASCII编码中:
数字的ASCII编码<大写字母的ASCII编码<小写字母的ASCII编码。
而在数字当中,数字0比数字9要小,并按0到9顺序递增;在大写字母当中,字母A比字母Z要小,并按A到Z顺序递增;在小写字母当中,字母a比字母z要小,并按a到z顺序递增。
如果是同一个字母,则其大写字母的ASCII编码比小写字母的ASCII编码要小32。如ord('A')的结果就等于ord('a')-32。
字符串和数字属于不可比较大小的。
列表比较大小也是从左到右逐个元素地依次比较。
但是以下表达式会出错。两个列表第一个元素分别是数字1和字符串'a',而字符串和数字属于不可比较大小,这样会触发TypeError异常。
同样,以下表达式也会出错。列表中第一个元素相同,然后比较第二个元素,一个是字符串'c',一个是数字3,原因不再赘述。
关系运算符可以连用,等价于某几个用and连接起来的表达式。
这里还要说明一点:因为精度问题可能导致实数运算有一定的误差,要尽可能地避免在实数之间进行相等性判断,可以使用实数之间的差值的绝对值是否小于某一个很小的数来作为实数之间是否相等的判断。
(5)成员测试运算符in和not in测试一个对象是否是另一个对象的成员,返回布尔值True或False。当一个对象是另一个对象的成员时,用in的表达式返回True,而用not in的表达式返回False;同样,当一个对象不是另一个对象的成员时,用in的表达式返回False,而用not in的表达式返回True。
(6)同一性测试运算符is和is not测试是否为同一个对象或内存地址是否相同,返回布尔值True和False。当是同一个对象时,用is的表达式返回True,而用is not的表达式返回False;同样,当不是同一个对象时,用is的表达式返回False,而用is not的表达式返回True。
x、y相等但并非为同一个对象。
请注意,是否相等只是测试值是否相同,是否为同一个对象指的是是否指向同一个对象,如果指向同一个对象,则内存地址应该相同。
内置函数id()返回对象的标识(内存地址)。
x、y的内存地址不同。
通过赋值语句z=x,则z和x不仅值相等而且指向同一个对象,z、x的内存地址相同。
(7)逻辑运算符not一定会返回布尔值True或False。
不论not后跟何值,其返回值一定是布尔值True或False。当not后跟False、0、[]、""、{}等和None时,返回值是True。这是因为在进行逻辑判断的时候,对于基本数据类型来说,基本上每个类型都存在一个值会被判定为False,这样not False就为True。被判定为False的值除了False以外,还有None、数值类型中的0值、空字符串、空元组、空列表、空字典、空集合等。
(8)逻辑操作符and和or也称作短路操作符,具有惰性求值的特点:表达式从左向右解析,一旦结果可以确定就停止。逻辑运算符and、or不一定会返回布尔值True和False。
当计算表达式exp1 and exp2时,先计算exp1的值,当exp1的值为True或非空值(非0、非None、值非空的其他数据类型),才计算并输出exp2的值;当exp1的值为False或空值(0、None、值为空的其他数据类型),直接输出exp1的值,不再计算exp2。
当计算表达式exp1 or exp2时,先计算exp1的值,当exp1的值为True或非空值(非0、非None、值非空的其他数据类型),直接输出exp1的值,不再计算exp2;当exp1的值为False或空值(0、None、值为空的其他数据类型),才计算并输出exp2的值。
(9)除了表2.2列出的运算符外,Python还有赋值运算符(=)、复合赋值运算符(+=、-=、∗=、/=、//=、∗∗=等)、位运算符(&、|、^等)等,这里说明一下复合赋值运算符,其他的运算符请读者自行参阅官网内容和其他资料。
以∗=运算符为例。
实际上a∗=b,就相当于a=a∗b,表示将左操作数乘以右操作数再赋值给左操作数。其他复合赋值运算符可同样理解。
(10)一个表达式中出现多种运算符时,按运算符的优先级高低依次进行运算。小括号()运算级别最高。优先级次序如图2.1所示。
图2.1 优先级次序
计算过程:先计算2-3,得到的值0.125与3相加。
计算过程:先计算2-3得到值0.125,再计算103得到值1000,然后计算0.125与1000的积得到值125.0,再计算125.0%2得到值1.0,最后1.0与3相加。
计算过程:先计算小括号中的表达式3%2,得到值1,再计算2-3和101分别得到值0.125和10,然后计算0.125∗10得到值1.25,最后1.25与3相加。
计算过程:先计算2∗10得到值20,再计算1 not in[1,2]得到值False,最后计算20 and False。