作者: Jim Wang 公众号: 巴博萨船长

Python运算符简介

程序语言运算符就是对数据操作的表示方法,即数据是如何处理的。理解运算符,在查看代码的时候就能理解代码中数据是如何加工处理的,掌握运算符就能过对数据按照自己所想操作加工处理。一般的教程或者学习资料会将操作符分为:算术运算符、连接运算符、关系运算符、赋值运算符和逻辑运算符。这也是普遍的共识。在本文中,我们稍作改变,我们分组分章节介绍,之所以这样,也是一些运算符好之间也有一定的关系。Python中有一种比较特殊的运算符,即身份运算,会单独介绍一下。位运算从本质上来讲也属于算术表达的一种,但是由于其比较特殊,常在硬件设计方面应用较多,日常的应用设计很少遇到,所以在文中也用单独的章节介绍。

算术运算符与赋值运算符

算术运算符

算术计算,在此是指常见的十进制计算,包括加法➕,减法➖,乘法✖️,除法➗,都是常见的数学计算,除了表现符号与数学课本上不一致,如,Python乘法(_),除法(/)。任何人理解这些符号的意义,在这里就不在赘述。在此我们仅介绍取模取整, 和*幂运算(包括逆运算,即对数运算)_,Python中也有math或cmath模块,提供专门的函数来帮助你进行更复杂的算术运算,如有需要可以关注一下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/usr/bin/python
# -*- coding: UTF-8 -*-
a = 7
b = 2

c = a // b
print "取整 c 的值为:", c

c = a % b
print "取模 c 的值为:", c

c = a ** b
print "幂运算 c 的值为:", c

d = c ** (1./b)
print "幂的逆运算 d 的值为:", d

输出结果:

1
2
3
4
取整 c 的值为: 3
取模 c 的值为: 1
幂运算 c 的值为: 49
幂的逆运算 d 的值为: 7.0

取整就是得到除法的结果的整数部分,取模就是得到除法的结果的余数(切记并非小数部分),幂运算可以处理平方,三次方等,幂运算符也可以处理幂运算的逆运算,即对数运算。上面代码1后面的那个点**.**就表示1要按照浮点数进行运算操作。

赋值运算符

赋值运算就是将算数运算结果赋值于变量,符号为**=**。 算术运算符➕与赋值的组合能过更简化代码,也就是常说的变量自加。即算术运算过程中等号左边的变量也作为算术运算的参与者,简单举个例子。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#!/usr/bin/python
# -*- coding: utf-8 -*-

a = 7
b = 3

# a + b
a += b
print "加法与赋值的值为:%s" % a
# a - b
a -= b
print "加法与赋值的值为:%s" % a
# a * b
a *= b
print "乘法与赋值的值为:%s" % a
# a * b
a *= b
print "乘法与赋值的值为:%s" % a
# a ** b
a **= b
print "幂与赋值的值为:%s" % a
# a // b
a //= b
print "取整与赋值的值为:%s" % a
# a % b
a %= b
print "取模与赋值的值为:%s" % a

输出结果:

1
2
3
4
5
6
7
加法与赋值的值为:10
加法与赋值的值为:7
乘法与赋值的值为:21
乘法与赋值的值为:63
幂与赋值的值为:250047
取整与赋值的值为:83349
取模与赋值的值为:0

由于变量a参与了算术计算,所以变量a的值一直发生了变化,所以不要怀疑结果出了问题。

比较运算符,成员运算符,身份运算符

这个章节的运算符,在编程中主要用于与条件语句进行配合,并返回True 与 Flase布尔值的运算符。

比较运算符

比较运算符比较容易理解:等于==, 不等于!=或者<>, 大于>与大于且等于>=和小于<与小于且等于<= 。关于这些也就不再举例,需要注意的是比较的两个元素应该具有相同的数据类型,或者都是类的实例。

成员运算符

成员运算符是用于检查某一值是否在可迭代的对象里面,返回值True或False。

