《Python从小白到大牛》第7章 运算符

《Python从小白到大牛》已经上市!

本章为大家介绍Python语言中一些主要的运算符(也称操作符),包括算术运算符、关系运算符、逻辑运算符、位运算符和其他运算符。

算术运算符

Python中的算术运算符用来组织整型和浮点型数据的算术运算,按照参加运算的操作数的不同可以分为一元运算符和二元运算符。

一元运算符

Python中一元运算符有多个,但是算数一元运算符只有一个,即:-,-是取反运算符,例如:-a是对a取反运算。

在Python Shell中运行示例代码如下:

>>> a = 12
>>> -a
-12
>>>

上述代码是把a变量取反,结果输出是-12。

二元运算符

二元运算符包括:+、-、*、/、%、**和//,这些运算符主要是对数字类型数据进行操作,而+和*可以用于字符串、元组和列表等类型数据操作。具体说明参见表7-1。

表 7‑1二元算术运算符

运算符 名称 说明 例子
+ 可用于数字、序列等类型数据操作。对于数字类型是求和;其他类型是连接操作。 a + b
- 求a减b的差 a - b
* 可用于数字、序列等类型数据操作。对于数字类型是求积;其他类型是重复操作。 a * b
/ 求a除以b的商 a / b
% 取余 求a除以b的余数 a % b
** 求a的b次幂 a ** b
// 地板除法 求小于a除以b商的最大整数 a // b

在Python Shell中运行示例代码如下:

>>> 1 + 2
3
>>> 2 - 1
1
>>> 2 * 3
6
>>> 3 / 2
1.5
>>> 3 % 2
1
>>> 3 // 2
1
>>> -3 // 2
-2
>>> 10 ** 2
100
>>> 10.22 + 10
20.22
>>> 10.0 + True + 2
13.0

上述例子中分别对数字类型数据进行了二元运算,其中True被当作整数1参与运算,操作数中有浮点数字,表达式计算结果也是浮点类型。其他代码比较简单不再赘述。

字符串属于序列的一种,所以字符串可以使用+和*运算符,在Python
Shell中运行示例代码如下:

>>> 'Hello' + 'World'
'HelloWorld'
>>> 'Hello' + 2
Traceback (most recent call last):
  File "<pyshell#35>", line 1, in <module>
    'Hello' + 2
TypeError: must be str, not int
>>>
>>> 'Hello' * 2
'HelloHello'
>>> 'Hello' * 2.2
Traceback (most recent call last):
  File "<pyshell#36>", line 1, in <module>
    'Hello' * 2.2
TypeError: can't multiply sequence by non-int of type 'float'

+运算符会将两个字符串连接起来,但不能将字符串与其他类型数据连接起来。*运算符第一操作数是字符串,第二操作数是整数,表示重复字符串多次。因此'Hello'
* 2结果是'HelloHello',注意第二操作数只能是整数。

关系运算符

关系运算是比较两个表达式大小关系的运算,它的结果是布尔类型数据,即True或False。关系运算符有6种:==、!=、>、<、>=和<=,具体说明参见表7-2。

表 7‑2 关系运算符

运算符 名称 说明 例子
== 等于 a等于b时返回True,否则返回False。 a == b
!= 不等于 与==相反 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

在Python Shell中运行示例代码如下:

>>> a = 1
>>> b = 2
>>> a > b
False
>>> a < b
True
>>> a >= b
False
>>> a <= b
True
>>> 1.0 == 1
True
>>> 1.0 != 1
False

Python中关系运算可用于比较序列或数字,整数、浮点数都是对象,可以使用关系运算符进行比较;字符串、列表和元组属于序列也可以使用关系运算符进行比较。在Python Shell中运行示例代码如下:

>>> a = 'Hello'
>>> b = 'Hello'
>>> a == b      
True
>>> a = 'World'
>>> a > b
True
>>> a < b
False
>>> a = []              ①
>>> b = [1, 2]      ②
>>> a == b
False
>>> a < b
True
>>> a = [1, 2]
>>> a == b
True

代码第①行创建一个空列表,代码第②行创建一个两个元素的列表,他们也可以进行比较。

逻辑运算符

