python-操作符相关介绍(一)

    软件的过程就是数据处理的过程,前面我们讲了python的各种类型的数字,并没有去说操作符,我一直在想是讲完所有python的内置类型再去说这个问题,还是不用等到那么晚。思考再三,我觉得还是把python所遇到的操作符都说一遍,这种操作符很多人都耳熟能祥,但是温故而知新,相信再次的阅读能让你加深印象,初学者也可以通过本章的学习对操作符有一个深入的认知。

    说到操作符,我们不得不提到表达式,什么是表达式呢?很多人对表达式的理解并不是很深刻,这很正常,因为这两者本来在不同的语境下就会有点似是而非。如果排除语言本身的特点,我们可以认为表达式是处理数字最基本的单元,它是一个代码片段,可以返回一个值。说到这里,这和我们的操作符息息相关,我们都知道,我们执行一个操作,肯定是要得到一个返回值的。当然说到这里,并不是说表达式里面必含操作符,其实一个单独的变量,常量也可以是表达式。看如下的代码:

a = 5
b = a
c = "123"
d = abs(a)
e = a + b
a
"abcd"

如果说等号后面是表达式,我想大家都不会觉得惊讶,因为表达式就是返回一个值。和表达式相对另外一个概念是语句,语句一般认为是大部分包含了表达式,就是可以独立运行的语言片段,表达式必须包含在语句中才行运行。但是细心的同学会发现一个奇怪的现象,最后一行代码只有一个字符串常量,上面说一个常量也是一个表达式,但是现在这个"abcd"单独一行,如果你运行它的话,不会出错。如果是C语言中,这种肯定会出错。为什么呢?因为C认为这个是表达式,而不是语句,但是python不这么认为,python模糊了表达式和语句的界限,有些看似是表达式,也是语句。虽然直接写"abcd"单独一行没什么实际意义,但是却不会出错。

    总的来讲表达式返回一个值,但是语句一般不会,但是对于python来讲,它模糊了语句和表达式的概念,很多既是语句又是表达式。刚才说了语句一般包含了表达式,那肯定也有例外的情况,对python来讲,pass,break,continue,这种单独的关键字就是一个语句,是不包含表达式的。

    通过上面的讲述,如果你还是不能完全明白,这也没关系,我们只知道表达式肯定会返回值就行了,尤其是对python来讲,语句和表达式界限模糊,这并不影响你书写代码。好了,接下来我们来谈操作符。

1,加法(+)和减法(-)

    这两个操作符一般用于数字的计算,但是也用于集合,字符串。看下面的代码:

a = 1 + 3
b = 1. +3
c = 1 - 3
d = 1.0 - 3
e = "abc" + "ef"
f = {1,2,3} - {1}
print("a = {},b = {},c = {},d = {}, \
e = {},f = {}".format(a,b,c,d,e,f))


结果:a = 4,b = 4.0,c = -2,d = -2.0, e = abcef,f = {2, 3}

有一点需要说明,当整数和浮点数相遇,都需要转换成浮点数,然后再计算。对于字符串,只支持相加的操作,对于集合,只支持相减的操作,也就是集合的交集。我们发现+,- 可以用在不同的对象上,这就是操作符的重载,虽然我们觉得这个理所当然,但是这其实都是语言背后的实现,回头专门讲操作符的重载。同时还有一点,字符串不能和其他类型相加,例如a = "123" + 1这个是非法的,但在java中是可以的。