可迭代的对象Iterable并不等于迭代器Iterator。Python中这两种定义有部分相同,但是还是有一些细节的差异的。为了便于区分,这里给你一个简单的方法来区别彼此,能用for进行循环迭代的都成为可迭代对象,能被next()调用不断返回下一个值的对象为迭代器。有关两者更细节话的区别,我们在以后的文章中介绍。

可迭代的对象是一种集合数据类型,如list,tuple,dict,set与str等。成员运算符为”in”和”not in”。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#!/usr/bin/python
# -*- coding: UTF-8 -*-

a = 10
b = 21
c = "a"
d = 1
lt = [11, 20, 10, 4, 5 ]
tup = (11, 20, 10, 4, 5)
ss = set([11, 20, 10, 4, 5])
dic = { "a" : 2, "b" : 1}

if a in lt:
print "变量 a 在给定的列表中"
else:
print "变量 a 不在给定的列表中"


if b not in lt:
print "变量 b 不在给定的tuple 中"
else:
print "变量 b 在给定的tuple中"


if b not in ss:
print "变量 b 不在给定的set 中"
else:
print "变量 b 在给定的set 中"


if c in dic:
print "变量 c 在给定的dict中"
else:
print "变量 c 不在给定的dict中"

if d in dic:
print "变量 d 在给定的dict中"
else:
print "变量 d 不在给定的dict中"

输出结果:

1
2
3
4
5
变量 a 在给定的列表中
变量 b 不在给定的tuple 中
变量 b 不在给定的set 中
变量 c 在给定的dict中
变量 d 不在给定的dict中

需要注意的是,在Python 2.x中,成员运算符与dict结合使用的时候等效于has_key()函数,即用于检查是否字典dict变量存在某一键。但是Python 3.x不再具有该函数,所以只能用成员运算符。为了保证代码的兼容性和一致性,建议优先选用成员运算符来判断某一键存在与字典之中。在此我们也做个延伸,请看下方例子。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#!/usr/bin/python
# -*- coding: UTF-8 -*-

e = {"a" : 1, "b" : 2, "c" : 3}

akeys = e.keys()

if "a" in e:
print "变量 'a' 在给定的dict中"
else:
print "变量 'a' 不在给定的dict中"

if "a" in akeys:
print "变量 'a' 在给定的dict中"
else:
print "变量 'a' 不在给定的dict中"

del e['a']

if "a" in e:
print "变量 'a' 在给定的dict中"
else:
print "变量 'a' 不在给定的dict中"

if "a" in akeys:
print "变量 'a' 在给定的dict中"
else:
print "变量 'a' 不在给定的dict中"

输出结果:

1
2
3
4
5
6
变量 'a' 在给定的dict中
变量 'a' 在给定的dict中
变量 'a' 在给定的dict中
变量 'a' 不在给定的dict中
变量 'a' 不在给定的dict中
变量 'a' 在给定的dict中

有人可能会想,我在代码中某一处获取一个字典的所有键的列表,然后在以后需要判断的时候,直接使用这个键的列表来判断,这种想法是很危险的,也是不可取的。请参照上述例子。字典键的判断最好是按需实时进行,以避免误判。

身份运算符

身份运算符用于比较两个对象的储存单元。也就是判断两个引用的对象是否为同一个,即两个在储存意义上的一致。需要注意的是,Python程序中,值相同并不意味着”一致”,”一致”必然值相同

  • is ,判断是否一致,是否引用自同一个对象 。 a is b 等效于 id(a) == id(b), id() 函数用于获取内存地址,地址一致则为同一个对象 。
  • not is, 与not 结合,意指取上述内容反义。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#!/usr/bin/python
# -*- coding: UTF-8 -*-

a = 10
b = 10

if a is b :
print "a 和 b 有相同的标识,一致"
else:
print "a 和 b 没有相同的标识,不一致"

b = 10

if a is b :
print "a 和 b 有相同的标识,一致"
else:
print "a 和 b 没有相同的标识,不一致"

c = [1, 2, 3]
d = c

if c is d :
print "c 和 d 有相同的标识,一致"
else:
print "c 和 d 没有相同的标识,不一致"

c = [1, 2, 3]
d = c[:]

if c is d :
print "c 和 d 有相同的标识,一致"
else:
print "c 和 d 没有相同的标识,不一致"