逻辑运算符是对布尔型变量进行运算,其结果也是布尔型,具体说明参见表7-3。

表 7‑3 逻辑运算符

运算符 名称 说明 例子
not 逻辑非 a为True时,值为False,a为False时,值为True not a
and 逻辑与 ab全为True时,计算结果为True,否则为False a and b
or 逻辑或 ab全为False时,计算结果为False,否则为True a or b

Python中的“逻辑与”和“逻辑或”都采用“短路”设计,例如a and
b,如果a为True,则不计算b(因为不论 b为何值,“与”操作的结果都为False);而对于a
or b,如果a为True,则不计算b(因为不论b为何值,“或”操作的结果都为True)。

这种短路形式的设计,使他们在计算过程中就像电路短路一样采用最优化的计算方式,从而提高效率。示例代码如下:

# 代码文件:chapter7/7.3/hello.py

i = 0
a = 10
b = 9

if a > b or i == 1:
    print("或运算为 真")
else:
    print("或运算为 假")

if a < b and i == 1:
    print("与运算为 真")
else:
    print("与运算为 假")


def f1():   ①
    return a > b


def f2():   ②
    print('--f2--')
    return a == b


print(f1() or f2()) ③

输出结果如下:

或运算为 真
与运算为 假
True

上述代码第①行和第②行定义的两个函数,函数返回的是布尔值。代码第③行进行“或”运算,由于短路计算,f1函数返回True之后,f2函数不再调用。

位运算符

位运算是以二进位(bit)为单位进行运算的,操作数和结果都是整型数据。位运算符有如下几个运算符:&、|、^、~、>>和<<,具体说明参见表7-4。

表 7‑4 位运算符

运算符 名  称 例  子 说  明
~ 位反 ~x 将x的值按位取反
& 位与 x & y x与y位进行位与运算
| 位或 x | y x与y位进行位或运算
^ 位异或 x ^ y x与y位进行位异或运算
>> 有符号右移 x >> a x右移a位,高位采用符号位补位
<< 左移 x << a x左移a位,低位用0补位

位运算示例代码:

# 代码文件:chapter7/7.4/hello.py

a = 0b10110010      ①
b = 0b01011110      ②

print("a | b = {0}".format(a | b))  # 0b11111110        ③
print("a & b = {0}".format(a & b))  # 0b00010010    ④
print("a ^ b = {0}".format(a ^ b))  # 0b11101100    ⑤
print("~a = {0}".format(~a))        # -179      ⑥
print("a >> 2 = {0}".format(a >> 2))  # 0b00101100  ⑦
print("a << 2 = {0}".format(a << 2))  # 0b11001000  ⑧

c = -0b1100         ⑨
print("c >> 2 = {0}".format(c >> 2))  # -0b00000011 ⑩
print("c <<  2 = {0}".format(c << 2))  # -0b00110000    ⑪

输出结果如下:

a | b = 254
a & b = 18
a ^ b = 236
~a = -179
a >> 2 = 44
a << 2 = 712
c >> 2 = -3
c <<  2 = -48

上述代码中,在第①行和第②行分别声明了整数变量a和b,采用二进制表示方式。第⑨行声明变量c,采用二进制表示的负整数。

注意
a和b位数是与本机相关的,虽然只写出了8位,但笔者计算机是64位的,所以a和b都是64位数字,只是在本例中省略了前56个零。位数的不这会影响位反和位移运算。

代码第③行(a |
b)表达式是进行位或运算,结果是二进制的0b11111110(十进制是254),它的运算过程如图7-1所示。从图中可见,a和b按位进行或计算,只要有一个为1,这一位就为1,否则为0。

图7-1 位或运算

代码第④行(a &
b)是进行位与运算,结果是二进制的0b00010010(十进制是18),它的运算过程如图7-2所示。从图中可见,a和b按位进行与计算,只有两位全部为1,这一位才为1,否则为0。

图7-2 位与运算

代码第⑤行(a ^
b)是进行位异或运算,结果是二进制的0b11101100(十进制是236),它的运算过程如图7-3所示。从图中可见,a和b按位进行异或计算,只有两位相反时这一位才为1,否则为0。

图7-3 异或位运算

