我从2021年6月13号写下第一篇Python的系列专栏算起,陆续更新了二十七篇Python系列文章。在此感谢读者朋友们的支持和阅读,特别感谢一键三连的小伙伴。
本专栏起名【Python从入门到精通】,主要分为基础知识和项目实战两个部分,目前基础知识部分已经完全介绍完毕。下一阶段就是写Python项目实战以及爬虫相关的知识点。
为了对前期学习的Python基础知识做一个总结归纳,以帮助读者朋友们更好的学习下一部分的实战知识点,故在此我写下此文,共勉,同进。
同时为了方便大家交流学习,我这边还建立了一个Python的学习群。群里都是一群热爱学习的小伙伴,不乏一些牛逼的大佬。大佬带飞,我相信进入群里的小伙伴一定会走的更快,飞的更高。
下面就通过一个思维导图,展示本专栏Python基础知识部分的总览图。
本专栏从零基础出发,从环境的搭建到高级知识点的学习,一步步走来,相信各位读者朋友们早已掌握相关的知识点。接下来就做一个详细的回顾。
Python是一门开源免费的,通用型的脚本编程语言。它需要在运行时将代码一行行解析成CPU能识别的机器码。它是一门解析型的语言,何为解析型语言呢?就是在运行时通过解析器将源代码一行行解析成机器码。而像C语言,C++等则是编译型的语言,即通过编译器将所有的源代码一次性编译成二进制指令,生成一个可执行的程序。解析型语言相对于编译型语言的好处就是天然具有跨平台的特点,一次编码,到处运行。
python3
验证安装的结果,如果出现如下结果就表明安装Python编译器安装成功了。工欲善其事必先利其器,在实际开发中我们都是通过IDE(集成开发环境)来进行编码,为啥要使用IDE呢?这是因为IDE集成了语言编辑器,自动建立工具,除错器等等工具可以极大方便我们快速的进行开发。打个比方 我们可以将集成开发环境想象成一个台式机。虽然只需要主机就能运行起来,但是,还是需要显示器,键盘等才能用的爽。
PyCharm就是这样一款让人用的很爽的IDE开发工具。下面就简单介绍一下它的安装过程
点击链接 https://www.jetbrains.com/pycharm/download/
进入下来页面,PyCharm 有专业版和社区版。其中,专业版需要购买才能使用,而社区版是免费的。社区版对于日常的Python开发完全够用了。所以我们选择PyCharm的社区版进行下载安装。点击如下图所示的按钮进行安装包的下载。
安装包下载好之后,我们双击安装包即可进行安装,安装过程比较简单,基本只需要安装默认的设置每一步点击Next按钮即可,不过当出现下图的窗口时需要设置一下。
设置好之后点击 Next 进入下一步的安装,知道所有的安装都完成。
这里使用只需要注意一点,就是设置解释器,默认的话在Project Interpreter的选择框中是提示的是 No interpreter,即没有选中解释器,所以,我们需要手动添加。
所以需要点击设置按钮设置解释器,这里选择 Add Local 设置本地的解释器。
打开解释器的设置页面之后,默认选中的是Virtualenv Environment 这个tab页,
这里Location是用来设置项目的虚拟环境,具体可以参考pycharm的使用小结,设置虚拟环境,更换镜像源
Base interpreter 用来设置解释器的路径。
至此,开发Python的脚手架已经弄好,接下来就是编码了。
如下创建了一个名为demo_1.py的文件,然后在文件中写入了如下几行代码
print("你好,世界") a = 120 b = 230 print(a + b)
运行这些代码只需要简单的右键选中 Run ‘demo_1’ 或者 Debug ‘demo_1’ ,这两者的区别是Run demo_1是以普通模式运行代码,而 Debug ‘demo_1’ 是以调试模式运行代码。
运行结果就是:
详细内容可以查看【Python从入门到精通】(二)怎么运行Python呢?有哪些好的开发工具
首先介绍的是Python的注释,Python的注释分为两种:单行注释和多行注释。
#注释内容
从#号开始直到这行结束为止的所有内容都是注释。例如:# 这是单行注释
''' 三个连续的单引号的多行注释 注释多行内容 '''
或者
""" 三个连续的双引号的多行注释 注释多行内容 """
多行注释通常用来为Python文件、模块、类或者函数等添加版权或者功能描述信息(即文档注释)
不同于其他编程语言(如Java,或者C)采用大括号{}
分割代码块,Python采用代码缩进和冒号 : 来区分代码块之间的层次。如下面的代码所示:
a = -100 if a >= 0: print("输出正数" + str(a)) print('测试') else: print("输出负数" + str(a))
其中第一行代码a = -100
和第二行代码if a >= 0:
是在同一作用域(也就是作用范围相同),所以这两行代码并排。而第三行代码print("输出正数" + str(a))
的作用范围是在第二行代码里面,所以需要缩进。第五行代码也是同理。第二行代码通过冒号和第三行代码的缩进来区分这两个代码块。
Python的缩进量可以使用空格或者Tab键来实现缩进,通常情况下都是采用4个空格长度作为一个缩进量的。
这里需要注意的是同一个作用域的代码的缩进量要相同,不然会导致IndentationError异常错误,提示缩进量不对,如下面代码所示:第二行代码print("输出正数" + str(a))
缩进了4个空格,而第三行代码print('测试')
只缩进了2个空格。
if a >= 0: print("输出正数" + str(a)) print('测试')
在Python中,对于类定义,函数定义,流程控制语句就像前面的if a>=0:
,异常处理语句等,行尾的冒号和下一行缩进,表示下一个代码块的开始,而缩进的结束则表示此代码的结束。
详细内容可以查看【Python从入门到精通】(三)Python的编码规范,标识符知多少?
Python3中的整数是不分类型,也就是说没有长整数类型(Long)或者短整数类型(short)之分,它的取值范围是是无限的,即不管多大或者多小的数字,Python都能轻松的应对。如下就是两个极大或者极小的整数。
>>> 100000-0000000000000000000000000000000000000000 1000000000000000000000000000000000000000000000 >>> print(-1000000000000000000000000000000000000000000000) -1000000000000000000000000000000000000000000000
可以看出再大或者再小的数字都不会出现溢出的情况,这说明了Python对整数的处理能力非常强。
Python中可以用多种进制的来表示整数。
# 二进制 a=0b1001 print('a=',a) # 八进制 b=0o207 print('b=',b) # 十六进制 c=0x45 print('c=',c)
运行结果是:
a= 9 b= 135 c= 69
Python 3.x允许使用下划线_作为数字(包括整数和小数)的分隔符,通常每隔三个数字添加一个下划线,比如:click = 1_301_547
在编程语言中,小数通常以浮点数的形式存储,浮点数和定点数是相对的;小数在存储过程中如果小数点发生移动,就称为浮点数;如果小数点不动,就称为定点数。
Python中的小数有两种书写形式:
aEn或aen
x=10.01 print('x=',x) y=-0.031 print('y=',y) z=2.3E10 print('z=',z) w=-0.00000001 print('w=',w)
运行结果是:
x= 10.01 y= -0.031 z= 23000000000.0 w= -1e-08
布尔类型用来表示真(对)或假(错),比如常见的3>2 比较算式,这个是正确的,Python中使用True来代表;再比如2>3 比较算式,这个是错误的,用False来代表。
print(3>2) print(2>3) print('True==1的结果是:',True==1) print('False==0的结果是:',False==0)
运行结果是:
True False True==1的结果是: True False==0的结果是: True
详细内容可以查看【Python从入门到精通】(四)Python的内置数据类型有哪些呢?数字了解一下
序列(sequence)指的是一块可存放多个元素的内存空间,这些元素按照一定的顺序排列。每个元素都有自己的位置(索引),可以通过这些位置(索引)来找到指定的元素。如果将序列想象成一个酒店,那么酒店里的每个房间就相当于序列中的每个元素,房间的编号就相当于元素的索引,可以通过编号(索引)找到指定的房间(元素)。
了解完了序列的基本概念,那么在Python中一共有哪些序列类型呢?如下图所示:
从图中可以看出在Python中共有7种序列类型,分别是文本序列类型(str);二进制序列类型 bytes和bytearray;列表(list);元组(tuple);集合类型(set和frozenset);范围类型(range)以及字典类型(dict)。
按照能存储的元素可以将序列类型划分为两大类:分别是:容器序列和扁平序列
容器序列:即可容纳不同数据类型的元素的序列;有 list;tuple;set;dict
举个栗子:
list=['runoob',786,2.23,'john',70.2]
这里的list保存的元素有多种数据类型,既有字符串,也有小数和整数。
扁平序列:即只能容纳相同数据类型的元素的序列;有bytes;str;bytearray,以str为例,同一个str只能都存储字符。
按照序列是否可变,又可分为可变序列和不可变序列。
这里的可变的意思是:序列创建成功之后,还能不能进行修改操作,比如插入,修改等等,如果可以的话则是可变的序列,如果不可以的话则是不可变序列。
可变序列有列表( list);字典(dict)等,
不可变的序列有元祖(tuple),后面的文章会详细的对这些数据类型做详细介绍。
在介绍序列概念的时候,说到了序列中元素的索引,那么什么是序列的索引呢?其实就是位置的下标。 如果对C语言中的数组有所了解的话,我们知道数组的索引下标都是从0开始依次递增的正数,即第一个元素的索引下标是0,第n个元素的索引下标是n-1。序列的索引也是同理,默认情况下都是从左向右记录索引,索引值从0开始递增,即第一个元素的元素的索引值是0,第n个元素的索引值是n-1。如下图所示:
当然与C语言中数组不同的是,Python还支持索引值是负数,该类的索引是从右向左计数。换句话说,就是从最后一个元素开始计数,从索引值-1开始递减,即第n个元素的索引值是-1,第1个元素的索引值是-n,如下图所示:
切片操作是访问序列元素的另一种方式,它可以访问一定范围内的元素,通过切片操作,可以生成一个新的序列。切片操作的语法格式是:
sname[start : end : step]
各个参数的含义分别是:
str1='好好学习,天天向上' # 取出索引下标为7的值 print(str1[7]) # 从下标0开始取值,一直取到下标为7(不包括)的索引值 print(str1[0:7]) # 从下标1开始取值,一直取到下标为4(不包括)的索引值,因为step等于2,所以会隔1个元素取值 print(str1[1:4:2]) # 取出最后一个元素 print(str1[-1]) # 从下标-9开始取值,一直取到下标为-2(不包括)的索引值 print(str1[-9:-2])
运行的结果是:
向 好好学习,天天 好习 上 好好学习,天天
Python支持类型相同的两个序列使用"+"
运算符做想加操作,它会将两个序列进行连接,但是不会去除重复的元素,即只做一个简单的拼接。
str='他叫小明' str1='他很聪明' print(str+str1)
运行结果是:他叫小明他很聪明
Python支持使用数字n乘以一个序列,其会生成一个新的序列,新序列的内容是原序列被重复了n次的结果。
str2='你好呀' print(str2*3)
运行结果是:你好呀你好呀你好呀
,原序列的内容重复了3次。
Python中可以使用in
关键字检查某个元素是否为序列中的成员,其语法格式为:
value in sequence
其中,value表示要检查的元素,sequence表示指定的序列。
举个栗子:查找天
字是否在字符串str1中。
str1='好好学习,天天向上' print('天' in str1)
运行结果是:True
*由若干个字符组成的集合就是一个字符串(str)**,Python中的字符串必须由双引号""或者单引号’'包围。其语法格式是:
"字符串内容" '字符串内容'
如果字符串中包含了单引号需要做特殊处理。比如现在有这样一个字符串
str4='I'm a greate coder'
直接这样写有问题的。
处理的方式有两种:
\
进行转义即可:str4='I\'m a greate coder'
str4="I'm a greate coder"
这里外层用双引号,包裹字符串里的单引号。
通过+
运算符
现有字符串码农飞哥好,
,要求将字符串码农飞哥牛逼
拼接到其后面,生成新的字符串码农飞哥好,码农飞哥牛逼
举个例子:
str6 = '码农飞哥好,' # 使用+ 运算符号 print('+运算符拼接的结果=',(str6 + '码农飞哥牛逼'))
运行结果是:
+运算符拼接的结果= 码农飞哥好,码农飞哥牛逼
切片操作是访问字符串的另一种方式,它可以访问一定范围内的元素,通过切片操作,可以生成一个新的字符串。切片操作的语法格式是:
sname[start : end : step]
各个参数的含义分别是:
str1='好好学习,天天向上' # 取出索引下标为7的值 print(str1[7]) # 从下标0开始取值,一直取到下标为7(不包括)的索引值 print(str1[0:7]) # 从下标1开始取值,一直取到下标为4(不包括)的索引值,因为step等于2,所以会隔1个元素取值 print(str1[1:4:2]) # 取出最后一个元素 print(str1[-1]) # 从下标-9开始取值,一直取到下标为-2(不包括)的索引值 print(str1[-9:-2])
运行的结果是:
向 好好学习,天天 好习 上 好好学习,天天
Python提供了split()方法用于分割字符串,split() 方法可以实现将一个字符串按照指定的分隔符切分成多个子串,这些子串会被保存到列表中(不包含分隔符),作为方法的返回值反馈回来。该方法的基本语法格式如下:
str.split(sep,maxsplit)
此方法中各部分参数的含义分别是:
str = 'https://feige.blog.csdn.net/' print('不指定分割次数', str.split('.')) print('指定分割次数为2次',str.split('.',2))
运行结果是:
不指定分割次数 ['https://feige', 'blog', 'csdn', 'net/'] 指定分割次数为2次 ['https://feige', 'blog', 'csdn.net/']
合并字符串与split的作用刚刚相反,Python提供了join() 方法来将列表(或元组)中包含的多个字符串连接成一个字符串。其语法结构是:
newstr = str.join(iterable)
此方法各部分的参数含义是:
list = ['码农飞哥', '好好学习', '非常棒'] print('通过.来拼接', '.'.join(list)) print('通过-来拼接', '-'.join(list))
运行结果是:
通过.来拼接 码农飞哥.好好学习.非常棒 通过-来拼接 码农飞哥-好好学习-非常棒
startswith()方法用于检索字符串是否以指定字符串开头,如果是返回True;反之返回False。其语法结构是:
str.startswith(sub[,start[,end]])
此方法各个参数的含义是:
str1 = 'https://feige.blog.csdn.net/' print('是否是以https开头', str1.startswith('https')) print('是否是以feige开头', str1.startswith('feige', 0, 20))
运行结果是:
是否是以https开头 True 是否是以feige开头 False
endswith()方法用于检索字符串是否以指定字符串结尾,如果是则返回True,反之则返回False。其语法结构是:
str.endswith(sub[,start[,end]])
此方法各个参数的含义与startswith方法相同,再此就不在赘述了。
Python中提供了3种方法用于字符串大小写转换
str.title()
str.lower()
str.upper()
。str = 'feiGe勇敢飞' print('首字母大写', str.title()) print('全部小写', str.lower()) print('全部大写', str.upper())
运行结果是:
首字母大写 Feige勇敢飞 全部小写 feige勇敢飞 全部大写 FEIGE勇敢飞
Python中提供了三种方法去除字符串中空格(删除特殊字符)的3种方法,这里的特殊字符,指的是指表符(\t)、回车符(\r),换行符(\n)等。
str = '\n码农飞哥勇敢飞 ' print('去除前后空格(特殊字符串)', str.strip()) print('去除左边空格(特殊字符串)', str.lstrip()) print('去除右边空格(特殊字符串)', str.rstrip())
运行结果是:
去除前后空格(特殊字符串) 码农飞哥勇敢飞 去除左边空格(特殊字符串) 码农飞哥勇敢飞 去除右边空格(特殊字符串) 码农飞哥勇敢飞
最早的字符串编码是ASCll编码,它仅仅对10个数字,26个大小写英文字母以及一些特殊字符进行了编码,ASCII码最多只能表示256个字符,每个字符只需要占用1个字节。为了兼容各国的文字,相继出现了GBK,GB2312,UTF-8编码等,UTF-8是国际通用的编码格式,它包含了全世界所有国家需要用到的字符,其规定英文字符占用1个字节,中文字符占用3个字节。
str.encode([encoding="utf-8"][,errors="strict"])
bytes.decode([encoding="utf-8"][,errors="strict"])
str = '码农飞哥加油' bytes = str.encode() print('编码', bytes) print('解码', bytes.decode())
运行结果是:
编码 b'\xe7\xa0\x81\xe5\x86\x9c\xe9\xa3\x9e\xe5\x93\xa5\xe5\x8a\xa0\xe6\xb2\xb9' 解码 码农飞哥加油
默认的编码格式是UTF-8,编码和解码的格式要相同,不然会解码失败。
在实际工作中我们经常要将一个数据对象序列化成字符串,也会将一个字符串反序列化成一个数据对象。Python自带的序列化模块是json模块。
import json dict = {'学号': 1001, 'name': "张三", 'score': [{'语文': 90, '数学': 100}]} str = json.dumps(dict,ensure_ascii=False) print('序列化成字符串', str, type(str)) dict2 = json.loads(str) print('反序列化成对象', dict2, type(dict2))
运行结果是:
序列化成字符串 {"name": "张三", "score": [{"数学": 100, "语文": 90}], "学号": 1001} <class 'str'> 反序列化成对象 {'name': '张三', 'score': [{'数学': 100, '语文': 90}], '学号': 1001} <class 'dict'>
详细内容可以查看
【Python从入门到精通】(五)Python内置的数据类型-序列和字符串,没有女友,不是保姆,只有拿来就能用的干货
【Python从入门到精通】(九)Python中字符串的各种骚操作你已经烂熟于心了么?【收藏下来就挺好的】
列表作为Python序列类型中的一种,其也是用于存储多个元素的一块内存空间,这些元素按照一定的顺序排列。其数据结构是:
[element1, element2, element3, ..., elementn]
element1~elementn表示列表中的元素,元素的数据格式没有限制,只要是Python支持的数据格式都可以往里面方。同时因为列表支持自动扩容,所以它可变序列,即可以动态的修改列表,即可以修改,新增,删除列表元素。看个爽图吧!
首先介绍的是对列表的操作:包括列表的创建,列表的删除等!其中创建一个列表的方式有两种:
第一种方式:
通过[]
包裹列表中的元素,每个元素之间通过逗号,
分割。元素类型不限并且同一列表中的每个元素的类型可以不相同,但是不建议这样做,因为如果每个元素的数据类型都不同的话则非常不方便对列表进行遍历解析。所以建议一个列表只存同一种类型的元素。
list=[element1, element2, element3, ..., elementn]
例如:test_list = ['测试', 2, ['码农飞哥', '小伟'], (12, 23)]
PS: 空列表的定义是list=[]
第二种方式:
通过list(iterable)
函数来创建列表,list函数是Python内置的函数。该函数传入的参数必须是可迭代的序列,比如字符串,列表,元组等等,如果iterable
传入为空,则会创建一个空的列表。iterable
不能只传一个数字。
classmates1 = list('码农飞哥') print(classmates1)
生成的列表是:['码', '农', '飞', '哥']
向列表中新增元素的方法有四种,分别是:
第一种: 使用**+运算符将多个列表**连接起来。相当于在第一个列表的末尾添加上另一个列表。其语法格式是listname1+listname2
name_list = ['码农飞哥', '小伟', '小小伟'] name_list2 = ['python', 'java'] print(name_list + name_list2)
输出结果是:['码农飞哥', '小伟', '小小伟', 'python', 'java']
,可以看出将name_list2中的每个元素都添加到了name_list的末尾。
第二种:使用append()方法添加元素
append()方法用于向列表末尾添加元素,其语法格式是:listname.append(p_object)
其中listname表示要添加元素的列表,p_object表示要添加到列表末尾的元素,可以是字符串,数字,也可以是一个序列。举个栗子:
name_list.append('Adam') print(name_list) name_list.append(['test', 'test1']) print(name_list)
运行结果是:
['码农飞哥', '小伟', '小小伟', 'Adam'] ['码农飞哥', '小伟', '小小伟', 'Adam', ['test', 'test1']]
可以看出待添加的元素都成功的添加到了原列表的末尾处。并且当添加的元素是一个序列时,则会将该序列当成一个整体。
第三种:使用extend()方法
extend()方法跟append()方法的用法相同,同样是向列表末尾添加元素。元素的类型只需要Python支持的数据类型即可。不过与append()方法不同的是,当添加的元素是序列时,extend()方法不会将列表当成一个整体,而是将每个元素添加到列表末尾。还是上面的那个例子:
name_list = ['码农飞哥', '小伟', '小小伟'] name_list.extend('Adam') print(name_list) name_list.extend(['test', 'test1']) print(name_list)
运行结果是:
['码农飞哥', '小伟', '小小伟', 'A', 'd', 'a', 'm'] ['码农飞哥', '小伟', '小小伟', 'A', 'd', 'a', 'm', 'test', 'test1']
从结果看出,当添加字符串时会将字符串中的每个字符作为一个元素添加到列表的末尾处,当添加的列表时会将列表中的每个元素添加到末尾处。
第四种:使用insert()方法
前面介绍的几种插入方法,都只能向列表的末尾处插入元素,如果想在列表指定位置插入元素则无能为力。insert()方法正式用于处理这种问题而来的。其语法结构是listname.insert(index, p_object)
其中index表示指定位置的索引值,insert()会将p_object插入到listname列表第index个元素的位置。与append()方法相同的是,如果待添加的元素的是序列,则insert()会将该序列当成一个整体插入到列表的指定位置处。举个栗子:
name_list = ['码农飞哥', '小伟', '小小伟'] name_list.insert(1, 'Jack') print(name_list) name_list.insert(2, ['test', 'test1']) print(name_list)
运行结果是:
['码农飞哥', 'Jack', '小伟', '小小伟'] ['码农飞哥', 'Jack', ['test', 'test1'], '小伟', '小小伟']
说完了列表中元素新增的方法,接着让我们来看看修改列表中的元素相关的方法。修改列表元素的方法有两种:
第一种:修改单个元素:
修改单个元素的方法就是对某个索引上的元素进行重新赋值。其语法结构是:listname[index]=newValue
,就是将列表listname中索引值为index位置上的元素替换成newValue。
举个栗子:
name_list = ['码农飞哥', '小伟', '小小伟'] name_list[1] = 'Sarah' print(name_list)
运行结果:['码农飞哥', 'Sarah', '小小伟']
从结果可以看出索引为1处的元素值被成功修改成了Sarch。
第二种:通过切片语法修改一组元素
通过切片语法可以修改一组元素,其语法结构是:listname[start:end:step]
,其中,listname表示列表名称,start表示起始位置,end表示结束位置(不包括),step表示步长,如果不指定步长,Python就不要求新赋值的元素个数与原来的元素个数相同,这意味着,该操作可以为列表添加元素,也可以为列表删除元素。举个栗子:
name_list = ['码农飞哥', '小伟', '小小伟'] name_list[0:1] = ['飞哥', '牛逼'] print(name_list)
运行结果是:['飞哥', '牛逼', '小伟', '小小伟']
,从结果可以看出将原列表中索引为0处的元素值已经被替换为飞哥
,并且插入了牛逼
这个元素。
删除列表中元素的方法共有四种。
第一种:根据索引值删除元素的del关键字
根据索引值删除元素的del关键字有两种形式,一种是删除单个元素,del listname[index]
,一种是根据切片删除多个元素del listname[start : end]
,其中,listname表示列表名称,start表示起始索引,end表示结束索引,del会删除从索引start到end之间的元素,但是不包括end位置的元素。还是举个栗子:
name_list = ['码农飞哥', '小伟', '小小伟', '超人'] name_list2 = name_list print('原始的name_list={0}'.format(name_list)) print('原始的name_list2={0}'.format(name_list2)) # 删除索引0到2之间的元素,即删除索引0和索引1两个位置的元素 del name_list[0:2] print('使用del删除元素后name_list={0}'.format(name_list)) print('使用del删除元素后name_list2={0}'.format(name_list2)) del name_list print('使用del删除列表后name_list2={0}'.format(name_list2))
运行结果是:
原始的name_list=['码农飞哥', '小伟', '小小伟', '超人'] 原始的name_list2=['码农飞哥', '小伟', '小小伟', '超人'] 使用del删除元素后name_list=['小小伟', '超人'] 使用del删除元素后name_list2=['小小伟', '超人'] 使用del删除列表后name_list2=['小小伟', '超人']
可以看出用del删除列表元素时是真实的删除了内存数据的,但是用del删除列表时,则只是删除了变量,name_list2所指向的内存数据还是存在的。
第二种:根据索引值删除元素的pop()方法
根据索引值删除元素的pop()方法的语法结构是:listname.pop(index)
,其中,listname表示列表名称,index表示索引值,如果不写index参数,默认会删除列表中最后一个元素,类似于数据结构中的出栈操作。举个例子:
name_list = ['码农飞哥', '小伟', '小小伟', '超人'] # 删除list末尾的元素 name_list.pop() print(name_list) # 删除指定位置的元素,用pop(i)方法,其中i是索引位置 name_list.pop(1) print(name_list)
运行结果是:
['码农飞哥', '小伟', '小小伟'] ['码农飞哥', '小小伟']
第三种:根据元素值进行删除的remove()方法
根据元素值进行删除的remove()方法,其语法结构是:listname.remove(object)
,其中listname表示列表的名称,object表示待删除的元素名称。需要注意的是:如果元素在列表中不存在则会报ValueError的错误。举个栗子:
name_list = ['码农飞哥', '小伟', '小小伟', '超人'] name_list.remove('小小伟') print(name_list)
运行结果是:['码农飞哥', '小伟', '超人']
。
第四种:删除列表中的所有元素clear()方法
通过clear()方法可以删除掉列表中的所有元素,其语法结构是:listname.clear()
,其中listname表示列表的名称。还是举个栗子吧:
name_list = ['码农飞哥', '小伟', '小小伟', '超人'] name_list.clear() print(name_list)
运行结果是:[]
,可以看出列表中元素被全部清空了。
说完了第五浅列表元素的删除,略感疲惫。接着进行第六浅吧!看看列表中元素的查找以及访问。看完这个之后,列表相关的内容也就告一段落了。
访问列表中的元素有两种方式,分别是通过索引定位访问单个元素,通过切片访问多个元素。
第一种:通过索引定位访问单个元素,其语法结构是:listname[index]
,其中listname表示列表的名字,index表示要查找元素的索引值。
第二种:通过切片的方式访问多个元素,其语法结构是:listname[start:end:step]
。其中,listname表示列表的名字,start表示开始索引,end表示结束索引(不包括end位置),step表示步长。同样是举个栗子:
list2 = ['码农飞哥', '小伟', '小小伟',123] print(list2[0]) # 输出列表的第一个元素 print(list2[1:3]) # 输出第二个至第三个元素 print(list2[2:]) # 输出从第三个开始至列表末尾的所有元素
运行结果是:
码农飞哥 ['小伟', '小小伟'] ['小小伟', 123]
indext()方法用来查找某个元素在列表中出现的位置(也就是索引),如果该元素在列表中不存在,则会报ValueError错误。其语法结构是:listname.index(object, start, end)
其中listname表示列表的名字,object表示要查找的元素,start表示起始索引,end表示结束索引(不包括)。
name_list = ['码农飞哥', '小伟', '小小伟', '超人'] print(name_list.index('小伟', 0, 2))
运行结果是:1
前面介绍了使用+运算符,使用append方法,使用extend方法都可以新增元素,那么他们到底有啥区别呢?还是举例说明吧;
name_list = ['码农飞哥', '小伟', '小小伟', '超人'] name_list2 = ['牛魔王'] name_list3 = name_list + name_list2 print("原始的name_list的值={0};内存地址={1}".format(name_list, id(name_list))) print("使用+运算符后name_list3的值={0};内存地址={1}".format(name_list3, id(name_list3))) print("使用+运算符后name_list的值{0};内存地址={1}".format(name_list, id(name_list))) name_list4 = name_list.append('牛魔王') print('使用append方法后name_list4的值={0};内存地址={1}'.format(name_list4, id(name_list4))) print("使用append方法后name_list的值{0};内存地址={1}".format(name_list, id(name_list))) name_list5 = name_list.extend('牛魔王') print('使用extend方法后name_list5的值={0};内存地址={1}'.format(name_list4, id(name_list4))) print("使用extend方法后name_list的值{0};内存地址={1}".format(name_list, id(name_list)))
运行结果是:
原始的name_list的值=['码农飞哥', '小伟', '小小伟', '超人'];内存地址=2069467533448 使用+运算符后name_list3的值=['码农飞哥', '小伟', '小小伟', '超人', '牛魔王'];内存地址=2069467533896 使用+运算符后name_list的值['码农飞哥', '小伟', '小小伟', '超人'];内存地址=2069467533448 使用append方法后name_list4的值=None;内存地址=2012521616 使用append方法后name_list的值['码农飞哥', '小伟', '小小伟', '超人', '牛魔王'];内存地址=2069467533448 使用extend方法后name_list5的值=None;内存地址=2012521616 使用extend方法后name_list的值['码农飞哥', '小伟', '小小伟', '超人', '牛魔王', '牛', '魔', '王'];内存地址=2069467533448
从运行结果可以看出如下几点:
说完了列表,接着让我们来看看另外一个重要的序列–元组(tuple),和列表类似,元组也是由一系列按特定书序排序的元素组成,与列表最重要的区别是,元组属于不可变序列,即元组一旦被创建,它的元素就不可更改了。
第一种:使用()
直接创建
使用()
创建元组的语法结构是tuplename=(element1,element2,....,elementn)
,其中tuplename表示元组的变量名,element1~elementn表示元组中的元素。小括号不是必须的,只要将元素用逗号分隔,Python就会将其视为元组。还是举个栗子:
#创建元组 tuple_name = ('码农飞哥', '小伟', '小小伟', '超人') print(tuple_name) #去掉小括号创建元组 tuple2 = '码农飞哥', '小伟', '小小伟', '超人' print(type(tuple2))
运行结果是:
('码农飞哥', '小伟', '小小伟', '超人') <class 'tuple'>
第二种:使用tuple()
函数创建
与列表类似的,我们可以通过tuple(iterable)
函数来创建元组,如果iterable传入为空,则创建一个空的元组,iterable 参数必须是可迭代的序列,比如字符串,列表,元组等。同样的iterable不能传入一个数字。举个栗子:
name_list = ['码农飞哥', '小伟', '小小伟', '超人'] print(tuple(name_list)) print(tuple('码农飞哥'))
运行结果是:
('码农飞哥', '小伟', '小小伟', '超人') ('码', '农', '飞', '哥')
由于元组是不可变序列,所以没有修改元素相关的方法,只能对元组中的元素进行查看。查看元素的方式也与列表类似,共两种方式:
第一种:通过索引(index)访问元组中的元素,其语法结构是tuplename[index]
第二种:通过切片的方式访问,其语法结构是:tuplename[start:end:step]
相关参数的描述在此不再赘述了。依然是举例说明:
tuple_name = ('码农飞哥', '小伟', '小小伟', '超人') # 获取索引为1的元素值 print(tuple_name[1]) #获取索引为1到索引为2之间的元素值,不包括索引2本身 print(tuple_name[0:2])
运行结果是:
小伟 ('码农飞哥', '小伟')
元组中的元素不能修改,不过可以通过 + 来生成一个新的元组。
详细内容可以查看【Python从入门到精通】(六)Python内置的数据类型-列表(list)和元组(tuple),九浅一深,十个章节,不信你用不到
创建字典的方式有很多种,下面罗列几种比较常见的方法。
第一种:使用 {} 符号来创建字典,其语法结构是dictname={'key1':'value1', 'key2':'value2', ..., 'keyn':valuen}
第二种:使用fromkeys方法,其语法结构是dictname = dict.fromkeys(list,value=None)
, 其中,list参数表示字典中所有键的列表(list),value参数表示默认值,如果不写则为所有的值都为空值None。
第三种:使用dict方法,其分为四种情况:
for k, v in iterable: d[k] = v
dict(**kwargs)
-> **kwargs
是可变函数,其调用的语法格式是:dict(key1=value1,key2=value2,...keyn=valuen)
,例如:dict(name='码农飞哥', age=17, weight=63)
#1. 创建字典 d = {'name': '码农飞哥', 'age': 18, 'height': 185} print(d) list = ['name', 'age', 'height'] # 2. fromkeys方法 dict_demo = dict.fromkeys(list) dict_demo1 = dict.fromkeys(list, '测试') print(dict_demo) print(dict_demo1) # 通过dict()映射创建字典,传入列表或者元组 demo = [('name', '码农飞哥'), ('age', 19)] dict_demo2 = dict(demo) print(dict_demo2) dict_demo21 = dict(name='码农飞哥', age=17, weight=63) print(dict_demo21)
运行结果是:
{'name': '码农飞哥', 'age': 18, 'height': 185} {'name': None, 'age': None, 'height': None} {'name': '测试', 'age': '测试', 'height': '测试'} {'name': '码农飞哥', 'age': 19} {'name': '码农飞哥', 'age': 17, 'weight': 63}
说完了字典的创建之后,接着就让我们来看看字典的访问。字典不同于列表和元组,字典中的元素不是依次存储在内存区域中的;所以,字典中的元素不能通过索引来访问,只能是通过键来查找对应的值。 ,其有两种不同的写法。
dictname[key]
,其中dictname表示字典的名称,key表示指定的键。如果指定的键不存在的话,则会报KeyError 错误。dictname.get(key)
,其中dictname表示字典的名称,key表示指定的键。如果指定的键不存在的话,则会返回None。name
查找其对应的值。dict_demo5 = {'name': '码农飞哥', 'age': 18, 'height': 185} print(dict_demo5['name']) print(dict_demo5.get('name')) print('键不存在的情况返回结果=',dict_demo5.get('test'))
运行结果是:
码农飞哥 码农飞哥 键不存在的情况返回结果= None
添加键值对的方法很简单,其语法结构是dictname[key]=value
,如果key在字典中不存在的话,则会新增一个键值对。如果key在字典中存在的话,则会更新原来键所对应的值。依然是举例说明下:本例中代码的结果是增加键值对 sex='男'
,把键height对应的值改成了190
。
# 添加键值对 dict_demo6 = {'name': '码农飞哥', 'age': 18, 'height': 185} dict_demo6['sex'] = '男' print('新增键值对的结果={0}'.format(dict_demo6)) # 修改键值对 dict_demo6['height'] = 190 print('修改键值对的结果={0}'.format(dict_demo6))
运行结果是:
新增键值对的结果={'age': 18, 'name': '码农飞哥', 'height': 185, 'sex': '男'} 修改键值对的结果={'age': 18, 'name': '码农飞哥', 'height': 190, 'sex': '男'}
当然修改和删除键值对也可以通过update方法来实现,其具体的语法格式是:dictname.update(dict)
,其中,dictname为字典的名称,dict为要修改的字典的值。该方法既可以新增键值对,也可以修改键值对。 该方法没有返回值,即是在原字典上修改元素的。下面例子中就是将键name的值改成了飞飞1024,键age对应的值改成了25。并新增了键值对 like=学习
。
# update方法 dict_demo7 = {'name': '码农飞哥', 'age': 18, 'height': 185, 'width': 100} dict_demo7.update({'name': '飞飞1024', 'age': 25, 'like': '学习'}) print('update方法返回结果={}', dict_demo7)
运行结果为:
update方法返回结果={} {'height': 185, 'like': '学习', 'width': 100, 'name': '飞飞1024', 'age': 25}
删除键值对的方法有三种:
del dictname[key]
,使用del关键字,其中dictname为字典的名称,key为要删除的键。如果键不存在的话则会报KeyError错误。dictname.pop(key)
。该方法是用于删除指定键值对,没有返回值,如果key不存在的话不会报错。dictname.popitem()
。该方法用于删除字典中最后一个键值对。举例说明下吧:dict_demo10 = {'name': '码农飞哥', 'age': 18, 'height': 185, 'width': 100} # 删除键值对 del dict_demo6['height'] print('删除键height对之后的结果=', dict_demo6) # pop()方法和popitem()方法 dict_demo10.pop('width') print('pop方法调用删除键width之后结果=', dict_demo10) dict_demo10 = {'name': '码农飞哥', 'age': 18, 'height': 185, 'width': 100} dict_demo10.popitem() print('popitem方法调用之后结果=', dict_demo10)
运行结果是:
删除键height对之后的结果= {'name': '码农飞哥', 'sex': '男', 'age': 18} pop方法调用删除键width之后结果= {'name': '码农飞哥', 'height': 185, 'age': 18} popitem方法调用之后结果= {'name': '码农飞哥', 'age': 18, 'height': 185}
可以看出popitem方法删除的键是最后一个键width。
详细内容可以查看【Python从入门到精通】(七)Python字典(dict)让人人都能找到自己的另一半(键值对,成双成对)
列表推导式的语法格式是
[表达式 for 迭代变量 in 可迭代对象 [if 条件表达式] ]
此格式中,[if 条件表达式]
不是必须的,可以使用,也可以省略。下面就是输出1~10的列表的乘积的一个例子:
L = [x * x for x in range(1, 11)] print(L)
此表达式相当于
L = [] for x in range(1, 11): L.append(x * x) print(L)
运行结果是:
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
来点复杂的吧,下面就是输出
print([x for x in range(1, 11) if x % 2 == 0])
运行结果是[2, 4, 6, 8, 10]
再来点复杂的,使用多个循环,生成推导式。
d_list = [(x, y) for x in range(5) for y in range(4)] print(d_list)
运行结果是:
[(0, 0), (0, 1), (0, 2), (0, 3), (1, 0), (1, 1), (1, 2), (1, 3), (2, 0), (2, 1), (2, 2), (2, 3), (3, 0), (3, 1), (3, 2), (3, 3), (4, 0), (4, 1), (4, 2), (4, 3)]
上面代码,x是遍历range(5)的迭代变量(计数器),因此该x可迭代5次,y是遍历range(4)的计数器,因此该y可迭代4次。因此,该(x,y)表达式一共迭代了20次。它相当于下面这样一个嵌套表达式。
dd_list = [] for x in range(5): for y in range(4): dd_list.append((x, y)) print(dd_list)
元组推导式与列表推导式类似,其语法结构是:
(表达式 for 迭代变量 in 可迭代对象 [if 条件表达式] )
此格式中,[if 条件表达式]
不是必须的,可以使用,也可以省略。下面就是输出1~10的元组的乘积的一个例子:
d_tuple = (x * x for x in range(1, 11)) print(d_tuple)
运行结果是:
<generator object <genexpr> at 0x103322e08>
从上面的执行结果可以看出,使用元组推导式生成的结果并不是一个元组,而是一个生成器对象。
使用tuple()函数,可以直接将生成器对象转换成元组。例如:
d_tuple = (x * x for x in range(1, 11)) print(tuple(d_tuple))
输出结果是(1, 4, 9, 16, 25, 36, 49, 64, 81, 100)
字典推导式的语法结构是:
{表达式 for 迭代变量 in 可迭代对象 [if 条件表达式]}
其中[if 条件表达式]
可以使用,也可以省略。举个例子:
key_list = ['姓名:码农飞哥', '年龄:18', '爱好:写博客'] test_dict = {key.split(':')[0]: key.split(':')[1] for key in key_list} print(test_dict)
运行结果是:
{'爱好': '写博客', '年龄': '18', '姓名': '码农飞哥'}
通过yield关键字配合循环可以做一个生成器,就像下面这样
def generate(): a = 2 while True: a += 1 yield a b = generate() print(b) print(next(b)) print(next(b)) print(next(b))
运行结果
<generator object generate at 0x7fc01af19b30> 3 4 5
这里generate方法返回的就是一个生成器对象generator,因为它内部使用了yield关键字,
调用一次next()方法返回一个生成器中的结果。这就很像单例模式中的懒汉模式,他并并不像饿汉模式一样事先将列表数据生成好。
流程控制有三种结构,一种是顺序结构,一种是选择(分支)结构,一种是循环结构。
顺序结构:就是让程序按照从头到尾的顺序执行代码,不重复执行任何一行代码,也不跳过任何一行代码。一步一个脚印表示的就是这个意思。
选择(分支)结构:就是让程序根据不同的条件执行不同的代码,比如:根据年龄判断某个人是否是成年人。
循环结构: 就是让程序循环执行某一段代码。顺序的流程这里不做介绍了。
只使用if语句是Python中最简单的形式。如果满足条件则执行表达式。则跳过表达式的执行。其伪代码是:
if 条件为真: 代码块
如果if 后面的条件为真则执行代码块。否则则跳过代码的执行。
其流程图是:
就是说只使用if的话,则表达式成立的话执行代码块,不成立的话就结束。
下面就是一个简单的例子,如果满足a==1这个条件则打印a,否则跳过该语句。
a = 1 if a == 1: print(a)
if else语句是if的变体,如果满足条件的话则执行代码块1,否则则执行代码块2。其伪代码是:
if 条件为真: 代码块1 else 代码块2
流程图是:
同时使用if和else的话,则表达式成立的话执行一个代码块,表达式不成立的话则执行另一个代码块。
举个简单的例子吧。
age = 3 if age >= 18: print('your age is', age) print('adult') else: print("your age is", age) print('kid')
根据输入的年龄判断某人是否是成年人。如果age大于等于18岁,则输出adult,否则输出kid。
if elif else语句针对的就是多个条件判断
的情况,如果if条件不满足则执行elif的条件,如果elif的条件也不满足的话,则执行else里面的表达式。其伪代码是:
if 条件为真: 表达式a elif 条件为真: 表达式b .... elif 条件为真: 表达是n-1 else 表达式n
其中elif可以有多个,但是elif不能单独使用,必须搭配if和else一起使用。
需要注意的是if,elif和else后面的代码块一定要缩进,而且缩进量要大于if,elif和else本身,建议的缩进量是4个空格。同一代码中所有语句都要有相同的缩进。 依然是举例说明:
bmi = 80.5 / (1.75 * 1.75) if bmi < 18.5: print('过轻') elif 18.5 <= bmi < 25: print('正常') elif 25 <= bmi < 28: print('过重') elif 28 <= bmi < 32: print('肥胖') else: print('严重肥胖') pass
下面就是根据bmi标准来判断一个人是过轻,正常还是肥胖。pass是Python中的关键字,用来让解释器跳过此处,什么都不做。
while是作为循环的一个关键字。其伪代码是:
while 条件表达式: 代码块
一定要保证循环条件有变成假的时候,否则这个循环将成为一个死循环,即该循环无法结束。 其流程图是:
如果while中的表达式成立的话则执行循环体,否则的话则直接结束。
举个栗子:计算从1~100的求和,这就是一个经典的运用循环的场景
sum = 0 n = 1 while n <= 100: sum = sum + n n = n + 1 print('sum=', sum)
运行结果是sum= 5050
,这个循环的结束条件是n>100,也就是说当n>100是会跳出循环。
在介绍range函数时用到了for关键字,这里介绍一下for关键字的使用。其语法结构是:
for 迭代变量 in 字符串|列表|元组|字典|集合: 代码块
字符串,列表,元祖,字典,集合都可以还用for来迭代。其流程图是:
for 循环就是:首先根据in 关键字判断序列中是否有项,如果有的话则取下一项,接着执行循环体。如果没有的话则直接结束循环。
详细内容可以查看【Python从入门到精通】(十)Python流程控制的关键字该怎么用呢?列表推导式,生成器【收藏下来,常看常新】
函数是按照固定格式封装组织的可以重复使用的代码段。它能提高应用的模块性和代码的重复利用率。
函数定义的语法格式是:
def 函数名(参数列表): 代码块 [return [返回值]]
函数名:其实就是一个符合Python语法的标识符,函数名最好能体现该函数的功能,比如: save_user。
形参列表:设置该函数可以接收多少个参数,多个参数之间用逗号(,)分割。需要注意的是没有参数的话,也需要留一对空的()
[return[返回值]]
:整体作为函数的可选参数,用于设置该函数的返回值。也就是说,一个函数,
可以有返回值,也可以没有返回值。
调用函数的语法格式是:
[返回值]=函数名([形参值])
函数名即指的是要调用的函数的名称,形参值指的是当初创建函数时要求传入的各个形参的值。
如果该函数有返回值,我们可以通过一个变量来接收该值,当然也可以不接收。需要注意的是,函数有多少个形参,那么调用的时候就需要传入多少个值,
且顺序必须和创建函数时一致。即便该函数没有参数,函数名后的小括号也不能省略。
举个栗子吧:
def my_abs(x): """ 返回绝对值 :param x: :return: """ if not isinstance(x, (int, float)): raise TypeError('传入的数据类型不对') if x >= 0: return x else: return -x
调用代码是:
x = my_abs(-3) print(x) print(my_abs.__doc__)
运行结果是:
3 返回绝对值 :param x: :return:
这是一个获取绝对值的函数,其函数名是my_abs,通过函数名可以让人大致明白函数的作用。形式参数是x。通过__doc__可以查看函数的说明文档。其返回值是处理后的值。
介绍函数值传递和引用传递之前首先需要了解两个概念。
def param_test(obj): obj += obj print('形参值为:', obj) print('*******值传递*****') a = '码农飞哥' print('a的值为:', a) param_test(a) print('实参的值为:', a) print("*******引用传递*****") b = [1, 2, 3] print('b的值为:', b) param_test(b) print('实参的值为:', b)
运行结果是:
*******值传递***** a的值为: 码农飞哥 形参值为: 码农飞哥码农飞哥 实参的值为: 码农飞哥 *******引用传递***** b的值为: [1, 2, 3] 形参值为: [1, 2, 3, 1, 2, 3] 实参的值为: [1, 2, 3, 1, 2, 3]
位置参数,有时也被称为必备参数,指的是必须按照正确的顺序将实参传到函数中,换句话说,调用函数时传入实参的数量和位置必须和定义函数时保持一致。如果不一致的话,则在程序运行时Python解释器会报TypeError异常。举个例子,下面演示调用函数事参数传入的数量不对的情况。
def girth(width , height): return 2 * width+height #调用函数时,必须传递 2 个参数,否则会引发错误 print(girth(3))
运行之后直接报Traceback错误。
Traceback (most recent call last): File "/Volumes/Develop/Python_learn/PycharmProjects/python_demo_1/demo/function/locate_fun.py", line 6, in <module> print(girth(3)) TypeError: girth() missing 1 required positional argument: 'height'
传入参数的位置不对的情况,本例中本想传入name的值为码农飞哥,age的值为18。结果入参顺序不对导致得到的结果不对。
def print_info(name, age): print('姓名=' + name + " 年龄=" + str(age)) print_info(18,'码农飞哥')
那么怎么处理这种情况呢?有两种方式:
def print_info(name, age): print('姓名=' + name + " 年龄=" + str(age)) print_info(age=18,name='码农飞哥')
运行结果是:
姓名=码农飞哥 年龄=18
可以看出关键字参数入参时,不需要保证入参的顺序跟形参的顺序保持一致。
前面介绍的位置参数,就是说调用函数时必须要传入该参数。但是有些场景下我们并不想传入所有的参数。这种情况下就可以使用默认参数了。不过需要注意的是:指定有默认值的形式参数必须在所有没默认值的参数的最后,否则会产生语法错误。其语法格式是:
def 函数名(...,形参名,形参名=默认值): 代码块
下面给出一个示例,该函数是记录学生的信息,有两个有默认值的参数,分别是age和city。它们都被置于函数的形参列表最后处。
def enroll(name, gender, age=6, city='Beijing'): print('name:', name) print("gender:", gender) print("age:", age) print("city:", city) print(enroll('张三', '一年级')) print('************************** ') print(enroll('李四', '二年级', 7))
运行结果是:
name: 张三 gender: 一年级 age: 6 city: Beijing None ************************** name: 李四 gender: 二年级 age: 7 city: Beijing None
从上面代码可以看出:1. 可以不用传入有默认值的参数。2. 如果传入默认的参数,则会覆盖掉默认值。
Python函数可变参数(*args
,**kwargs
),又称为不定长参数,即传入函数中的实际参数可以是任意多个,Python定义可以变参数,主要有以下两种形式:
*
,格式是*args
。表示创建一个名为args的空元组,该元组可以接受任意多个外界传入的非关键字实参。必须以非关键字参数的形式给普通参数传值,否则Python解释器会把所有参数都优先传给可变参数。**kwargs
表示创建一个名为kwargs的空字典,该字典可以接受任意多个以关键字参数赋值的实参。举个