输出结果:

1
2
3
4
a 和 b 有相同的标识,一致
a 和 b 有相同的标识,一致
c 和 d 有相同的标识,一致
c 和 d 没有相同的标识,不一致

从上述输出结果可以得知,整数(也包含浮点数)的变量,在值相同的情况下,赋值或者从新赋值,其引用的是同一块内存,列表在赋值的时候,上文中,从c赋值到d的时候也是引用的同一块内存。但是如果需要保证列表c和d在使用时相互之间不影响,就要对d进行重新赋值。这些都是需要在编写代码时候考虑的,从而避免不必要的错误。

逻辑运算符

逻辑运算符常在条件语句和while循环语句中与上述的比较运算符,成员运算符与身份运算符结合使用。用于结合两个条件,或者否定某一条件。但是需要注意的是,其他语言中的逻辑运算符并不在Python语言中兼容,在程序代码转换时候需要注意。

逻辑运算符(其他语言) 逻辑运算符(Python)
&& and
|| or
not

代码实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#!/usr/bin/python
# -*- coding: UTF-8 -*-

a = True
b = True

if a and b : # 等效其他语言的 &&
print "变量 a 和 b 都为 true"
else:
print "变量 a 和 b 有一个不为 true"

if a or b : # 等效其他语言的 ||
print "变量 a 和 b 都为 true,或其中一个变量为 true"
else:
print "变量 a 和 b 都不为 true"

# 修改变量 a 的值
a = False
if a and b :
print "变量 a 和 b 都为 true"
else:
print "变量 a 和 b 有一个不为 true"

if a or b :
print "变量 a 和 b 都为 true,或其中一个变量为 true"
else:
print "变量 a 和 b 都不为 true"

if not( a and b ): # 等效其他语言的 !
print "变量 a 和 b 都为 false,或其中一个变量为 false"
else:
print "变量 a 和 b 都为 true"

输出结果:

1
2
3
4
5
变量 a 和 b 都为 true
变量 a 和 b 都为 true,或其中一个变量为 true
变量 a 和 b 有一个不为 true
变量 a 和 b 都为 true,或其中一个变量为 true
变量 a 和 b 都为 false,或其中一个变量为 false

以上介绍的都是常用的运算符,在日常程序设计实现时常常用到,对比其他编程语言Python有一下独有的运算符,或一些运算符在Python中的表现形式会有一些不同,都需要在实现代码时注意。

位运算符

位运算符,会在硬件编程中用到,主要处理二进制的计算。在日常任务中并不常见,但是它也是学习进而掌握一种编程语言的必备知识。在我经历的任务中,比如需要得到RGB颜色的整数或者16进制数。RGB整数与RBG三色值之间的相互转换时,用到过位运算符。Python的位运算符与其他语言的位运算符一致,在本节我们介绍一下位运算符。

  • &**, 二进制的”**与“操作。二进制相应位都位1,则结果为1,反之为0。
  • |**, 二进制的”**或“操作。结合逻辑运算符来理解,二进制相应位有一个位1时,结果就为1,反之为0。
  • ^,二进制的”异或“操作。二进制相应位不同时,结果为1,反之为0。
  • *~**, 二进制的”\*取反”操作。二进制数按位取反,1变为0,0变为1。
  • <<**,二进制的”**左移“操作。由符号”<<”右边的数字决定向左移动的位数,高位丢弃,低位补0。
  • >>**,二进制的”**右移“操作。由符号”>>”右边的数字决定向左移动的位数,高位补0。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#!/usr/bin/python
# -*- coding: UTF-8 -*-

a = 50 # 50 = 0011 0010
b = 14 # 14 = 0000 1110
c = 0

c = a & b; # 2 = 0000 0010
print "c 的值为dec:", c
print "c 的值为bin:{:#010b}".format(c)

c = a | b; # 62 = 0011 1110
print "c 的值为dec:", c
print "c 的值为bin:{:#010b}".format(c)

c = a ^ b; # 60 = 0011 1100
print "c 的值为dec:", c
print "c 的值为bin:{:#010b}".format(c)