代码第⑥行(~a)是按位取反运算,这个过程中需要补码运算,而且与计算机位数有关。笔者使用的64位机,计算结果所是
-179。

代码第⑦行(a >>
2)是进行右位移2位运算,结果是二进制的0b00101100(十进制是44),它的运算过程如图7-4所示。从图中可见,a的低位被移除掉,高位用0补位(注意最高为不是1,而是0,在1前面还有56个0)。

图7-4 右位移2位运算

代码第⑧行(a <<
2)是进行左位移2位运算,结果是二进制的0b1011001000(十进制是712),它的运算过程如图7-5所示。从图中可见,由于本机是64位,所以高位不会移除掉,低位用0补位。但是需要注意如果本机是8位的,高位会被移除掉,结果是二进制的0b11001000(十进制是310)。

图7-5 左位移2位运算

提示
代码第⑩行和第⑪行是对负数进行位运算,负数也涉及到补码运算,如果对负数位移运算不理解可以先忽略负号当成正整数运行,然后运算出结果再加上负号。

提示 有符号右移n位,相当于操作数除以2n,例如代码第⑦行(a >>
2)表达式相当于(a / 22), 178 /
4所以结果等于12。另外,左位移n位,相当于操作数乘以2n,例如代码第⑩行(a <<
2)表达式相当于(a * 22),178 * 4所以结果等于712,类似的还有代码第⑧行。

赋值运算符

赋值运算符只是一种简写,一般用于变量自身的变化,例如a与其操作数进行运算结果再赋值给a,算术运算符和位运算符中的二元运算符都有对应的赋值运算符。具体说明参见表7-5。

表 7‑5 算术赋值运算符

运算符 名称 例子 说明
+= 加赋值 a += b 等价于a = a + b
-= 减赋值 a -= b 等价于a = a - b
*= 乘赋值 a *= b 等价于a = a * b
/= 除赋值 a /= b 等价于a = a / b
%= 取余赋值 a %= b 等价于a = a % b
**= 幂赋值 a **= b 等价于a = a ** b
//= 地板除法赋值 a //= b 等价于a = a // b
&= 位与赋值 a &= b 等价于a = a&b
|= 位或赋值 a |= b 等价于a = a|b
^= 位异或赋值 a ^= b 等价于a = a^b
<<= 左移赋值 a <<= b 等价于a = a<<b
>>= 右移赋值 a >>= b 等价于a = a>>b

示例代码如下:

# 代码文件:chapter7/7.5/hello.py

a = 1
b = 2

a += b  # 相当于a = a + b
print("a | b = {0}".format(a))  # 输出结果3

a += b + 3  # 相当于 a = a + b + 3
print("a + b + 3 = {0}".format(a))  # 输出结果7
a -= b  # 相当于a = a - b
print("a - b = {0}".format(a))  # 输出结果6

a *= b  # 相当于a = a * b
print("a * b = {0}".format(a))  # 输出结果12

a /= b  # 相当于a = a / b
print("a / b = {0}".format(a))  # 输出结果6

a %= b  # 相当于a = a % b
print("a % b = {0}".format(a))  # 输出结果0

a = 0b10110010
b = 0b01011110

a |= b
print("a | b = {0}".format(a))
a ^= b
print("a ^ b = {0}".format(a ^ b))

输出结果如下:

a | b = 3
a + b + 3 = 8
a - b = 6
a * b = 12
a / b = 6.0
a % b = 0.0
a | b = 254
a ^ b = 254

上述例子分别对整型进行了赋值运算,具体语句不再赘述。

其他运算符

除了前面介绍的主要运算符,Python还有一些其他运算符,本节先介绍其中两个“测试”相关重要的运算符,其他运算符会后面涉及到相关内容时再详细介绍。这两个“测试”运算符是:同一性测试运算符和成员测试运算符,所谓“测试”就是判断之意,因此他们的运算结果是布尔值,他们也属于关系运算符。

同一性测试运算符

同一性测试运算符就是测试两个对象是否同一个对象,类似于==运算符,不同之处,==是测试两个对象的内容是否相同,当然如果是同一对象==也返回True。

同一性测试运算符有两个:is和is not,is是判断是同一对象,is
not是判断不是同一对象。示例代码如下:

