python基础入门笔记,记录翀翀对Python基础的理解与总结,常言道:一分耕耘,一分收获。”在自己的理想道路上,多动脑筋,不断的思考,不停地学习,四肢能勤,不断地“书读百遍”,就会“其义自现”。愿你我都能坚持学习😁
Python序列
所谓序列,就是一块可以存放多个值的连续内存空间,这些值按照一定的顺序排列,可以通过每一个值所在位置的编号(称为索引)访问他们。
在Python中,序列类型包括字符串、列表(也称为数组)、元组、集合与字典(也称为映射),这些序列支持以下几种通用的操作。但是特殊地是集合和字典不支持索引、切片、相加和相乘操作。
序列索引
这个很好理解,从左到右索引值从0开始递增,我们使用A[index]的形式就可以获取指定位置的序列元素:
除此之外,Python还支持索引值是负数,此时索引是从又向左计数,换句话说,从最后一个元素开始计数,从索引值-1开始向左递减,如下所示:
要注意,使用负值作为序列中各元素的索引值时,是从-1开始,而不是从0开始,因为-0就是0就是开头元素。
1 | str="你好呀大帅哥" |
运行结果:
1 | 你 == 你 |
序列切片
切片操作是访问序列中元素的另一种方法啊,他可以访问一定范围内的元素,通过切片操作,可以生成一个新的序列。一定要注意切片并不是操作原序列,而是生成一个新序列。
1 | sname[start : end : step] |
其中,各个参数的含义分别是:
- sname:表示序列的名称;
- start:表示切片的开始索引位置(包括该位置),此参数也可以不指定,会默认为 0,也就是从序列的开头进行切片;
- end:表示切片的结束索引位置(不包括该位置),如果不指定,则默认为序列的长度;
- step:表示在切片过程中,隔几个存储位置(包含当前位置)取一次元素,也就是说,如果 step 的值大于 1,则在进行切片去序列元素时,会“跳跃式”的取元素。如果省略设置 step 的值,则最后一个冒号就可以省略。
要注意切片的范围是左闭右开[start,end),同时step默认是1,想要隔k个元素取一个元素,那么step要设置为step+1
1 | str="你好呀大帅哥" |
运行结果:
1 | 你好 |
序列相加
Python中支持两种类型相同的序列使用+
运算符进行相加操作,他会将两个序列进行连接,但是并不会取出重复的元素,而是仅仅简单的拼接。同时要注意这里的类型相同
指的是两侧序列要么都是列表类型,要么都是元组类型,要么都是字符串。
序列相乘
在Python中,使用数字乘以一个序列会生成新的序列,其内容为原来序列被重复n次的结果。例如:
1 | str="你好呀大帅哥" |
运行结果:
1 | '你好呀大帅哥你好呀大帅哥你好呀大帅哥' |
同时比较特殊的,列表类型在进行乘法运算时,还可以实现初始化指定长度列表的功能。例如如下的代码,将创建一个长度为5的列表,列表中的每一个元素都是None,表示什么都没有。
1 | #列表的创建用 [],后续讲解列表时会详细介绍 |
运行结果:
1 | [None, None, None, None, None] |
检查元素是否包含在序列中
在Python中,可以使用in
关键字检查某元素是否为序列的成员,其语法格式为:
1 | value in sequence |
其中value表示要检查的元素,sequence表示指定的序列。如下代码所示:
1 | str="coolchong.cn" |
运行结果:
1 | True |
同时还有一个not in
关键字,他可以用来检查元素是否不包含在指定的序列中,比如:
1 | str="coolchong.cn" |
运行结果:
1 | False |
和序列相关的内置函数
同时Python还提供了一些有关序列的内置函数,其功能如下,注意这些函数都不会直接操作原序列而是生成一个新的值:
函数 | 功能 |
---|---|
len() | 计算序列的长度,即返回序列中包含多少个元素。 |
max() | 找出序列中的最大元素。 |
min() | 找出序列中的最小元素。 |
list() | 将序列转换为列表。 |
str() | 将序列转换为字符串。 |
sum() | 计算元素和。注意,对序列使用 sum() 函数时,做加和操作的必须都是数字,不能是字符或字符串,否则该函数将抛出异常,因为解释器无法判定是要做连接操作(+ 运算符可以连接两个序列),还是做加和操作。 |
sorted() | 对元素进行排序。(类型不变) |
reversed() | 反向序列中的元素。(类型会变成reversed,需要再使用list()、或者tuple()转换回去) |
enumerate() | 将序列组合为一个索引序列,多用在 for 循环中。 |
思考:enumerate()方法的应用?
1 | enumerate(sequence, [start=0]) |
sequence是一个输入序列,start是下标起始位置,方法返回的是一个枚举对象。
1 | 'Spring', 'Summer', 'Fall', 'Winter'] seasons = [ |
在遍历一个序列(列表或者元组)时,我们可以如下遍历,这样就同时可以使用索引和元素值了:
1 | 'one', 'two', 'three'] seq = [ |
思考:sorted(list)与list.sort()的区别?
首先两种写法都是正确的,可以对列表进行排序,但是两个方法略有不同。首先就是返还值不同,sorted()是返还一个新的列表并不会操作原序列,而list.sort()则是直接操作原序列进行排序并且返还一个值None
1 | 1,3,2,4] lst=[ |
同时sorted()和list.sort()还都可以通过使用key参数指定排序规则,并且是稳定排序,也就是说对于指定规则不能涵盖的元素,本来谁在前面,排好以后谁还是在前面。如下所示我们对列表重新制定排序规则,通过使用lambd重新定义排序规则为按照元素转换成字符串以后的长度排序:
1 | 1,2,3,13,7,11] lst=[ |
实际上sorted()和list.sort()都是在通过key的值比较进行递增排序,默认key=None的但是我们也可以重定义key,一般使用lambda进行重定义(后面会讲到lambda,这里了解即可)
思考:如何实现降序排序?
实际上排序函数语法如下:
1 | sorted(iterable,key=None,reverse=False) |
因此降序我们只需要将reverse设置为True即可啦:
1 | 1,2,3,4,45,6] lst=[ |
Python列表(list)
在C和Java中我们通常是使用数组Array来存储多个相邻连接的数据,但是在Python中是没有数组的,而是提供了一个更加强大的列表类型,他可以按成数组的所有操作同时还具有一些更加强大的函数。从形似上看,列表就是将所有元素放到一个中括号[]
中,相邻元素之间使用,
分隔,如下:
1 | [element1,element2,element3,...,elementn] |
Python的列表没有个数限制,存储范围为无限大,同时内容可以是任何类型如下所示一个列表可以存储许多不同类型的元素:
1 | ["http://coolchong.cn/", 1, [2,3,4] , 3.0] |
但是为了提高代码可读性,我们通常默认推荐使用列表存放一些数据类型相同的元素
Python创建列表
在Python中有两种创建列表的方法:
1)使用[]直接创建列表
使用[]
创建列表,同时使用=
将列表赋值给一个变量:
1 | um = [1, 2, 3, 4, 5, 6, 7] |
创建一个空列表只需要用[]表示即可
1 | emptylist=[] |
2)使用list()函数创建列表
使用内置函数lis()创建一个列表,使用它可以将其他数据数据类型转换为列表类型:
1 | #将字符串转换成列表 |
运行结果:
1 | ['h', 'e', 'l', 'l', 'o'] |
注意对于字典转换为列表以后,只会存储key键,而映射值会丢失并不能存储到列表中
访问列表元素
列表是Python中序列的一种形式,因此我们可以使用索引来获取元素,同时也可以使用切片访问列表中的一组元素(得到的是一个新的子列表)
1 | url = list("http://c.biancheng.net/shell/") |
运行结果:
1 | p |
一定要注意取元素一定是从左向右取,可以正/负索引搭配使用来划定要切片的范围,但是要保证范围是合法的
Python删除列表
对于不再使用的数据,我们统一使用del
关键字进行删除,因此如果我们需要手动删除某个列表时使用del lst
即可,如下:
1 | intlist = [1, 45, 8, 34] |
运行结果:
1 | [1, 45, 8, 34] |
思考:我们需要删除每一个不会再使用的变量吗?
不需要,Python有自带的垃圾回收机制,当发现某个数据没有再被引用以后就会自动销毁,即使开发者不手动删除,Python也会自动将其回收。
Python list列表添加元素
我们直接尝试使用过+
来拼接列表添加元素,如下所示:
1 | language = ["Python", "C++", "Java"] |
运行结果:
1 | language = ['Python', 'C++', 'Java'] |
但是我们会发现此时两个原列表并没有发生变化,拼接操作仅仅是将两个列表拼接生成一个新列表,但是我们如何修改原列表给他添加元素呢?
Python append()方法添加元素
append()方法就是用于在列表的末尾追加元素,该方法的语法格式如下:
1 | listname.append(obj) |
其中listname就是要添加元素的列表,obj表示添加到列表末尾的数据,他可以是单个元素,也可以是列表、元组等。
1 | l = ['Python', 'C++', 'Java'] |
运行结果:
1 | ['Python', 'C++', 'Java', 'PHP'] |
我们会发现使用append()方法添加列表或者元组时得到的结果和我们预期略有不同,它仅仅是将列表或者元组整体追加到了后面,但是我们更希望把其内部的元素逐一取出添加到末尾。
Python extend()方法添加元素
extend()和append()的不同之处:extend()不会把列表或者元组视为一个整体,而是把它们包括的元素逐个添加到列表末尾。
1 | l = ['Python', 'C++', 'Java'] |
运行结果:
1 | ['Python', 'C++', 'Java', 'C'] |
Python insert()方法插入元素
append()和extend()都只能在列表的末尾追加元素,但是如果我们希望在列表中间插入元素,那么次是就会使用到insert()方法,格式如下:
1 | listname.insert(index , obj) |
其中,index表示指定位置的索引值,insert()会将obj插入到listname列表第index个元素的位置,更好理解的说就是新插入的元素在新标中的索引位置为index。同时我们要注意insert()也是将要插入的列表或者元组视为一个整体插入到列表中,这一点和append()一样。
1 | l = ['Python', 'C++', 'Java'] |
运行结果:
1 | ['Python', 'C', 'C++', 'Java'] |
Python list列表删除元素
在Python列表中想要删除元素主要有以下三种场景:
- 根据目标元素所在位置的索引进行删除,可以使用 del 关键字或者 pop() 方法;
- 根据元素本身的值进行删除,可使用列表(list类型)提供的 remove() 方法;
- 将列表中所有元素全部删除,可使用列表(list类型)提供的 clear() 方法。
del:根据索引值删除元素
del是Python中的关键字,专门用来执行数据删除操作,他不仅可以删除列表整体,也可以删除列表中指定位置的元素。格式为:
1 | #删除一个指定元素 |
1 | lang = ["Python", "C++", "Java", "PHP", "Ruby", "MATLAB"] |
运行结果:
1 | ['Python', 'C++', 'PHP', 'Ruby', 'MATLAB'] |
要注意del listname[start,end]此时表示的就是删除原列表!
思考:什么时候切片是新列表?什么时候是引用原列表?
这个地方非常容易混淆,我们要注意:可以使用切片来截取列表中的任何部分,得到一个新列表,也可以通过切片来修改和删除列表中部分元素,甚至可以通过切片操作为列表对象增加元素。
只有在删除和=
赋值的时候切片表示原引用列表,其他情况下都是一个新列表对象,如下所示:
1 | 1,2,3] lst=[ |
Pop():根据索引值删除元素
使用listname.pop(index)
可以删除指定索引出的元素,如果不指定index那么默认删除的是列表的最后一个元素类似于数据结构中的出栈操作,此种方法不支持范围删除。
1 | nums = [40, 36, 89, 2, 36, 100, 7] |
运行结果:
1 | [40, 36, 89, 36, 100, 7] |
要注意虽然Python中列表由pop()表示删除元素,但是插入元素可不是push()而是append()
remove():根据元素值进行删除
除了使用del和pop()删除指定索引值的元素,我们还可以使用remove()来删除指定元素值,但是要注意他每一次只会删除第一个值匹配的元素,并且必须保证要删除的元素存在,否则会报异常
1 | nums = [40, 36, 89, 2, 36, 100, 7] |
运行结果:
1 | [40, 89, 2, 36, 100, 7] |
clear():删除所有元素
Python可以使用clear()删除列表的所有元素,即清空列表但是此时列表自身还是存在的只是变成了一个空列表:
1 | url = list("http://c.biancheng.net/python/") |
运行结果:
1 | [] |
思考:搜索并逐一删除元素的写法?
假设现在有一个场景,是当列表中存在元素为1时,那我们就要将这个元素删除,此时你会怎么写?我猜测你的第一想法一定是:
1 | lst=[1,1,1,2,1,1,1] |
我们会发现报错了,此时他报的错是列表访问越界:
1 | Traceback (most recent call last): |
这是为什么呢?原因是列表在删除过程中会逐渐变短,而i使用是在原列表长度的范围内进行递增,因此只要删除了一个或者多个元素,那么后面就一定会出现越界。我们以一个例子为例体会一下这个过程:
1 | lst=[1,2,2,3,1,1,4] |
假设现在我们要遍历一个列表,每次都打印此次访问到的元素索引值和元素值,然后再删除这个元素,那么我们最终得到的结果如下:
1 | PS D:\Pythoncode> & D:/Python/anaconda3/python.exe d:/Pythoncode/Algrithm/test.py |
这个过程如上所示,因此我们发现这种方法删除元素是不可行的,为了解决这个问题,我们只需要让i倒着遍历列表并删除即可了:
1 | lst=[1,2,2,3,1,1,4] |
运行结果:
1 | PS D:\Pythoncode> & D:/Python/anaconda3/python.exe d:/Pythoncode/Algrithm/test.py |
我们可以使用remove()方法来实现类似的删除元素值的功能,他的写法如下:
1 | lst=[1,2,2,3,1,1,4] |
运行结果:
1 | [2, 2, 3, 4] |
这里我们要注意必须是遍历全范围切片,原因很简单和上面类似,如果我们直接在lst中遍历并删除也会造成数组越界的问题,为了解决这个问题,我们使用的策略是遍历一个lst的全范围切片子列表(可以看成是复制了一个列表),在里面寻找是否还有要删除的元素,如果有就调用一次lst.remove()删除,这样我们就保证了每一次调用lst.remove()时保证了一定还有可以删除的元素。同时由于遍历查找和删除的是两个不同的列表,因此就不会造成访问越界了,毕竟el遍历的切片子列表一直就没有变化。
Python list列表修改元素
修改单个元素
1 | nums = [40, 36, 89, 2, 36, 100, 7] |
运行结果:
1 | [40, 36, -26, 2, -66.2, 100, 7] |
修改一组元素
Python 支持通过切片语法给一组元素赋值。在进行这种操作时,如果不指定步长(step 参数),Python 就不要求新赋值的元素个数与原来的元素个数相同;这意味,该操作既可以为列表添加元素,也可以为列表删除元素。
1 | nums = [40, 36, 89, 2, 36, 100, 7] |
运行结果:
1 | [40, 45.25, -77, -52.5, 36, 100, 7] |
如果对空切片(slice)赋值,就相当于插入一组新的元素:
1 | nums = [40, 36, 89, 2, 36, 100, 7] |
运行结果:
1 | [40, 36, 89, 2, -77, -52.5, 999, 36, 100, 7] |
但是我们要注意使用切片语法赋值时,Python 不支持单个值(必须是一个列表才行),例如下面的写法就是错误的:
1 | nums[4: 4] = -77 |
只需要修改为
1 | nums[4: 4] = [-77] |
但是如果使用字符串赋值,Python会自动把字符串转换成序列,其中的每个字符都是一个元素:
1 | nums = [40, 36, 89, 2, 36, 100, 7] |
运行结果:
1 | [40, 36, 89, 2, 'x', 'y', 'z', 36, 100, 7] |
Python list列表查找元素
index()方法
1 | istname.index(obj, start, end) |
listname表示列表名称,obj表示要查找的元素,start表示查找起始位置,end表示结束位置。index方法用来查找某个元素在[start,end)列表中首次出现的位置。
- start 和 end 可以都不写,此时会检索整个列表;
- 如果只写 start 不写 end,那么表示检索从 start 到末尾的元素;
- 如果 start 和 end 都写,那么表示检索 start 和 end 之间的元素。
1 | nums = [40, 36, 89, 2, 36, 100, 7, -20.5, -999] |
运行结果:
1 | 3 |
要注意当要查找的元素不存在时,则会导致ValueError错误,因此在使用index()之前最好使用count()方法判断一下
count()方法
1 | listname.count(obj) |
其中listname是列表名称,obj是要统计的元素。count()方法用来统计某个元素在列表中出现的次数,我们可以使用这个方法来判断哪一个列表是否包含某个元素。如果count()返还0则说明列表中不存在这个元素。
1 | nums = [40, 36, 89, 2, 36, 100, 7, -20.5, 36] |
运行结果:
1 | 36出现了3次 |
Python range()快速初始化数字列表
range()语法格式和切片很像,也有三个参数:
1 | range(start, stop[, step]) |
start是起始位置,stop是结束位置,step是步长,同时也是左闭右开[start,stop),且当只填写一个数字时默认从0开始,但是我们要注意range()生成的元素组成的并不是列表list类型:
1 | print(type(range(5))) |
因此如果我们想要视同range()快速初始化列表需要在最外侧转换成list类型,同时我们使用step步长可以初始化一些特殊列表:
比如1~10内的偶数组成的列表:
1 | even_numbers = list(range(2,11,2)) |
运行结果:
1 | [2, 4, 6, 8, 10] |
思考:还有没有其他高级写法?
列表推导(List Comprehension) 是一种数学家用来实现众所周知标记集合的Python方式。它由方括号组成,包含一个表达式,后跟一个for子句,后面跟一个可选的if子句。
表达式可以是我们想要放入列表中的任何类型的对象;由于我们用零初始化列表,因此我们的表达式将只为0。
1 | arr = [0 for i in range(1000)] |
当然也可以用等价的写法:
1 | arr=[0]*1000 |
使用列表推导也可以写1-10以内的偶数组成的列表:
1 | even_numbers = [i for i in range(2,11,2)] |
Python 使用list模拟栈和队列
list模拟栈
栈stack的特点就是后进先出,因此我们必须保证pop()时弹出的是最后进来的元素,因此只需要插入元素使用append()即可模拟:
1 | #定义一个空 list 当做栈 |
运行结果:
1 | [1, 2, 'hello'] |
list模拟队列
队列queue特点是先进先出,因此我们必须保证pop()时弹出的是最先进来的元素,因此只需要保证插入元素使用insert(0,obj)即可模拟:
1 | #定义一个空列表,当做队列 |
运行结果:
1 | ['hello', 2, 1] |