2,乘法/重复(*),除法(/),floor 除法(//),余数/格式化(%),看下下面的代码:

a = 2 * 3
b = 2.0 * 3
c = 4 / 2
d = 4 / 2.0
#e = "123" * 3.0
e = "123" * 3
f = 4 // 3
g = 4 // 3.0
h = 4 // -3
i = 4 % 3
j = 4 % -3.0

print("a = {},b = {},c = {},d = {}, \
e = {},f = {},g={}, h = {}, i = {}, \
j = {}".format(a, b, c, d, e, f, g, h, i, j))

‘’‘
结果:a = 6,b = 6.0,c = 2.0,d = 2.0, 
e = 123123123,f = 1,g=1.0, h = -2, i = 1, j = -2.0
’‘’

首先 a 和 b 的结果说明一个问题,整数和浮点数相乘,都会自动转换为浮点数。对于字符串的乘法,表示重复的次数,可以看e的表达式中的数字必须是整数,如果是浮点数会报错。c 和 d表示除法,看到结果都2.0,不论有没有浮点数,结果都是浮点数。这是因为python3.0对于除法都是真除法,python2.6的话,3/2 的结果是1 ,只有 3/2.0,才会是1.5,当然,现在估计也没有太多程序要用这么古老的版本,大家可以忽略了。

    f的值是1,g的结果是1.0,这个和上面讲的乘法一样,如果有浮点数,直接转换为浮点数在计算,因为floor除法的结果就是小于等于除法结果的最小整数,4/3的结果是1.3333,所以取整数是1,当然这个最小整数不太精确,因为当有浮点数的时候,结果就是1.0了。对于h结果是-2,因为小于等于-1.3333的整数是-2。

    i和j是模除或者取余数,i的结果是1,这个符合预期,对于4%-3,我可以用公式算一下,假设a是被除数,b是除数,r是余数,q是商,则 a = b*q +  r 则r = a-b*q

带入当前的参数则r = 4 - (-2 * -3 )= -2,其中q=-2,这是为什么呢?4/-3的结果是-1.33333,他的整数部分肯定是比这个结果小的那个整数,然后我们才能有余数,所以我们取-2,如果是4/3,的结果是1.33333,比这个小的整数是1,所以套用公式,i的结果就是4-1*3=1。

floor和trunc

    math的这个模块里面提供了两个函数,其中floor和 //的的效果是一样的。例如math.floor(-2.8),结果是3,math.floor(2.8)结果是2,都是取小于当前数的最小整数,因为负数数字越大值越小,所以-2.8取值为-3。但是某些时候,我们可能只是想截断,就是直接去除小数部分,我们可以用math.trunc,math.trunc(-2.8)的结果是-2,它只是截断,同理,math.trunc(2.8)的结果是2。

百分号(%)不仅可以表示取余数,也可以用于字符串格式化。在python3.0之前,这个是字符串格式化的常用格式,我们看下代码:

print("%d" % 5)#5
print("%5d" % 5)#    5
print("%+5d" % 5)#   +5
print("%-5d" % 5)#5
print("%o" % 13)#15
print("%x" % 13)#d
print("%.2f" % 5)#5.00
print("%s" % "www")#www
print("a=%s,b=%d,c=%6f" % ("abc", 5, 7))#a=abc,b=5,c=7.000000

格式化的参数有很多,不需要都记住,记住最常用的就可以了,字符串里面通过%来定位格式化形式,例如%-5d,-号表示左对齐,5表示最小的宽度,d表示输出的是十进制整数,如果这个数没有5位,则在后面补空格,如果没有这个-号,那就是右对齐,在左边补空格,如果这个数,超过了5位,按照实际的宽度表示。d既然表示十进制整数,那必然也有8进制,用字母o表示,x表示16进制,对于浮点数用f,其中.2表示两位小数,你也可以在. 前面加上数字表示宽度。s表示打印字符串。 最后一行代码,可以一下格式化多个变量,其中后面的参数要用元组。 python的这个字符串格式化方式确实有点怪怪的,总感觉不伦不类,没有美感,所以在python3.0之后出现了一个format函数,它使用起来就变得比较符合正常的习惯了。有兴趣的可以自行查看format的用法。

3,逻辑与(and)或(or)非(not)

    不像Java或者C,python用and,or,not来表示与或非,java或者c用 &&,||,!来表示与或非。我猜想可能是为了和位运算区分。其中 X and y,如果X表达式为假,则Y不会被计算,结果为假,如果X为真,再去计算Y,如果Y为真,则结果为真,如果Y为假,结果为假。X or Y,如果X为真,则不去计算Y的值,直接结果为真,如果X为假,则计算Y的值,如果Y为真,则结果为真,如果Y为假则结果为假。not Y,如果Y为真,则结果为假,如果Y为假,则结果为真。看如下代码:

a = 3 > 2 and 4 < 2
b = 3 < 2 and 4 < 2
c = 3 > 2 or 3
d = 3 > 2 and 3
e = not 4
f = 1==True
print("a=%s,b=%s,c=%s,d=%s,e=%s" % (a, b, c, d, e))
#结果:a=False,b=False,c=True,d=3,e=False

对于a,因为是与,必须两边同时为真才是真,因为4<2是假,所以a的结果是False,对于b两边都为真,所以结果为True。c是逻辑或,一个为真便为真,因为3>2,所以直接返回,结果为True,但是对于d,需要两者都为真,我们发现d的的值是3,而不是True,这说明这个逻辑运算返回的是最后一个计算的表达式的值,而不是真或者假,所以这个和Java是不同的,java逻辑运算操作数必须是布尔类型的,java不能将1转化为true,但是f的结果是True,说明python中True的值就是1。最后说一下not 这个运算符如果后面的表达式为真,则结果为假,如果表达式为假,则结果真。对于e,python延续了C的bool类型的处理方式,非0的数皆为真。所以4为真,not 4 结果就是假的False。这个和 and or 稍稍不同,因为and or返回最后一个计算的表达式的值,而且not是对这个值转化为bool的值取反再返回。

4,位运算: 位或集合并集(|),位与,集合交集(&),位异或(^)

位运算用的不是很经常,但是如果你需要一个整数同时保存多个状态的话,那么位运算是一个好方法。前面我们学过数字计算机的内存表示,我们用每个位代表一种状态的开关,例如我们有四个状态,这四个状态不是互斥的,可以并存,用1表示有这种状态,用0表示没这种状态。例如我们有四个技能,分别是琴棋书画,一个人可以拥有0个或者多个这种技能,我们用四位来表示这个技能,例如0001,表示这个人有绘画的技能,0010,表示这个人有书法技能,0100表示这个人有下棋的技能,1000表示这个人有弹琴技能。

所以一个人如果没有一个技能的话,那么四个位全是0,值就是0,如果这个人满技能四个位全是1111,值就是15,我们可以用琴棋书画当掩码,和这个人的技能取位与,取完之后,如果这个数不为0或者是等于这个掩码,我们就说这个人有这个技能。因为很多人可能没有接触过C,所以对于位运算比较陌生,所以这里我们介绍的详细点,请看下面的代码:

a = 0b1000 #琴,也可以写成a=8
b = 0b0100 #棋,也可以写成b=4
c = 0b0010 #书,也可以写成c=2
d = 0b0001 #画,也可以西城d=1


def get_skills(skills):
    #记录skill
    num = ""
    print("参数值:{}".format(bin(skills)))
    if skills & a == a: #这个条件也可以写成skills & a != 0
        num = num + "琴"
    if skills & b == b:
        num = num + "棋"
    if skills & c == c:
        num = num + "书"
    if skills & d == d:
        num = num + "画"
    if len(num) == 0:
        print("have no skill \n")
    else:
        print("have the skill:%s\n" % num)

get_skills(0b1010)
#结果:参数值:0b1010 
#    have the skill:琴书
get_skills(15)
#结果:参数值:0b1111
#     have the skill:琴棋书画
get_skills(0)
#结果:参数值:0b0
#     have no skill 

代码我们定义了abcd四个变量分别代表琴棋书画,来判断有没有该技能,就是用该技能的掩码与这个技能变量取按位与,例如a是1000,输入是1010,那么对应的每位取与,从左到右,a的第一位是1,技能变量skills的第一位是1,所以1&1是1,这就算出了第一位的值,然后a的第二位是0,skills的第二位是0,那么0&0是0,所以算出了第二位是0,a的第三位是0,skills的第三位是1,0&1是0,所以算出第三位是0,a的第四位是0,skills的第四位是0,0&0结果是0,所以最后结果是1000,这个值就是a本身,所以与a取与后还是a,我们就判断出有这个技能。这是继续与b按位取与,同样的过程,算出结果是0000,所以不存在这个棋的技能,然后继续与c按位取与,得出结果是0010,所以存在这个书的技能,最后与d按位取与,得到0000,所以不存在画这个技能。

其实0b1010这种书写形式,值是为了方便看位,我们也可以输入十进制10,内存表示一样的都是1010,如果对二进制表示有疑惑,建议翻看我之前的这篇文章pyhon-整数以及内存表示方式。

通过上面的代码,我们知道了按位与的用法,然后按位或(|),就是对应的两个位有一个为1的话,这个位的或值位1,否则为0,异或(^)就是对应的两个位不同,则值为1,否则位0。请看下面的代码片段:

a = 0b1000 | 0b0001
b = 0b1001 ^ 0b1000

print("a={},b={}".format( bin(a), bin(b)))

#结果:a=0b1001,b=0b1

输出的b是0xb1,因为高位是都是0,所这么打印了,等于0b0001,大家可以自己心里过于边算法,加深记忆。

之前讲减法的时候,两个集合可以减,取交集,但是却不能相加。现在|和 &可以完成集合的并集和交集。看下面代码片段:

a = {1, 2, 3, 4}
b = {4, 5, 6}

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

#结果:a | b={1, 2, 3, 4, 5, 6},a & b={4}, a ^ b ={1, 2, 3, 5, 6}

a | b,这是将两个集合合并,生成了一个新的集合{1, 2, 3, 4, 5, 6},包含了a和b的所有元素。a &  b,取这两个集合的共有元素,只有元素4,所以结果是生成了一个新的结合{4},a ^ b 就是取这两个集合的非共同元素,所以就是除了4以外的所有元素,结果是生成新集合{1, 2, 3, 5, 6}。

好了,操作符的第一部分就讲完了,欢迎大家给我留言反馈。

  

   

你可能感兴趣的:(python,开发语言)