# coding=utf-8
# 代码文件:chapter7/7.6/ch7.6.1.py

class Person:       ①
    def __init__(self, name, age):
        self.name = name
        self.age = age

p1 = Person('Tony', 18)     
p2 = Person('Tony', 18)

print(p1 == p2)  # False    
print(p1 is p2)  # False

print(p1 != p2)  # True
print(p1 is not p2)  # True

上述代码第①行自定义类Person,它有两个实例变量name和age,然后创建了两个Person对象p1和p2,他们具有相同的name和age实例变量。那么是否可以说p1与p2是同一个对象(p1
is p2为True)?程序运行结果不是,因为这里实例化了两个Person对象(Person('Tony',
18)语句是创建对象)。

那么p1 ==
p2为什么会返回False呢?因为==虽然是比较两个对象的内容是否相当,但是也需要告诉对象比较的规则是什么,是比较name还是age?这需要在定义类时重写eq方法,指定比较规则。修改代码如下:

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __eq__(self, other):
        if self.name == other.name and self.age == other.age:
            return True
        else:
            return False


p1 = Person('Tony', 18)
p2 = Person('Tony', 18)

print(p1 == p2)  # True
print(p1 is p2)  # False

print(p1 != p2)  # False
print(p1 is not p2)  # True

上述代码重写eq方法,其中定义了只有在name和age都同时相当时,两个Person对象p1和p2才相等,即p1
== p2为True。注意p1 is
p2还是为False的。有关类和对象等细节问题读者想必要关心,只需要知道is和==两种运算符的不同即可。

成员测试运算符

成员测试运算符可以测试在一个序列(sequence)对象中是否包含某一个元素,成员测试运算符有两个:in和not
in,in是测试是否包含某一个元素,not in是测试是否不包含某一个元素。

示例代码如下:

# coding=utf-8
# 代码文件:chapter7/7.6/ch7.6.2.py

string_a = 'Hello'
print('e' in string_a)  # True      ①
print('ell' not in string_a)  # False   ②

list_a = [1, 2]
print(2 in list_a)  # True          ③
print(1 not in list_a)  # False     ④

上述代码中第①行是判断字符串Hello中是否包含e字符,第②行是判断字符串Hello中是否不包含e字符串ell,这里需要注意的是字符串本质也属于序列,此外还有列表和元组都属于序列,有关序列的知识会在第9章详细介绍。

代码第③行是判断list_a 列表中是否包含2元素,代码第④行是判断list_a
列表中是否不包含1元素。

运算符优先级

在一个表达式计算过程中,运算符的优先级非常重要。表7-6中从上到下优先级从高到低,同一行具有相同的优先级。

表 7‑6运算符优先级

优先级 运算符 说明
1 () 小括号
2 f(参数) 函数调用
3 [start:end], [start:end:step] 分片
4 [index] 下标
5 . 引用类成员
6 **
7 ~ 位反
8 +, - 正负号
9 *, /, % 乘法、除法、取余
10 +, - 加法、减法
11 <<, >> 位移
12 & 位与
13 ^ 位异或
14 | 位或
15 in, not in, is, is not, <, <=, >, >=,<>, !=, == 比较
16 not 逻辑非
17 and 逻辑与
18 or 逻辑或
19 lambda Lambda表达式

通过表7-6所示读者对运算符优先级有一个大体上了解,知道运算符优先级大体顺序从高到低是:算术运算符→位运算符→关系运算符→逻辑运算符→赋值运算符。还有一些运算符还没有介绍,会在后面的逐一介绍。

本章小结

通过对本章内容的学习,读者可以了解到Python语言运算符,这些运算符包括:算术运算符、关系运算符、逻辑运算符、位运算符和其他运算符。最后介绍了Python运算符优先级。

配套视频

http://www.zhijieketang.com/classroom/10/courses

配套源代码

http://www.zhijieketang.com/group/8

纸质版电商

京东:https://item.jd.com/12468732.html
当当:http://product.dangdang.com/25574315.html

作者微博:@tony_关东升
邮箱:eorient@sina.com
智捷课堂微信公共号:zhijieketang
Python读者服务QQ群:565736812

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容