c = ~a; # -51 = -0011 0011
print "c 的值为dec:", c
print "c 的值为bin:{:#010b}".format(c)

c = a << 2; # 200 = 1100 1000
print "c 的值为dec:", c
print "c 的值为bin:{:#010b}".format(c)

c = a >> 2; # 12 = 0000 1100
print "c 的值为dec:", c
print "c 的值为bin:{:#010b}".format(c)

输出结果:

1
2
3
4
5
6
7
8
9
10
11
12
c 的值为dec: 2
c 的值为bin:0b00000010
c 的值为dec: 62
c 的值为bin:0b00111110
c 的值为dec: 60
c 的值为bin:0b00111100
c 的值为dec: -51
c 的值为bin:-0b0110011
c 的值为dec: 200
c 的值为bin:0b11001000
c 的值为dec: 12
c 的值为bin:0b00001100

可使用bin()内置函数来获取而数的二进制字符串,但是如果要更好的格式化字符串,即带有前补零和”0b”标示的二进制字符串时,则可使用{:#010b}”.format(value)来实现。

运算符之间的优先级

尽然编程语言中的运算符种类如此之多,在相互之间结合使用的时候,哪个操作符会被先执行,这就是操作符之间的优先级问题。在此准备一表单,运算符优先级以数字形式表示,数值越小则表示优先级越高,即在运行时会被优先执行。

优先级 运算符 描述
1 ** 指数运算,最高优先级
2 ~ + - 位的取反操作,一元加号与减号(标示数的正负)
3 * / % // 乘,除,取模和取整
4 + - 加法,减法
5 >>, << 位操作左移,位操作右移
6 & 位操作 与
7 ^ , | 位操作 异或 与 或
8 <=, <>, >= 比较运算符
9 <>, ==, != 等于,不等于运算符
10 =, %=, /=, -=, +=, =, *= 赋值运算符,自加,自减等
11 is, is not 身份运算符
12 in, not in 成员运算符
13 not, and, or 逻辑运算符

传统数学计算时的优先级也在上述列表中得到体现,如,乘除法运算优先与加减法运算。括号可以提升优先级。操作符的优先级结合数学计算的优先级,又加上了编程语言的特有预算符的优先级。掌握运算符的优先级,没有什么技巧,只有在不断的实践中加深印象,从而实现熟练使用。

运算符扩展— 函数注释 Function Annotations

Python 3.x 增加了一个新的特性Feature,叫做函数注释Function Annotations。其表现特征是函数定义是,在函数定义括号内使用”:”来注释参数,在右括号外添加”->”符号,来注释返回值。

我们来举个例子,传统意义上定义函数为:

1
2
3
4
5
def func(a, b, c):
return a + b + c

>>> func(1, 2, 3)
6

添加注释的函数可以用如下形式表示:

1
2
3
4
5
def func(a: 'spam', b: (1, 10), c: float) -> int:
return a + b + c

>>> func(1, 2, 3)
6

参数后的注释,即”:”后的内容可以是任何形式,返回值的注释需要注意返回值的数据类型必须为Python的数据类型。

函数的注视添加之后会以属性的形式保存在函数中。查看函数注释可以使用如下语句:

1
2
>>> func.__annotations__
{'c': <class 'float'>, 'a': 'spam', 'b': (1, 10), 'return': <class 'int'>}

函数注释只是一种附加的特征,其并不影响函数的传统方式的使用。参数的注释只是一种帮助信息,并没有现实意义上的约束力。

小结

编程语言的运算符,是学习编程语言的基础。熟练掌握才能进行其他方面知识的学习。目前网络中存在很多Python的教程,本人也无意重复别人做过的事情,只是将自己在学习这门编程语言的时的一些感悟,也对某一部分内容的个人见解与内容的延伸以文字的方式记录下来,这样在查看别的文章的时候,如果遇到一些基本知识的内容,就可以在不跳转别的教程网站的情况下,解决学习中遇到的问题,方便读者也方便自己。欢迎订阅我的个人微信公众号。


版权声明:
文章首发于 Jim Wang's blog , 转载文章请务必以超链接形式标明文章出处,作者信息及本版权声明。