python学习过程中的一些随笔,用于整理一些琐碎但可能引发一些bug的知识点
一、数组
1.1 在编程中,对于两个变量进行数值交换常采用的形式为如下:
a=1,b=2,temp=b,b=a,a=temp
在python中可以将其简化为
a,b=b,a
但要注意对于数组的原地数值交换,可能造成结果错误,如对于下面的程序
a=[1,2,3]
a[0],a[a[0]]=a[a[0]],a[0]
你期望得到的结果过是1,2两个元素进行换位,但是最终的结果是a=[2,2,1]
原因在于当a[0]=a[1]=2被执行后,第一个逗号后得到的结果为a[2]而非a[1],因而引发错误。
但对于代码段如下,就可以得到正确的值:
a=[1,2,3]
# a[0],a[a[0]]=a[a[0]],a[0]
a[a[0]],a[0]=a[0],a[a[0]]
print(a)
>>>[2, 1, 3]
对上面的代码分析可知,对于这样的表达式,python将会先读取等式的右边,得到变量的值分别为1,2,然后依次读取等式的左边,对其进行赋值,因此对a[a[0]]进行修改后,并不影响已读到的a[a[0]]的值,然后再修改a[0],但对于上一段代码,先修改了a[0]后,再读取a[a[0]]时,a[0]的值已经被改变了,因此造成错位。
1.2 对于数组如果切片超出索引,那么返回值为一个空列表
a=[1,2,3]
print(a[3:])
>>>>>>[]
1.3 数组的深复制与浅复制
a=[[1]*10]*10
a[1][2]=100
print(a)
对于这样一个数组,预期目标是只修改第二行第三个数为100,但实际得到的结果是所有行的第三个数变成了100,原因设计数组的深复制与浅复制的关系。这里借用博文——图解python深拷贝与浅拷贝说明如下:
对于python列表的乘法而言,如果列表中的元素为不可变类型,如数字,字符串等,那么复制能够正常进行,如:
a=[1]*3
>>>[1,1,1]
但,当列表中的元素为引用类型时,那么列表复制执行的为引用(见上文中的说明),当对其中元素进行修改时,会对所有的元素造成影响,列表内的对象为字典时也会出现。
1.4python语法糖
对一个 list 排序,这很简单,但如果要先按元素的一个属性排序,再按另一个排序,怎么做?
比如一个学校的人站成一行,需要年级从小到大,并且每个年级里从矮到高。
可以这样:
[P1, P2, P3, ...Pn].sort(key=lambda x: (x.grade, x.height))
对上文的例子进行拓展,假设有一个 list:
lst = [1, -2, 10, -12, -4, -5, 9, 2]
还是排序,我们希望把正的放前面,负的放后面,并且分别按绝对值从小到大。即输出:
[1, 2, 9, 10, -2, -4, -5, -12]
最简单的方法是:
lst.sort(key=lambda x: (x < 0, abs(x)))
1.5 for和lambda表达式结合
def testFun():
temp = [lambda x : i*x for i in range(4)]
return temp
for everyLambda in testFun():
print (everyLambda(2))
对上面的表达式,返回的最终结果为6,6,6,6,对于temp中的lambda表达式,在执行时,i都是在其周围的作用域中寻找的,当执行时,i的结果为3,因此返回结果均为6
二、字符操作
1、对于二进制可知道负数在计算机中是采用补码的形式表示的,但对于python而言,利用函数bin()提取二进制表示时,输出得到的结果却是:-0b1,不是实际的二进制形式,为了得到真实的二进制数,可以写出函数如下:
print(len(bin(-1 & 0xffffffff)))
2python对字符串进行补位,对齐,格式化等操作,可以通过format函数来完成
可以参考文章——Python用format格式化字符串
2、python中的for else 和while else循环都表示正确执行完全部循环就执行else语句,否则不执行,例如循环内有break,return打断了循环,continue不打断循环