一、列表
1.创建列表
兼收并蓄是列表的一个特色,列表可以容纳不同类型的数据。
创建列表很简单,如:
a=[1,2,3,4,5,'上山打老虎']
print(a)
2.访问列表元素
访问列表所有元素可以利用增强型for循环:
for each in a:
print(a)
访问列表单个元素可以利用下标表示:a[0] a[2]等等都是有效方法
如果列表很长,想访问最后一个元素,可以用两个方法:
length=len(a)
a[length-1]
a[-1]
3.列表切片
如果想要一次性获取列表多个元素,那该多好啊!Python提供了这种语法,利用冒号。
为什么0:3只包含三个数字呢?因为 a[0:3]
表示从索引0开始,切片到索引3之前(不包括索引3),即取出索引为0、1、2的三个元素。所以 a[0:3]
打印的是 [1, 2, 3]
。这和range函数的参数定义是一样的!
列表甚至可以像range函数一样跳着来!
里面的第三个参数表示我的步长,输入-1甚至可以实现逆序输出列表。
4.增加元素
在列表末尾加一个指定元素:append()
如果要增加的元素很多,我们可以使用extend()方法,但extend方法的参数必须是一个可迭代对象,新的内容是追加到原列表最后一个元素的后面。
同时我们也可以利用切片来进行元素增加(初学者难以理解此部分,建议从extend和append学习)。
这段代码是通过使用切片来将数字6添加到列表s
的末尾。
首先,len(s)
返回列表s
的长度,也就是5。所以 s[len(s):]
表示取从索引5开始到列表末尾的切片,也就是一个空的切片。
然后,用=
将切片赋值为[6]
,这样就将数字6赋值给了空切片,相当于在列表s
的末尾添加了数字6。所以最终的结果就是列表s
变成了[1, 2, 3, 4, 5, 6]
。
如果我们想在任意位置增加元素,可以用insert函数,insert有两个参数,第一个参数指明插入的位置,第二个参数指明插入的元素。
5.删除元素
将指定的元素删除可以用remove方法,如果列表中存在多个匹配的元素,那么它只会删除第一个。如果要删除的元素不存在,那么程序会报错。
删除某个指定位置的元素,可以使用pop方法,参数是下标的索引值。
想要删除全部的元素,可以使用clear方法。
6.更改元素
更改元素和Java C++类似,直接利用下标进行重新赋值即可,如果更改多个元素,利用切片。
底层原理是:将赋值号=左边的内容先删除,再讲等号右边的可迭代对象里的片段插入左边被删除的位置。
对数字元素的列表进行排序,我们利用sort()方法。
如果想将数字元素列表逆转,我们可以用reverse方法
sort函数有两个参数,第一个参数指定排序的比较函数,第二个参数用于指定结果是否反转,一般情况下reverse是默认为FALSE的。
6.查找元素
我们想知道列表里到底有多少个元素是3,可以用count方法实现。
想知道指定元素的索引值,可以用index方法实现。重复出现的元素显示第一次出现的位置。
index函数还有两个参数,index(x,start,end)指明查找的起始和终止位置。
copy函数用于拷贝一个列表。同时利用切片也可以拷贝列表。
值得注意的是,我们现在的拷贝都只是浅拷贝。
二、列表的运算和嵌套
1.加法和乘法
加法就是拼接,乘法就是一个列表重复多次。
2.嵌套列表
我们可以利用下面的方式来创建矩阵或二维列表。
访问嵌套列表中的元素可以利用for循环实现:
通过下标我们仍然可以访问列表元素,比如matrix[0]=[1,2,3]
Python官方也推荐我们使用循环来创建列表:
我们先创建行,迭代获取每一个元素,对每一个元素赋值,赋值一个一维列表,这样就是嵌套列表了。
我们再来看例子:
在内存中两个列表其实是这样的:
A的每一行都是不同的对象,但是B的每一行都是指向了同一个对象。
3.is 运算符
在Python中,is运算符用于比较两个对象的身份标识,即它们是否引用同一个对象。is运算符返回一个布尔值,如果两个对象具有相同的身份标识,则返回True;否则返回False。
身份标识是对象在内存中的唯一地址,可以使用id()函数获取。当两个对象的身份标识相同时,意味着它们指向的是同一个对象。
is运算符与==运算符不同。==运算符用于比较两个对象的值是否相等,即它们是否具有相同的内容。
下面是两个示例,理解is运算符的使用:
a = [1, 2, 3]
b = a
c = [1, 2, 3]
print(a is b) # 输出True,a和b引用同一个对象
print(a is c) # 输出False,a和c引用不同的对象
print(a == c) # 输出True,a和c的值相等
在这个例子中,a和b引用同一个列表对象,它们的身份标识相同,所以is运算符返回True。而a和c引用不同的对象,所以is运算符返回False。但是,a和c的值相等,所以==运算符返回True。
4.引用和深拷贝
现在我们将变量y和x用赋值运算符关联起来,发现改变x的值,y的值也会随之改变。Python将数据和变量进行挂钩,这个行为称为引用。将一个变量赋值给一个变量,其实是将该变量的引用传递给另一个变量。
内存布局为:
浅拷贝:利用上面说过的copy函数或者切片,得到一个新的对象,这时候再改变x不会影响到y。
浅拷贝处理嵌套列表时就会失效,因为它只拷贝了外层对象,内层则拷贝引用,不会再拷贝一个对象。
如下图所示,我们更改第二行第二列的值,y也跟着改变了。
深拷贝:利用copy模块,copy模块里有两个函数,一个是copy实现浅拷贝,另一个是deepcopy函数实现深拷贝。
deepcopy拷贝原对象的同时,也将原对象中的所有子对象同时进行了拷贝。
内存布局是这样:
三、列表推导式
语法:[ expression for target in iterable ] 列表推导式和循环有着高度关联,列表推导式前面的expression可以理解循环体,后面则是循环控制。
列表推导式的效率比循环快很多,因为推导式是直接编译成C语言的。
列表推导式处理字符串也不在话下(ord函数作用是将字符转化成编码):
我们还可以利用列表推导式获取矩阵第二列的元素:
在这个例子中,matrix的对象是三个一维列表,因此row其实是三个一维的列表,每次我们获取row列表的第二个元素,赋值给col2.
我们还可以获取矩阵两条对角线上的元素:
列表和循环一样吗?还是有区别的,循环是通过迭代逐个修改原列表中的元素,列表推导式则是创建一个新的列表,再赋值为原先的这个变量名。
四、再谈列表推导式
利用列表推导式创建嵌套列表:
对于这个列表推导式,for循环执行了三次,每次都生成了一个[0,0,0]一维列表,这样最后我们得到的就是一个嵌套列表,里面是三个不同对象。
列表表达式可以与if结合,形成条件分支:
语句执行顺序为:先执行for循环,再执行if条件判断,最后执行前面的循环体。
列表推导式的嵌套:
比如我们可以利用二重循环将二维列表降级为一维列表
同样我们可以利用二重的列表推导式达到这一点:
嵌套的列表表达式也可以接多重的嵌套条件判断:
四、元组
元组像列表一样可以容纳不同种类的对象,也拥有字符串不可更改的属性。从语法上来讲,列表用的是[ ],而元组用的是( )。实际上,元组不带小括号也是可以的。
想获取下标元素仍然要用[ ],并且我们看到元组的元素是不可更改的。
元组也支持切片,因为切片只是将某部分导出,并且元组里的切片还是[ :3 ]这种格式。
元组只支持查找,也就是只有count和index方法。
并不存在元组推导式。生成只有一个元素的元组,我们可以这样写:
这是因为括号的解析规则决定了单个元素的元组应该被解析为该元素本身,而不是一个元组。因此,为了明确指示生成一个元组,需要在元素后面加上逗号。
如果不加上逗号,Python会将括号解析为优先级运算符,而不是元组的创建操作。
打包和解包:
将元组里所有元素赋值给三个不同的变量称为解包。字符串和列表有着同样的语法,但是我们要注意左右的数量应该匹配起来。
Python里的多重赋值正是先通过元组打包,再进行解包的。
元组一定不能被修改吗?不一定!当元组里是列表的时候就可以修改。
元组是不可变的,但是元组中的元素可以是可变对象,比如列表。当元组中的元素是可变对象时,我们可以修改列表中的元素,因为列表是可变的。所以,即使元组是不可变的,但是元组中的可变对象的值是可以被修改的。