软件的过程就是数据处理的过程前面我们讲了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来讲passbreakcontinue这种单独的关键字就是一个语句是不包含表达式的。通过上面的讲述如果你还是不能完全明白这也没关系我们只知道表达式肯定会返回值就行了尤其是对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,g1.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的值是1g的结果是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*31。floor和truncmath的这个模块里面提供了两个函数其中floor和 //的的效果是一样的。例如math.floor(-2.8),结果是3math.floor(2.8)结果是2都是取小于当前数的最小整数因为负数数字越大值越小所以-2.8取值为-3。但是某些时候我们可能只是想截断就是直接去除小数部分我们可以用math.truncmath.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))#aabc,b5,c7.000000格式化的参数有很多不需要都记住记住最常用的就可以了字符串里面通过%来定位格式化形式例如%-5d-号表示左对齐5表示最小的宽度d表示输出的是十进制整数如果这个数没有5位则在后面补空格如果没有这个-号那就是右对齐在左边补空格如果这个数超过了5位按照实际的宽度表示。d既然表示十进制整数那必然也有8进制用字母o表示x表示16进制对于浮点数用f其中.2表示两位小数你也可以在. 前面加上数字表示宽度。s表示打印字符串。 最后一行代码可以一下格式化多个变量其中后面的参数要用元组。 python的这个字符串格式化方式确实有点怪怪的总感觉不伦不类没有美感所以在python3.0之后出现了一个format函数它使用起来就变得比较符合正常的习惯了。有兴趣的可以自行查看format的用法。3逻辑与(and)或(or)非(not)不像Java或者Cpython用andornot来表示与或非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 1True print(a%s,b%s,c%s,d%s,e%s % (a, b, c, d, e)) #结果aFalse,bFalse,cTrue,d3,eFalse对于a因为是与必须两边同时为真才是真因为42是假所以a的结果是False对于b两边都为真所以结果为True。c是逻辑或一个为真便为真因为32所以直接返回结果为True但是对于d需要两者都为真我们发现d的的值是3而不是True这说明这个逻辑运算返回的是最后一个计算的表达式的值而不是真或者假所以这个和Java是不同的java逻辑运算操作数必须是布尔类型的java不能将1转化为true但是f的结果是True说明python中True的值就是1。最后说一下not 这个运算符如果后面的表达式为真则结果为假如果表达式为假则结果真。对于epython延续了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 #琴也可以写成a8 b 0b0100 #棋也可以写成b4 c 0b0010 #书也可以写成c2 d 0b0001 #画也可以西城d1 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所以11是1这就算出了第一位的值然后a的第二位是0skills的第二位是0那么00是0所以算出了第二位是0a的第三位是0skills的第三位是101是0所以算出第三位是0a的第四位是0skills的第四位是000结果是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))) #结果a0b1001,b0b1输出的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}。好了操作符的第一部分就讲完了欢迎大家给我留言反馈。