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

张开发
2026/4/9 15:59:41 15 分钟阅读

分享文章

python-操作符相关介绍(二)
上一章我们说了部分的操作符今天继续讲操作符。1一元减法(-) 识别()这两个符号和二元的加减法一样的符号一样但是只有一个操作数例如-11。其实负数的话我们用的就是一元减法整数的话这个号可以不带但是带上也没啥问题记住这个号是一元的看一下下面的代码。a -1 1 print(a{}.format(a)) #结果a0上面的a的表达式中第一个加号是二元运算符第二个加号是一元运算符表示负一加正一结果就是0。 第二个加号实际上可以省略。2按位求补~这个操作符就是将内存中表示数字比特位每一位取反就是将0变成11变成0举个例子我们如果用四bit表示一个数那么5在内存中的表示就是0101-5在内存中表示就是1011这是~5就是1010值就变成了-6同样~(-5)就是0100值就变成了4。看过我之前文章的同学可能会对补码的定义还有印象但是现在这个概念和我们之前谈的补码又有不同。重点是前两个字按位说明这个是对每一位进行操作的。如果你对数字在内存中的表示不明白建议看看我之前的文章pyhon-整数以及内存表示方式。有时候温故而知新所以我又写了转换位内存表示的代码大家可以再温习一下内存中bit的转化。 获取内存bit值 a: 整数 b: 内存存储的bit数 返回一个bit列表 def get_memory_bit(a, bits_num): minus False # 如果a是负数则取a的绝对值 if a 0: a abs(a) minus True #用于存放比特 bits [] #如果a大于0则不停的将a的余数倒序存入列表将a更新位商 while a 0: #取余数 tmp a % 2 #将余数倒序插入列表也就是始终在0的位置插入余数 bits.insert(0, tmp) # Floor除法值是取整数部分 a a // 2 #如果整个列表的长度小于用于存放bit数则在0的位置不断的插入0 while len(bits) bits_num: bits.insert(0, 0) #如果是负数则开始求负数的补码内存中我们都用补码表示数字 if minus: i 0 #先求出反码就是每一位取反也就是如果是0则变成1,如果是1则变成0 while i len(bits): if bits[i] 0: bits[i] 1 else: bits[i] 0 i 1 i len(bits) - 1 #将最后一位加1如果等2说明有进位将当前位置0继续循环 # 如果不等于2将当前位置1循环结束 while i 0: if bits[i] 1 2: bits[i] 0 else: bits[i] 1 break i i - 1 return bits a 5 b -5 print(get_memory_bit(a, 4), get_memory_bit(b, 4)) print(~a{},~b{}.format(get_memory_bit(~a, 4), get_memory_bit(~b, 4))) #结果 #[0, 1, 0, 1] [1, 0, 1, 1] #~a[1, 0, 1, 0],~b[0, 1, 0, 0]为了表明内存中是如何存储数字的我写了get_memory_bit这样的函数他可以模拟出内存的表示这个函数需要你给出用多少位来表示数字因为最高位是代表符号位所以需要知道有多少位。从输出的结果来看~确实是将内存中每一个位取反了。3冥运算(**)这个运算符表示多少次方例如x**y就是x的y次方这是个纯数学运算我们可能用到的不多简单下一下代码:a 2**3 b (-2)**4 print(a{},b{}.format(a, b)) #结果a8,b16需要注意的是运算符的优先级其实我们一直没有谈运算符的优先级因为运算符排优先级是很复杂的事情要记住所有是很困难的所以在你不确定的时候只需要加括号就行就像b表达式中的-2加了括号因为一元运算符-的优先级是比冥运算的优先级低所以如果不加括号就会先进行冥运算这样结果就是-16了。4比较运算符集合子集超集相等不等 !上一篇我们讲逻辑与或非的时候其实就已经用了比较运算符比较运算符会返回一个布尔值看一下下面的代码a 1 3 b 1 3 c 2 2 d 2 2 e 2 ! 2 f 2 1.01.0 g 2 2.000000000000001 g1 2 2.0000000000000001 h 0.10.10.1 - 0.1 - 0.1 - 0.1 0 print(a{},b{},c{},d{}\n\ e{},f{},g{},g1{},h{}.format(a, b, c, d, e, f, g, g1, h)) #结果aTrue,bFalse,cTrue,dTrue # eFalse,fTrue,gFalse,g1True,hFalse注意格式化字符串的第二个\这个是python的代码换行符。我这样做的原因是因为不想让你看代码的时候往左滑动。这里面注意和,c和d的表达式都为真因为的含义是大于或者等于只要满足一个条件就为真同样 的含义就是小于或者等于满足一个条件为真。另外注意g和g1这两个结果是不一样的之前我们说过如果两个操作数如果一个是整数一个是浮点数那么就会将整数转化为浮点数再计算。浮点数是不精确的所以只要小数位足够多就会产生为真的情况这种情况一般是比较极端的因为实际的操作中一般不会出现这么大精度的比较。但是h的表表达式发生的概率还是相对较大的这个结果是假因为左边的0.10.10.1 - 0.1 - 0.1 - 0.1结果是一个非0的很小的数所以如果有浮点数表达式和0的比较一定要非常小心尽量避免出现这种情况。这些比较运算符同样适用于集合当然我们说集合的关系不是大小而是谁是谁的超集谁是谁的子集或者两者相等看下面的代码a {1} {3} b {1, 3} {3} c {1, 2, 3} {1, 2, 3} d {2} {2} e {2} ! {2} f {1, 2} {2, 1} print(a{},b{},c{},d{}\n\ e{},f{}.format(a, b, c, d, e, f)) #结果aFalse,bTrue,cTrue,dTrue # eFalse,fTrue集合的比较需要注意一点就是这两个集合必须有包含和被包含的才能比较如果这两个集合都有对方没有的元素那么不论是任何类型的比较都是False除了不等于就比如a的表达式这两个集合都存在对方都没有的元素所以不论是大于小于等于结果都是False。5右移和左移这和按位求补~以及位运算 | ^一样都是涉及到了数字在内存的中表示方式。因为python只要内存允许可以表示无穷大的数所以理论上python的左移不会溢出。当右移的时候最高位往右移动最低位舍去。因为最高位已经右移当前最高位的值和之前的最高位的值一样。这样做是为了保证右移之后这个数的正负不会变。左移的时候因为整体向左移动因为python内存足够的情况下可以表示无穷大的数所以python左移后位数会越来越多最低位补0。左移可以看作是将这个数乘以2而右移则是floor除法。看一下下面的代码a -1 2 a1 -1 * (2**2) b -1 8 b1 -1 // (2**8) c 1 2 c1 1 * (2**2) d 1 8 d1 1 // (2**8) print(a{},b{},c{},d{},\n\ a1{},b1{},c1{},d1{}.format(a, b, c, d, a1, b1, c1, d1)) #结果a-4,b-1,c4,d0, # a1-4,b1-1,c14,d10abcd都是左移或者右移a1b1c3c4对应的乘法或者floor除法可以看到结果是一样的。值的注意的是-1这个值右移的时候值是不变的因为负1的补码表示全是1所以无论右移多少次还是-1。6索引[]序列以及映射序列可以认为是有序排列的容器包含了列表字符串元组映射就是字典通过键值对关联。看一下代码#列表 a [1, 2, 3, 4,5,6] #字符串 b abcdef #元组 c (1, 2, 3, 4, 5, 6) #字典 d {a: 1, b: 2, c: 3} print(a[1]{},b[2]{},c[3]{},d[a]{}.format(a[0], b[5], c[3], d[a])) #结果 a[1]2,b[2]c,c[3]4,d[a]1从结果来看对于序列都是先从下标0开始的第一个元素最后一个元素的下标是序列的长度减一。对于字典输入键的名字可以得到值。7分片[::]分片用于序列操作用两个冒号分成了三部分例如[x:y:z]x代表起始位置y代表结束位置不包含z代表步长如果z不填则默认步长是1。分片的操作有点tricky我们看一下代码x [1, 2, 3, 4, 5, 6] a x[0:2] b x[0:2:1] c x[1:6:2] d x[-5:-1] e x[-1:-7:-1] f x[-1:-7] print(a{},b{},c{},d{},e{},f{}.format(a, b, c, d, e, f)) #结果a[1, 2],b[1, 2],c[2, 4, 6],d[2, 3, 4, 5],e[6, 5, 4, 3, 2, 1],f[]上面的代码我是以列表为例子来讲的对于字符串和元组也是一样的。a的表达式结果可以看出取了第一个元素和第二个元素因为序列的下标是默认从0开始但是没有取下标是2的元素,所以分片不包含结束位置。b和a的效果是一样的指定了步长1因为默认的步长就是1。c的指定的步长是2所以我们会取到下标1357但是因为7已经超过结束的位置6了所以取了三个元素246。对于d的下标就觉得有点奇怪了因为有负数python默认最后一个元素的位置是-1然后往前依次是-2-3-4。。。。所以下标-5对应的值是2所以从-5到-1对应的值2345。e是列表逆序的一种方法开始的位置的下标是-1这对应最后一个元素然后步长是-1所以下一个元素的下标是-2这是倒数第二个元素所以通过这种方式实现了列表的逆序。f的值是个空的那是因为步长出了问题-1是开始的位置-7是结束的位置但是步长是1所以-1递增1永远不会得到-7所以这个是非法的输入所以结果是空。我们记住一点开始的位置加上步长最后会到达或者超过结束的位置才是合法的输入要不然就不会取的任何的值。可能有的思考仔细的同学在想为啥逆序用负数我用正数可以么答案是不可以假如我们要用正数x[5:0:-1],这样操作后第一个元素是取不到的因为这个结束的下标是不包含的那是不是可以写成x[5:-1:-1]呢这样也是不行的这起来很混乱5和-1是同一个位置因为结束位置是不包含的所以取到的结果是空。那么x[5:-7:-1]是不是可以呢答案是肯定的。因为-7已经超过第一个元素的范围了所以可以包含第一个元素。但是不管怎样至少用到了一个负数。不过还是建议不要这种正负数混用确实有点不和谐说到这里希望大家明白了切片操作的真谛。操作符的介绍我们就讲到这里当然有一些更高级的操作符的用法这个到时候和具体的类型结合起来说。

更多文章