不要问为什么选择python
问就是工作需要!!!
1989年,为了打发圣诞节假期,Gudio van Rossum吉多· 范罗苏姆(龟叔)决心开发一个新的解释程序(Python雏形)
1991年,第一个Python解释器诞生
Python这个名字,来自龟叔所挚爱的电视剧Monty Python’s Flying Circus
简单、易学、开发效率高、适用面广
python环境安装在另一篇中有讲解点这里跳转
向世界说你好,应该是全世界,所有程序员入门编程语言时,都会选择的第一个程序。
让我们也延续这一份来自程序员之间的浪漫,学习如何使用Python,向世界说你好。
我们的Python代码非常简单
print(“Hello World!!!”)
向屏幕输出(显示)Hello World!!!
python不像C/C++等,必须要头文件,但使用一些库的时候还是要引用出来
打印字符串加单引号或双引号都可以,数字直接输出,不用引号,自动添加换行
若不需要换行时,可这样写:print(“hello”, end=‘’)
加上end=''就不会换行
python中,字符串需要用双引号 " " 括起来
被引号包围的都是字符串
注释不是程序,不能被执行,只是对程序进行解释说明,让别人看懂程序的作用,能够大大增加程序的可读性
单行注释 # ,#右侧内容不会被执行;建议在使用注释时,在#后面加个空格
name = "张三" # 定义了一个值为张三的变量
多行注释:英文符号双引号 “”" “”"
"""
这里是多行注释
三个英文符号双引号
这里不会被程序执行
"""
变量是在程序运行时,能储存计算结果或能表示值的抽象概念。简单的说,变量就是在程序运行时,记录数据用的
变量,从名字中可以看出,表示“量”是可变的。
所以,变量的特征就是,变量存储的数据,是可以发生改变的。
变量的目的是存储运行过程的数据,存储的目的是为了重复使用
print(内容1, 内容2...内容N) # 直接输出就行,中间加上逗号
前期先从基础的开始
类型 | 描述 | 说明 |
---|---|---|
string | 字符串类型 | 用引号引起来的数据都是字符串 |
int | 整型(有符号) | 数字类型,存放整数 |
float | 浮点型(有符号) | 数字类型,存放小数 |
我们通过type(变量)可以输出类型,这是查看变量的类型还是数据的类型?
查看的是:变量存储的数据的类型。因为,变量无类型,但是它存储的数据有。
所谓字符串变量,不是说变量是字符串,而是它存储了 字符串
字符串定义一般有单引号’内容’ 双引号 “内容” 还有三个双引号 “”“内容”“”
这里的三个双引号和注释类似,支持换行操作。使用变量接收它,它就是字符串,不使用变量接收它,就可以作为多行注释使用。
单引号定义法,可以内含双引号
双引号定义法,可以内含单引号
可以使用转移字符 \ 来将引号解除效用,变成普通字符串
如果我们有两个字符串字面量,可以将其拼接成一个字符串,通过加号 + 即可完成
name_boy = "立花泷"
name_girl = "宫水三叶"
print("你的名字" + name_boy + name_girl)
输出:你的名字立花泷宫水三叶
拼接字符串时,如果变量太多,就会很麻烦,而且字符串和数字还不能拼接,那怎么办呢?
这里就可以通过字符串和变量来完成快速拼接
name_boy = "立花泷"
name_girl = "宫水三叶"
num = 2
name = "你的名字 %s %s %d" % (name_boy, name_girl, num)
print(name)
输出:你的名字 立花泷 宫水三叶 2
这里的%s
% 表示这个位置我要了
s 将变量变成字符串放入占位的地方
字符串无法和非字符串拼接,因为类型不一致,无法接上,就像接力赛一样,不是队友无法进行接力
多个变量占位,需要用括号将变量括起来,并按顺序填入
%s 将内容转换成字符串
%d 将内容转换成整数
%f 将内容转换成浮点型
这里是也可以通过%s来进行拼接数字,但是拼接的数字是自动转换为字符串类型的
我们可以使用辅助符号"m.n"来控制数据的宽度和精度
m 控制宽度,要求是数字(很少使用),设置的宽度小于数字自身,不生效
n 控制小数点精度,要求是数字,会进行小数的四舍五入
%5d:表示将整数的宽度控制在5位,如数字11,被设置为5d,就会变成:[空格][空格][空格]11,用三个空格补足宽
度。
%5.2f:表示将宽度控制为5,将小数点精度设置为2
小数点和小数部分也算入宽度计算。如,对11.345设置了%7.2f后,结果是:[空格][空格]11.35。2个空格补足宽度,小数部分限制2位精度后,小数部分四舍五入为.35
%.2f:表示不限制宽度,只设置小数点精度为2,如11.345设置%.2f后,结果是11.35
目前通过%符号占位已经很方便了,还能进行精度控制。
可是追求效率的Python,是否有更加优雅的方式解决问题呢?
答案是:有
通过语法:f"内容{变量}"的格式来快速格式化
name = "张三"
age = 100
birthday = 13.32
print(f"你的名字是{name}, 年龄是{age}, 生日是{birthday}")
输出:你的名字是张三, 年龄是100, 生日是13.32
这种写法不会做精确控制
也不理会类型
适用于快速格式化字符串
表达格式化是比上面两种更简便的写法
所谓表达式:一条具有明确执行结果的代码语句
1+1, 2*2 这就是表达式,因为有具体的结果,结果是一个数字
或者常见的变量定义:
name = "张三" age = 11 + 11
等号右侧的都是表达式呢,因为它们有具体的结果,结果赋值给了等号左侧的变量。
直接格式化一个表达式:
print(f"22={22}")
print(“字符串在Python中的类型是:%s”% type(‘字符串’))
在无需使用变量进行数据存储的时候,可以直接格式化表达式,简化代码
数据类型之间,在特定的场景下,是可以相互转换的,如字符串转数字、数字转字符串等
从文件中读取的数字,默认是字符串,我们需要转换成数字类型
后续在input()语句,默认结果是字符串,若需要数字也需要转换
将数字转换成字符串用以写出到外部系统
int(x) | 将x转换成一个整数 |
---|---|
float(x) | 将x转换成一个浮点数 |
str(x) | 将x转换为字符串 |
若是遇见无法转换的类型,比如字符串中有数字以外的类型,则无法转换为int类型,就会报错
浮点型转换整数会丢失小数点后的数字,也就是丢失精度
在Python程序中,我们可以给很多东西起名字,比如:变量的名字
方法的名字类的名字,等等
这些名字,我们把它统一的称之为标识符,用来做内容的标识。
所以,标识符是用户在编程的时候所使用的一系列名字,用于给变量、类、方法等命名。
标识符命名中,只允许出现
英文、中文、数字、下划线_
这四类元素。
其余任何内容都不被允许。
这里不推荐使用中文
!!数字不能作为开头
dog = "旺财"
Dog = "富贵"
一个字母的大小写是完全能够区分标识符的
Python中有一系列单词,称之为关键字关键字在Python中都有特定用途
这些关键字我们不可以使用它们作为标识符,会出问题
学完了标识符(变量、类、方法)的命名规则后,在来学习标识符的命名规范。
变量名
类名
方法名
不同的标识符,有不同的规范
目前只接触到了:变量。所以,目前学习:变量的命名规范。
见名知意
明了:尽量做到,看到名字,就知道变量什么意思
简洁:在确保“明了”的前提下下,减少名字的长度
下划线命名法
多个单词组合的变量名,尽量使用下划线分隔
英文字母全小写
命名表变量中的英文字母,应全部小写
运算符 | 描述 | 实例 |
---|---|---|
+ | 加 | 两个对象相加 a+b 输出结果 n |
- | 减 | 得到两个数的差 |
* | 乘 | 两数相乘取得的结果 |
/ | 除 | b/a输出结果,除法计算 |
// | 取整除 | 返回商的整数部分 9//2 输出结果 4 |
% | 取余 | 返回余数 |
** | 指数 | a**b意为a的b次方 |
等号 = 把的能耗右边的结果 赋给 左边的变量,如num=1+2*3,结果num的值为7
运算符 | 描述 | 实例 |
---|---|---|
+= | 加法赋值运算符 | c+=a等效于c=c+a |
-= | 减法赋值运算符 | c-=a等效于c=c-a |
*= | 乘法赋值运算符 | c*=a等效于c=c*a |
/= | 除法赋值运算符 | c/=a等效于c=c/a |
%= | 取模赋值运算符 | c%=a等效于c=c%a |
**= | 幂赋值运算符 | c**=a等效于c=c**a |
//= | 取整除赋值运算符 | c//=a等效于c=c//a |
input函数对应print函数是从键盘获取输入
使用一个变量接收input语句获取的键盘输入数据
print("Who are you?")
name = input()
print("I am " + name)
这里还可以简化写法,可以在要求使用者输入内容前,输出提示内容
name = input("Who are you?")
print("I am " + name)
进行逻辑判断,是生活中常见的行为。同样,在程序中,进行逻辑判断也是最为基础的功能。
判断在程序中广泛应用,如果没有它,这些功能都难以实现
比如网站登录、APP登录、景区验票、车牌识别等
判断是程序最基础、最核心的功能
判断真和假,也就是说只有是或者否两种结果
python中常用的6重数据类型
布尔类型的字面量:
True表示真(是、肯定)
False表示假(否、否定)
定义变量存储布尔类型数据:
变量名称=布尔类型字面量
布尔类型不仅可以自行定义同时也可以通过计算的来
也就是使用比较运算符进行比较运算得到布尔类型的结果
布尔类型的数据,不仅可以通过定义得到,也可以通过比较运算符进行内容比较得到。
result = 10 > 5
print(f"10 > 5的结果是:{result},类型是:{type(result)}")
# 输出:10>5的结果是:Ture,类型是:
判断嘛,是从 如果→动作 的运动方式
比如说,如果小美喜欢我,明天我就去表白
程序中写法
# if 要判断的条件:
# 条件达成时, 要做的事
grade = 70
if grade <= 90:
print("考试结束")
print("成绩不及格")
print("请回中心打印成绩单")
这里判断条件就是要分数大于90
符合就执行后面的打印语句,不符合则直接跳过if和以下的这段打印代码
判断语句的结果,必须是布尔类型True或FalseTrue会执行if内的代码语句
False则不会执行
归属于if断的代码语句块,需在前方填充4个空格缩进,也就是一个tab键
Python通过缩进判断代码块的归属关系,若前面没有空格或不符时则被编译器认为是if以外的代码,不会代入到判断语句内从而影响程序结果
判断条件后面的冒号不要忘记!
当if无法满足判断需求的时候呢,else就冒出来了
这时候就变成了:如果→动作,否则→动作
比如说,如果小美喜欢我,明天我就去表白,否则我就去追求小新
程序中写法
grade = 70
if grade <= 90:
print("考试结束")
print("成绩不及格")
print("请回中心打印成绩单")
else:
print("考试结束")
print("成绩合格")
print("请回中心打印成绩单")
else后面不需要判断条件
这就是说,当你的判断条件满足时,就会执行,不满足时,就会 直接 执行另一个条件
和if一样,else也需要缩进四个空格
这里是:如果1→动作,如果2→动作,如果N→动作,否则→动作
比如说,如果小美喜欢我,明天我就去表白,或者小甜喜欢我,明天我去表白,否则我就去追求小新
程序中写法
age = 16
height = 175
if age < 18: # 1
print("年龄太小了")
elif height < 180 # 2
print("有点矮,不合适")
else # 3
print("年龄或身高合格")
print("已加入该社团")
这段代码如果执行的话就会报错
因为没有加 ’ : ’
elif语句可以写很多个,用来判断各种可能发生的事件
这段代码执行时,若1符合判断条件,进行输出后,则不会在执行2和3
1不满足但满足2时,执行2,不会执行3,1和2都不满足时,则进入else,也就是3
注意点:这里还是缩进,千万不要忘了!
input语句也是可以写入判断中的,用来节省代码量
例
if int(input("请输入你的年龄:")) < 18:
print("年龄太小")
else:
print("年龄合适")
在满足一项要求的前提下进行另一条要求的判断
这里就显出了缩进的关键性,通过缩进满足层次关系
if 条件1:
满足条件1 做的事情1
满足条件1 做的事情2
if条件2:
满足条件2 做的事情1
满足条件2 做的事情2
这种情况下可以自由组合if elif else,完成特定的需求
循环普遍存在于日常生活中,同样,在程序中,循环功能也是至关重要的基础功能。
循环在程序中同判断一样,也是广泛存在的,是非常多功能实现的基础:
像:循环广告牌、批量修图、视频轮播、音乐轮播、图片轮播、大喇叭喊话、动态壁纸等
循环是程序最基础、最核心的功能
举个例子,比如说:每天都像小美表白,知道成功为止
程序中,只要条件满足,就会无限循环执行
while 条件:
满足时最的事情1
满足时最的事情2
满足时最的事情3
满足时最的事情N
当第N次的时候,咱不说为啥,小美同意了,这时候跳出循环,循环结束
n = 0
while n = 101:
print("小美,表白")
n += 1
print("小美终于接受了你的表白")
这是一个美好的假设,从第0次开始,n每次加以用以计数,当程序执行到101次的时候,小美同意了;
但现实大多数都是:while True ……
1.while的条件需得到布尔类型,True表示继续循环,False表示结束循环
2.需要设置循环终止的条件,如i+= 1配合 i <100,就能确保100次后停止,否则将无限循环
3.空格缩进和if判断一样,都需要设置
while循环嵌套
while条件1:
条件1满足时﹐做的事情1
条件1满足时﹐做的事情2
条件1满足时﹐做的事情3
条件1满足时﹐做的事情N
while条件2:
条件2满足时,做的事情1
条件2满足时﹐做的事情2
条件2满足时﹐做的事情3
条件2满足时﹐做的事情N
这里同判断语句的嵌套一样,循环语句的嵌套,要注意空格缩进
基于空格缩进来决定层次关系
注意条件的设置,避免出现无限循环(除非真的需要无限循环)
除了while循环语句外,Python同样提供了for循环语句。两者能完成的功能基本差不多,但仍有一些区别:
. while循环的循环条件是自定义的,自行控制循环条件
. for循环是一种”轮询”机制,是对一批内容进行”逐个处理”
生活中的for循环:
洗碗,一个一个洗净
剥大蒜,一个一个剥
送快递,一个一个送
吃瓜子,一个一个吃
等都是一个一个逐渐完成
程序中
for 临时变量 in 待处理数据集:
循环条件满足时执行的代码
从待处理数据集中,逐个取出数据赋值给临时变量
name = "asdfghjkl"
for q in name:
print(q)
运行结果:
a
s
d
f
g
h
j
k
l
可以看出,for循环是将字符串的内容:依次取出
所以for循环也叫做:遍历循环
同while循环不同,for循环是无法定义循环条件的。
只能从被处理的数据集中,依次取出内容进行处理。
所以,理论上讲,Python的for循环无法构建无限循环(被处理的数据集不可能无限大)
for l临时变量in待处理数据集(可迭代对象):
循环满足条件时执行的代码
语法中的:待处理数据集,严格来说,称之为:可迭代类型
可迭代类型指,其内容可以一个个依次取出的一种类型,包括:
字符串、列表、元组等
for循环语句,本质上是遍历:可迭代对象
这里用一个简单的数字序列举例(可迭代的类型的一种)
range(num)
获取—个从0开始,到num结束的数字序列(不含num本身)如range(5)取得的数据是:[0,1,2,3,4]
range(num1,num2)
获得一个从num1开始,到num2结束的数字序列(不含num2本身)
如,range(5,10)取得的数据是:[5,6,7,8,9]
range(num1,num2,step)
获得一个从num1开始,到num2结束的数字序列(不含num2本身)
数字之间的步长以step为准(step默认为1)
如,range(5,10,2)取得的数据是:[5,7,9]
# for循环遍历range序列
for i in range(5)
print(i)
输出:
0
1
2
3
4
练习:
算出1-100中有多少个偶数出现(不包含100)
num = 0
for i in range(1, 100):
if i % 2 == 0:
num += 1
print("偶数有%d个" % num) # 49
for 临时变量 in 待处理数据集:
循环满足条件时执行的代码
临时变量:
如果在for循环外部访问临时变量:在编程规范上,作用范围(作用域),只限定在for循环内部实际上是可以访问到的,但是不允许、不建议这么做的,因为没有意义
如果实在需要在循环外访问循环内的临时变量,可以在循环外预先定义
i = 0
for i in range(5):
print(i)
print(i)
如上面代码,每一次循环的时候,都会将取出的值赋予i变量,由于i变量是在循环之前(外)定义的,在循环外访问i变量是合理的、允许的
就像在操场跑圈,需要跑10圈,每次跑完一圈之后都要做5个标记
for i in range(1, 11):
print(f"这是第{i}圈,加油")
for x in range(1, 6):
print(x)
print("终于跑完了,真棒")
这里的缩进也是和while的一样,要多注意
输出:
这是第1圈,加油
1
2
3
4
5
这是第2圈,加油
1
…
5
这是第10圈,加油
1
2
3
4
5
终于跑完了,真棒
continue关键字:中断本次循环,直接进入下一次循环
continue可用于:for循环和while循环,效果一致
就像每天都和小美表白,送一日三餐,直到成功
每天送餐的时候看小美脸色,今天不高兴就不送了,明天继续
通过代码实现小美心情
for i in range(1,101):
print(f"追求小美的第{i}天,坚持......")
print("给小美送早饭,比心")
print("给小美送午饭,比心")
if input(f"今天小美的心情好像(Q好心情,1坏心情)") == '1':
print("小美心情不好,晚饭不送了,撤退......")
print()
continue
print("给小美送晚饭,送小美回家并表白")
print()
break关键字用于:直接结束所在循环
break可以用于for和while循环,效果一致
每天都去向小美表白,送一日三餐,直到成功
某天小美说,不要再打扰我了,以后就不要缠着她了
代码实现小美心情
for i in range(1,101):
print(f"追求小美的第{i}天,坚持......")
print("给小美送早饭,比心")
print("给小美送午饭,比心")
if input(f"如果你是小美,请告诉我你是否明确拒绝(0再观察观察,1不合适拒绝)") == '1':
print("小美拒绝我了,以后不追求小美了。T.T")
break
print("给小美送晚饭,送小美回家并表白")
print()
函数是组织好的,可重复使用的,用来实现特定功能的代码段
使用函数的好处是:
将功能封装在函数内,可供随时随地重复利用
提高代码的复用性,减少重复代码,提高开发效率
函数的定义
def 函数名(传入参数):
函数体
return 返回值
函数的调用:
函数名(参数)
要注意:
参数如果不需要,可以省略
返回值如果不需要,可以省略
函数必须先定义后使用
传入参数的功能是:在函数进行计算的时候,接受外部(调用时)提供的数据
def add():
result = 1 + 2
print(f"1+2的结果是:{result}")
该函数的功能非常局限,只能计算1+2
有没有可以实现计算机去计算用户指定的两个数字呢?
有!使用函数传参功能,即可实现
基于函数的定义语法:
def 函数名(传入参数):
函数体
return 返回值
代码写法:
# 定义函数
def add(x, y):
result x + y
print(f("{x}+{y}的结果是:{rersult}"))
# 调用函数
add(2, 3)
实现了每次计算x+y而不是固定的1+2
x+y的值,可以在调用函数的时候指定
函数定义中,提供的x和y,称之为:形式参数(形参),表示函数声明将要使用2个参数
参数之间使用逗号进行分隔
函数调用中,提供的2和3,称之为:实际参数(实参),表示函数执行时真正使用的参数值
传入的时候,按照顺序传入数据,使用逗号分隔
传入的参数的数量可以是不受限制的
可以不使用参数
也可以仅使用任意N个参数
就好比你和你室友说,帮我带三瓶可乐,这里的三瓶就是参数
你舍友收到后,带回来三瓶可乐给你,这就是返回值,让你叫爸爸就是另一说了
所谓“返回值”,就是程序中函数完成事情后,最后给调用者的结果
def 函数(参数……):
函数体
return 返回值
变量 = 函数(参数)
如上,变量就能接收到函数的返回值
语法就是:通过return关键字,就能够向调用者返回数据
如果函数没有使用return语句返回数据,那么函数有返回值吗?
有!
Python中有一个特殊的字面量:None,其类型是:
None表示:空的、无实际意义的意思
函数返回的None,就表示,这个函数没有返回什么有意义的内容。也就是返回了空的意思。
这个就不写测试了,知道有这回事就可以了
None作为一个特殊的字面量,用于表示:空、无意义,其有非常多的应用场景
用在函数无返回值上
用在if判断上
·在if判断中,None等同于False
·一般用于在函数中主动返回None,配合if判断做相关处理
用于声明无内容的变量上
·定义变量,但暂时不需要变量有具体值,可以用None来代替
函数是纯代码语言,想要理解其含义,就需要一行行的去阅读理解代码,效率比较低。
我们可以给函数添加说明文档,辅助理解函数的作用。
通过多行注释的形式,对函数进行说明解释
·内容应写在函数体之前
在编写代码时,可通过鼠标悬停,查看调用函数的文档说明
和for、if嵌套一样,在一个函数中再调用另一个函数
def func_b():
print("---2---")
def func_a():
print("---1---")
func_b()
print("---3---")
func_a() # 调用函数func_a
# 输出:
---1---
---2---
---3---
如果函数A中,调用了另外一个函数B,那么先把函数B中的任务都执行完毕之后才会回到上次函数A执行的位置
变量作用域指的是变量的作用范围(变量在哪里可用,在哪里不可用)
主要分为两类:局部变量和全局变量
所谓局部变量是定义在函数体内部的变量,即只在函数体内部生效
定义在fun1函数中的变量,在函数外部调用时就会报错
局部变量的作用:在函数体内部,临时保存数据,即当函数调用完成后,则销毁局部变量
所胃全局变量,指的是在函数体内、外都能生效的变量
如果有一个数据,函数A、B都要用,这时就可以定义一个全局变量存储它们两个需要的数据
若一个函数内修改了全局变量的值,只会在该函数内有效,不影响其他函数
num = 1
def fun1():
num = 2
print(f"num是:{num}")
def fun2():
print(f"num是:{num}")
fun1() # 2
fun2() # 1
要在函数中修改全局变量的值,就用到了global关键字
num = 1
def fun1():
# global 关键字声明num是全局变量
global num
num = 2
print(f"num是:{num}")
def fun2():
print(f"num是:{num}")
fun1() # 2
fun2() # 2
如果要在程序中记录5名学生信息,如姓名,有两种方法
1.定义5个变量
2.一个变量完成(搞笑,我非要用定义5个变量,随便喽)
数据容器就是为了批量存储或批量使用多份数据
一种可以容纳多份数据的数据类型,容纳的每一份数据称之为1个元素
每一个元素,可以是任意类型的数据,如字符串、数字、布尔等
数据容器根据特点的不同,如:
是否支持重复元素
是否可以修改
是否有序等
分为5类,分别是:
列表(list)、元组(tuple) 、字符串(str)、集合(set)、字典(dict)
定义
基本语法:
# 字面量
[元素1,元素2,元素3……]
# 定义变量
变量名称 = [元素1,元素2,元素3……]
# 定义空列表
变量名称 = []
变量名称 = list()
列表的每一个数据,称之为元素
·以[]作为标识符
·列表内每一个元素之间用逗号隔开
name_list = ['ithello', 'itcase', 'python']
print(name_list)
print(type(name_list))
# 输出:
['ithello', 'itcase', 'python']
<class 'list'>
my_list = [[1, 2, 3], [4, 5, 6]]
print(my_list)
print(type(my_list))
# 输出:
[[1, 2, 3], [4, 5, 6]]
<class 'list'>
列表可以一次存储多个数据,且可以为不同的数据类型,支持嵌套
列表的下标索引
为了更简单的取出某个位置的数据,可以使用:下标索引
列表中的每一个元素,都有其位置下标索引,从前向后的方向,从0开始,依次递增
我们只需要按照下标索引,即可取得对应位置的元素
name_1ist = ['Tom', 'Li1y','Rose ']
print(name_list[0]) # 结果:Tom
print(name_1ist[1]) # 结果:Lily
print(name_list[2]) # 结果:Rose
反向索引,也就是从后向前:从-1开始,依次递减(-1、-2、-3……)
name_list = [ 'Tom', 'Li1y' , 'Rose ']
print(name_list[-1]) # 结果:Rose
print(name_list[-2]) # 结果:Lily
print(name_list[-3]) # 结果:Tom
# 2层嵌套1ist
my_1ist = [ [1,2,3],[4,5,6]]
# 获取内层第一个list
print(my_list[0]) # 结果:[1,2,3]
#获取内层第一个1ist的第一个元素
print(my_list[0][0]) # 结果:1
注意:下标索引的取值范围超出是无法取出元素的,而且会报错
·定义
·使用下标索引获取值
·插入元素
·删除元素
·清空列表
·修改元素
·统计元素个数
这些功能我们都称之为:列表的方法
回忆:函数是一个封装的代码单元,可以提供特定功能。
在Python中,如果将函数定义为class(类)的成员,那么函数会称之为:方法
# 函数
def add(x, y):
return x+y
# 方法
class Student:
def add(self, x, y):
return x+y
方法和函数功能一样,有传入参数,有返回值,只是方法的使用格式不同:
函数的使用:num = add(1, 2)
方法的使用:Student = Student()
num = Student.add(1, 2)
功能:查找指定元素在列表的下标,如果找不到,报错ValueError
语法:列表.index(元素)
index就是列表对象(变量)内置的方法(函数)
my_1ist = ["ithello", "itcase", "python"]
print(my_1ist.index("itcase) # 结果:1
·修改特定位置(索引)的元素值
语法:列表[下标] = 值
可以使用如上语法,直接对指定下标(正向反向下标均可)的值进行:重新赋值(修改)
#正向下标
my_list = [1,2,3]
my_list[0] = 5
print(my_list) # 结果:[5,2,3]
#反向下标
my_list = [1,2,3]
my_list[-3] = 5
print(my_list) # 结果:[5,2,3]
语法:列表.insert(下标元素),在指定的下标位置,插入指定的元素
my_list = [1,2,3]
my_list.insert(1, "ithello")
print(my_list) # 结果:[1,"ithello",3,4]
语法:列表.append(元素),将指定元素,追加到列表的尾部
my_list = [1,2,3]
my_list.append(4)
print(my_list) # 结果:[1,2,3,4]
my_list = [1,2,3]
my_list.append([4,5,6])
print(my_list) # 结果:[ 1,2,3,[4,5,6]]
语法:列表.extend(其它数据容器),将其它数据容器的内容取出,依次追加到列表尾部
my_list = [1,2,3]
my_1ist.extend([4,5,6])
print(my_list) # 结果:[1,2,3,4,5,6]
语法1:
del列表[下标]
语法2:
列表.pop(下标)
my_list = [1,2,3]
# 方式1
de1 my_list[o]
print(my_list) # 结果:[2,3]
# 方式2
my_list.pop(0)
print(my_list) # 结果:[2,3]
删除某元素在列表中的第一个匹配项
语法:列表.remove(元素)
my_list = [1,2,3,2,3]
my_list.remove(2)
print(my_list) # 结果:[1,3,2,3]
语法:列表.clear()
my_list = [1,2,3]
my_list.clear()
print(my_list) # 结果:[]
语法:列表.count(元素)
my_list = [1,1,1,2,3]
print(my_list.count(1)) # 结果:3
统计列表内,有多少元素
语法: len(列表)
可以得到一个int数字,表示列表内的元素数量
my_list = [1,2,3,4,5]
print(1en(my_list)) # 结果5
可以容纳多个元素(上限为2**63-1.9223372036854775807个)可以容纳不同类型的元素混装)
数据是有序存储的(有下标序号)允许重复数据存在
可以修改(增加或删除元素等)
使用方式 | 作用 |
---|---|
列表.ap pend(元素) | 向列表中追加一个元素 |
列表.extend(容器) | 将数据容器的内容依次取出,追加到列表尾部 |
列表.insert(下标,元素) | 在指定下标处,插入指定的元素 |
del列表[下标] | 删除指定位置的下标 |
列表,pop(下标) | 删除指定位置的下标 |
列表.remove(元素) | 从前向后,删除此元素第一个匹配任务 |
列表.clear(元素) | 清空列表 |
列表.count(元素) | 统计此元素在列表中出现的次数 |
列表.index(元素) | 查找指定元素在列表的下标,找不到就报错ValueErr |
len(列表) | 统计容器内有多少元素 |
将容器内的元素依次取出进行处理的行为,称之为:遍历、迭代
如何遍历列表的元素呢?
·可以使用前面学过的while循环
如何在循环中取出列表的元素呢?
·使用列表[下标]的方式取出循环条件如何控制?
·定义一个变量表示下标,从0开始
·循环条件为下标值<列表的元素数量
index = 0
while index < len(列表)
元素 = 列表[index]
对元素进行处理
index += 1
对比while,for循环更加适合对列表等数据容器进行遍历
my_1ist = [1, 2, 3, 4, 5]
for i in my_1ist:
print(i)
每—次循环将列表中的元素取出,赋值到变量i,供操作
while循环和for循环,都是循环语句,但细节不同:
· 在循环控制上:
. while循环可以自定循环条件,并自行控制
. for循环不可以自定循环条件,只可以一个个从容器内取出数据
· 在无限循环上:
. while循环可以通过条件控制做到无限循环
. for循环理论上不可以,因为被遍历的容器容量不是无限的
·在使用场景上:
· while循环适用于任何想要循环的场景
. for循环适用于,遍历数据容器的场景或简单的固定次数循环场景
如果想要传递的信息,不被篡改,列表就不合适了
元组同列表一样,都是可以封装多个、不同类型的元素在内
但最大的不同点在于:
元组一旦定义完成,就不可修改
所以,当我们需要在程序内封装数据,又不希望封装的数据被篡改,那么元组就非常合适了
定义元组使用小括号,且使用逗号隔开各个数据,数据可以是不同的数据类型
# 定义元组字面量
(元素, 元素, ……,元素)
# 定义元组变量
变量名称 = (元素, 元素, ……,元素)
# 定义空元组
变量名称 = () # 方法1
变量名称 = tuple() # 方法2
如果这个元组内只有一个数据,这个数据后面必须添加逗号,否则不是元组类型
元组也支持嵌套
# 定义一个嵌套元组
t1 = ((1,2,3),(4,5,6))
print(t1[0][0]) # 结果:1
方法 | 作用 |
---|---|
index() | 查找某个数据,如果数据存在返回对应的下标,否则报错 |
count() | 统计某个诗句在当前元组中出现的次数 |
len(元组) | 统计元组内的元素个数 |
由于元组的不可修改特性,所以其操作方式非常少
#根据下标〔索引)取出数据
t1 = (1,2,‘he11o')
print(t1[2]) # 结果: 'he11o’
#根据index(),查找特定元素的第一个匹配项
t1 = (1,2, ‘he11o',3,4,‘he11o')
print(t1.index( ' he11o')) # 结果:2
#统计某个数据在元组内出现的次数
t1 = (1,2,‘he11o’,3,4,‘he1lo’)
print(t1.count( 'he11o')) # 结果:2
#统计元组内的元素个数
t1 = (1,2,3)
print(len(t1)) # 结果3
不可以修改元组的内容,否则会直接报错
可以修改元组内的list的内容(修改元素、增加、删除、反转等)
不可以替换list为其它list或其它类型
同列表一样,元组也可以被遍历
可以使用while和for循环遍历它
while循环
my_tuple = (1, 2, 3, 4, 5)
index = 0
while index < len(my_tuple):
print(my_tuple[index])
index += 1
for循环
my_tuple = (1, 2, 3, 4, 5)
for i in my_tuple:
print(i)
输出:
1
2
3
4
5
可以容纳多个数据
可以容纳不同类型的数据(混装)
数据是有序存储的(下标索引)
允许重复数据存在
不可以修改(增加或删除元素等)
支持for循环
多数特性和list一致,不同点在于不可修改的特性。
尽管字符串看起来并不像:列表、元组那样,一看就是存放了许多数据的容器。但不可否认的是,字符串同样也是数据容器的一员。
字符串是字符的容器,一个字符串可以存放任意数量的字符。
和其他容器一样,字符串也可以通过下标进行访问
· 从前向后,从下标0开始
· 从后向前,下标从-1开始
# 通过下标获取特定位置字符
name = "ivjvytra"
print(name[0]) # 结果:i
print(name[-1]) # 结果:a
同元组一样,字符串是一个:无法修改的数据容器
所以:
修改、移除、指定下标的字符、追加字符等,均无法完成
如果必须要做,只能得到一个新的字符串,旧的字符串是无法修改
查找特定字符串的下标索引值
语法:字符串.index(字符串)
my_str = “itabcd and itzxcvb”
print(my_str.index(“and”)) # 结果7
语法:字符串.replace(字符串1,字符串2)
功能:将字符串内的全部:字符串1,替换为字符串2
注意:不是修改字符串本身,而是得到了一个新字符串哦
name = "itasdfg itzxcvb"
new_name = name. replace("it","hello")
print(new_name) # 结果:helloasdfg hellozxcvb
print(name) # 结果:ithello itcast
可以看到,字符串本身并没有变化
而是得到了一个新字符串对象
语法:字符串.split(分隔符字符串)
功能:按照指定的分隔符字符串,将字符串划分为多个字符串,并存入列表对象中
注意:字符串本身不变,而是得到了一个列表对象
name = "abc def ghi jkl mno"
name_list = name.split(" ")
print(name_list) # ['abc', 'def', 'ghi', 'jkl', 'mno']
print(name) # abc def ghi jkl mno
可以看到,字符串按照给定的<空格>进行了分割,变成多个子字符串,并存入一个列表对象中
去前后空格
语法:字符串.strip()
my_str = " asdfghjkl "
print(my_str.strip()) # 结果:"asdfghjkl"
语法:字符串.strip(字符串)
my_str = "123asdfghjkl"
print(my_str.strip(123)) # 结果:"asdfghjkl"
注意,这里传入的是数字“1”,“2”,“3”,所有的123都会被删除,是按照单个字符移除的
语法:字符串.count(字符串)
my_str = "aabbcc"
print(my_str.count("a")) # 结果:2
语法:len(字符串)
my_str = " lq3uhr9'p,'m ,,'p. [你好ni"
print(len(my_str)) # 结果:25
可见,数字、字母、符号(包括空格)、中文等,均算作一个字符
while、for
用法和;列表、元组一样
只可以存储字符串
长度任意(取决于内存大小)
支持下标索引
允许重复字符串存在
不可以修改(增加或删除元素等)
支持for循环
基本和列表、元组相同
不同与列表和元组的在于:字符串容器可以容纳的类型是单一的,只能是字符串类型。
不同于列表,相同于元组的在于:字符串不可修改
操作 | 说明 |
---|---|
字符串[下标] | 根据下标索引取出特定位置字符 |
字符串.index(字符串) | 查找给定字符的第一个匹配项的下标 |
字符串.replace(字符串1,字符串2) | 将字符串的全部字符串1替换为字符串2,不会修改原定字符串,而是得到一个新的 |
字符串.split(字符串) | 按照给定字符串,对字符串进行分割,不会修改原定字符串,而是得到一个新的列表 |
字符串.strip()/字符串.strip(字符串) | 移除首尾的空格或指定字符串 |
字符串.count(字符串) | 统计字符串内某个字符出现的次数 |
len(字符串) | 统计字符串的字符个数 |
序列是指:内容连续、有序 ,可使用下标索引的一类数据容器
列表、元组、字符串都可视为序列
即:列表、元组、字符串,均支持进行切片操作
切片:从一个序列中,取出一个子序列
语法:序列[起始下标:结束下标:步长]
表示从序列中,从指定位置开始,依次取出元素,到指定位置结束,得到一个新序列:
起始下标表示从何处开始,可以留空,留空视作从头开始
结束下标(不含)表示何处结束,可以留空,留空视作截取到结尾
步长表示,依次取元素的间隔
步长1表示,—个个取元素
步长2表示,每次跳过1个元素取
步长N表示,每次跳过N-1个元素取
步长为负数表示,反向取(注意,起始下标和结束下标也要反向标记)
注意,此操作不会影响序列本身,而是会得到一个新的序列(列表、元组、字符串)
my_list =[1,2,3,4.5]
new_list = my_list[1:4] # 下标1开始,下标4结束,不包含4
print(new_list) # 结果:[2,3,4]
my_tuple = (1,2,3,4,5)
new_tuple = my_tuple[:] # 从头开始,到最后结束,步长1
print(new_tuple) # 结果:(1,2,3,4,5)
my_list = [1,2,3,4.5]
new_list = my_list[2] # 从头开始,到最后结束,步长2
print(new_list) # 结果;[1,3,5]
my_str = "12345"
new_str = my_str[:4:2] # 从头开始,到下标4(不含)结束,步长2
print(new_str) # 结果:"13"
my_str = "12345"
new_str = my_list[::1] # 从结尾开始到开头结束,步长-1(倒序)
print(new_str) # 结果:"54321"
my_1ist = [1,2,3,4,5]
new_list = my_1ist[3:1:-1] # 从下标3开始,到下标1结束,不包含1,步长-1(倒序)
print(new_list) #结果:[4,3]
my_tuple = (1,2,3,4,5)
new_tuple = my_tuple[:1:-2] # 从最后开始,到下标1结束,不包含1,步长-2(倒序)
print(new_tuple) # 结果:(5,3)
可以看到,这个操作对列表、元组、字符串是通用的
同时非常灵活,根据需求,起始位置,结束位置,步长(正反序)都是可以自行控制的
列表、元组、字符串已经基本满足多数场景使用了
为什么还要用集合类型呢?
通过特性来分析
列表可修改、支持重复元素且有序
元组、字符串不可修改、支持重复元素且有序
局限:它们都支持重复元素。
如果场景需要对内容做去重处理,列表、元组、字符串就不方便了。
而集合,最主要的特点就是:不支持元素的重复(自带去重功能)、并且内容无序
语法
#定义集合字面量
{元素,元素,…,元素}
#定义集合变量
变量名称={元素,元素,…,元素}
#定义空集合
变量名称= set()
和列表、元组、字符串等定义基本相同:
列表使用:[]
元组使用:()
字符串使用:“”
集合使用:{}
names = {"abc","abc","kb","kaygco","ayyc","abc"}
print(names) #
结果1:{'kaygco', 'abc', 'ayyc', 'kb'}
结果2:{'ayyc', 'kb', 'abc', 'kaygco'}
结果3:{'abc', 'ayyc', 'kaygco', 'kb'}
可见,作用是去除重复,且无序排放
因为要对元素做去重处理所以无法保证顺序和创建的时候一致
因为集合是无序的,所以不支持下标索引访问
但是集合和列表一样,是允许修改的,下面是集合的修改方法
语法:集合.add(元素)。将指定元素,添加到集合内
结果:集合本身被修改,添加了新元素
my_set = {"hello","world"}
my_set.add("abcde")
print(my_set)
# 结果:{'world', 'abcde', 'hello'}
语法:集合.remove(元素),将指定元素,从集合内移除
结果:集合本身被修改,移除了元素
my_set = {"hello","world","abcde"}
my_set.remove("abcde")
print(my_set)
# 结果:{'hello', 'world'}
语法:集合.pop()
功能,从集合中随机取出一个元素
结果:会得到一个元素的结果。同时集合本身被修改,元素被移除
my_set = i "He11o","wor1d","abcdefg"}
element =my_set.pop()
print(my_set) #结果{'wor1d','itheima'}
print(element) #结果'He11o'
语法:集合.clear()
功能,清空集合
结果:集合本身被清空
my_set = {"He11o", "wor1d", "itheima"}
my_set.clear()
print(my_set) #结果:set() # 空集合
语法:集合1.difference(集合2)
功能:取出集合1和集合2的差集(集合1有而集合2没有的)
结果:得到一个新集合,集合1和集合2不变
set1 = {1,2,33set2 = {1,5,6}
set3 = set1.difference(set2)
print(set3) #结果:{2,3} 得到的新集合
print(set1) #结果:{1,2,3} 不变
print(set2) #结果:{1,5,6} 不变
语法:集合1.difference_update(集合2)
功能:对比集合1和集合2,在集合1内,删除和集合2相同的元素
结果:集合1被修改,集合2不变
set1 = 1,2,33set2 = {,5,6}
set1.difference_update(set2)
print(set1) #结果:{2,3}
print(set2) #结果:{1,5,6}
语法:集合1.union(集合2)
功能:将集合1和集合2组合成新集合
结果:得到新集合,集合1和集合2不变
set1 = {1,2,3}
set2 = {1,5,6}
set3 = set1.union(set2)
print(set3) #结果:{1,2,3,5,6} 新集合
print(set1) #结果:{,2,33,set1不变
print(set2) #结果:{1,5,6}, set2不变
语法: len(集合)
功能:统计集合内有多少元素
结果:得到一个整数结果
set1 = {1,2,3}
print(len(set1)) #结果3
set1 = {1,2,3}
for i in set1:
print(i)
结果:
1
2
3
注意:集合不支持下标索引,所以也就不支持使用while循环。
操作 | 说明 |
---|---|
集合.add(元素) | 集合内添加一个元素 |
集合.remove(元素) | 移除集合内指定的元素 |
集合.pop() | 从集合中随机取出一个元素 |
集合.clear() | 将集合清空 |
集合1.difference(集合2) | 得到一个新的集合,内含两个集合的差集;原有的两个集合内容不变 |
集合1.defference_update(集合2) | 在集合1中删除集合2中存在的全部元素,集合1被修改,集合2不变 |
集合1.union(集合2) | 得到一个新集合,内含两个集合的全部内容,原有的两个集合不变 |
len(集合) | 得到一个整数,记录了元素数量 |
在现实生活中呢,字典记录着一堆:
【字】:【含义】
【字】:【含义】
……
【字】:【含义】
就像C++的map键值对
但写起来呢又像是Json格式
在python中的字典写法是这样子的:
Key:Value
Key:Value
……
Key:Value
可以按【Key】找出对应的【Value】
以成绩单举个栗子
张三 75
李四 85
王五 90
使用字典:
{
“张三”:75,
“李四”:85,
“王五”:90
}
可以通过Key(学生姓名),取到对应的Value(考试成绩)
字典的定义,同样使用0,不过存储的元素是一个个的:键值对,如下语法:
#定义字典字面量
{key: value, key: value,...... , key: value}
# 定义字典变量
my_dict = {key: value,key: value,...... , key: value}
#定义空字典
my_dict = {0} #空字典定义方式1
my_dict = dict() #空字典定义方式2
使用存储原始,每一个元素是一个键值对
每一个键值对包含Key和Value(用冒号分隔)
键值对之间使用逗号分隔
Key和Value可以是任意类型的数据(key不可为字典)
Key不可重复,重复会对原有数据覆盖
字典同集合一样,不可以使用下标索引
但是字典可以通过Key值来取得对应的Value
stu_score = {“张三”:75, “李四”:85, “王五”:90}
print(stu_score[“张三”]) # 结果:75
print(stu_score[“李四”]) # 结果:85
print(stu_score[“王五”]) # 结果:90
字典的Key和Value可以是任意数据类型(Key不可为字典)
那么,就表明,字典是可以嵌套的
直接上代码
stu_score = {"张三":{"科一":90,"科二":80,"科三":90,"科四":88},"李四":{"科一":10,"科二":0,"科三":0,"科四":0},"王五":{"科一":89,"科二":75,"科三":85,"科四":88}}
可优化一下格式提升可读性
stu_score = {
"张三":{"科一":90,"科二":80,"科三":90,"科四":88},
"李四":{"科一":10,"科二":0,"科三":0,"科四":0},
"王五":{"科一":89,"科二":75,"科三":85,"科四":88}
}
发现这些编程语言写法都好类似,但又有哪里有些不同
嵌套字典的内容获取
继续上面代码,这里就直接打印结果
print(stu_score["张三"]) # 结果:{'科一':90,'科二':80,'科三':90,'科四':88}
print(stu_score["李四"]["科一"]) # 结果:10
print(stu_score["王五"]["科二"]) # 结果:75
语法:字典[Key] = Value,结果:字典被修改,新增了元素
stu_score = {
"张三":75,
"李六":85,
"王五":90
}
stu_score['赵四'] = 100
print(stu_score)
结果:{‘张三’: 75, ‘李六’: 85, ‘王五’: 90, ‘赵四’: 100}
语法:字典[Key] = Value,结果:字典被修改,兀系被更新
注意:字典Key不可以重复,所以对已存在的Key执行上述操作,就是更新Value值
stu_score = {
"张三":75,
"李四":85,
"王五":90
}
stu_score['李四'] = 100
print(stu_score)
结果:{‘张三’: 75, ‘李四’: 100, ‘王五’: 90}
语法:字典.pop(Key)
结果:获得指定Key的Value,同时字典被修改,指定Key的数据被删除
stu_score = {
"张三":75,
"李四":85,
"王五":90
}
stu_score.pop("王五")
print(stu_score)
结果:{‘张三’: 75, ‘李四’: 85}
语法:字典.clear()
结果:字典被修改,元素被清空
stu_score = {
"张三":75,
"李四":85,
"王五":90
}
stu_score.clear()
print(stu_score)
结果:{}
语法:字典.keys0
结果:得到字典中的全部Key
stu_score = {
"张三":75,
"李四":85,
"王五":90
}
keys = stu_score.keys()
print(keys)
结果:dict_keys([‘张三’, ‘李四’, ‘王五’])
语法:for key in 字典.keys()
stu_score = {
"张三":75,
"李四":85,
"王五":90
}
keys = stu_score.keys()
for key in keys:
print(f"考生:{key},分数:{stu_score[key]}")
结果:
考生:张三,分数:75
考生:李四,分数:85
考生:王五,分数:90
*注意:字典不支持下标索引,所以同样不可以用while循环遍历 *
计算字典内所有元素(键值对)数量
语法:len()
结果:得到一个整数,表示字典内元素(键值对)的数量
stu_score = {
"张三":75,
"李四":85,
"王五":90
}
print(len(stu_score))
结果:3
可以容纳多个数据
可以容纳不同类型的数据
每一份数据是KeyValue键值对
可以通过Key获取到Value,Key不可重复(重复会覆盖)
不支持下标索引
可以修改(增加或删除更新元素等)
支持for循环,不支持while循环
操作 | 说明 |
---|---|
字典[Key] | 获取指定Key对应的Value值 |
字典[Key] = Value | 添加或更新键值对 |
字典.pop(Key) | 取出Key对应的Value并在字典内删除此Key的键值对 |
字典.clear() | 清空词典 |
字典.keys() | 获取字典的全部Key,可用于for循环遍历字典 |
len(字典) | 计算字典内的元素数量 |
数据容器可以从以下视角进行简单的分类:
· 是否支持下标索引
· 支持:列表、元组、字符串–序列类型
· 不支持:集合、字典–非序列类型
· 是否支持重复元素:
· 支持:列表、元组、字符串–序列类型
· 不支持:集合、字典―非序列类型
·是否可以修改
· 支持:列表、集合、字典
· 不支持:元组、字符串
数据容器尽管各自有各自的特点,但是它们也有通用的一些操作
在遍历上:
· 5类数据容器都支持for循环遍历
· 列表、元组、字符串支持while循环,集合、字典不支持(无法下标索引)
尽管遍历的形式各有不同,但是,它们都支持遍历操作。
除了遍历这个共性外,数据容器可以通用非常多的功能方法
len(容器) # 统计容器的元素个数
max(容器) # 统计容器的最大元素
min(容器) # 统计容器的最小元素
list(容器) # 将给定容器转换为列表
str(容器) # 将给定容器转换为字符串
tuple(容器)# 将给定容器转换为元组
set(容器) # 将给定容器转换为集合
sorted(容器,[reverse=True])
要注意,排序后都会得到列表(list)对象
在程序中,字符串所用的所有字符如:
· 大小写英文单词
· 数字
· 特殊符号(!、l、]、@、#、空格等)
都有其对应的ASCII码表值
每一个字符都能对应上一个:数字的码值
字符串进行比较就是基于数字的码值大小进行比较的
字符串是按位比较,也就是一位位进行对比,只要有一位大,那么整体就大
一个函数有多个返回值
def test_return():
return 1,2
x, y = test_return()
print(x) # 结果:1
print(y) # 结果:2
按照返回值的顺序,写对应顺序的多个变量接收即可变量之间用逗号隔开
支持不同类型的数据return
使用方式上不同,函数有4种常见的参数使用方式
位置参数
关键字参数
缺省参数
不定长参数
位置参数使用函数时根据函数定义的参数位置来传递参数
def user_info(name, age, gender):
print(f'您的名字是{name},年龄是{age},性别是{gender}')
user_info('TOM', 20, '男')
注意,传递的参数和定义的参数的顺序及个数必须一致
函数调用时通过“键=值”形式传递参数
可以让函数更加清晰、容易使用,同时也清楚了参数的顺序需求
def user_info(name, age, gender):
print(f'您的名字是{name},年龄是{age},性别是{gender}')
# 关键字传参
user_info(name = "TOM", age = 20, gender = "男")
# 可以不按顺序传参
user_info(gender = "男", name = "TOM", age = 20)
# 可以和位置参数混用,位置参数必须在前,且匹配参数顺序
user_info("TOM", age = 20, gender = "男")
注意,函数调用时,如果有位置参数时,位置参数必须在关键字参数前面,但关键字参数之间不存在先后顺序
缺省参数也叫默认参数,用于定义函数,为参数提供默认值,调用函数时可不传该默认参数的值(注意:所有位置参数必须出现在默认参数前,包括函数定义和调用)﹒
作用:当调用函数时没有传递参数,就会使用默认是用缺省参数对应的值
def user_info(name, age, gender= '男'):
print(f'您的名字是{name},年龄是{age},性别是{gender}')
user_info('TOM', 20)
user_info('Rose', 20, '女')
注意,函数调用时,如果为缺省参数传值则 修改默认参数值,否则使用这个默认值
不定长参数也叫可变参数.用于不确定调用的时候会传递多少个参数(不传参也可以)的场景.作用:当调用函数时不确定参数个数时,可以使用不定长参数
不定长参数的类型:
1.位置传递 2.关键字传递
位置传递
def user_info(*args):
print(args)
# (''TOM)
user_info('TOM')
# ('TOM', 18)
user_info('TOM', 18)
注意,传进的所有参数都会被args变量收集,它会根据传进参数的位置合并为一个元组(tuple), args是元组类型,这就是位置传递
def user_info(**beijing)
print(beijing)
# {'name': 'TOM', 'age': 18, 'id': 12345}
user_info(name='TOM', age=18, id=12345)
注意,参数是“键=值”形式的形式的情况下,所有的“键=值”都会被kwargs接受,同时会根据“键=值”组成字典
除了 数字、字符串、字典、列表、元组等数据作为参数外,函数本身也可作为参数传入的另一个函数内
def test_func(compute):
result = compute(1,2)
print(result)
def compute(x,y):
return x + y
test_func(compute) # 结果:3
def test_func(compute):
result = compute(1,2)
print(result)
def compute(x,y):
return x * y
test_func(compute) # 结果:2
def test_func(compute):
result = compute(1,2)
print(result)
def compute(x,y):
return x - y
test_func(compute) # 结果:-1
函数compute,作为参数,传入了test_func函数中使用
test func需要一个函数作为参数传入,这个函数需要接收两个数字进行计算,计算逻辑由这个被传入函数决定
compute函数接收两个数字对其进行计算,compute函数作为参数,传递给了test_func函数使用
最终,在test_func函数内部,由传入的compute函数,完成了对数字的计算操作
所以,这是一种,计算逻辑的传递,而非数据的传递。
就像上述代码那样,不仅仅是相加,相见、相除、等任何逻辑都可以自行定义并作为函数传入。
def关键字,可以定义带有名称的函数
lambda关键字,可以定义匿名函数(无名称)
有名称的函数,可以基于名称重复使用。
无名称的匿名函数,只可临时使用一次。
lambda传入参数:函数体(一行代码)
lambda是关键字,表示定义匿名函数
传入参数表示匿名函数的形式参数,如:x, y表示接收2个形式参数。
函数体,就是函数的执行逻辑,要注意:只能写一行,无法写多行代码
通过def关键字,定义一个函数,并传入
def test_func(compute):
result = compute(1, 2)
print(result)
def compute(x, y):
return x + y
test_func(compute) # 结果:3
通过lambda关键字,传入一个一次性使用的lambda匿名函数
def test_func(compute):
result = compute(1, 2)
print(result)
def compute(x, y):
return x + y
test_func(compute) # 结果:3
使用def和使用lambda,定义的函数功能完全一致,只是lambda关键字定义的函数是匿名的,无法二次使用
计算机只能识别0和1,那么文本文件是怎么被计算机识别,并存储在硬盘中呢?
那就是使用编码技术(密码本)将内容翻译成0和1存入
编码技术即:翻译的规则,记绿了如何将内容翻译成二进制,以及如何将二进制翻译回可识别内容。
这里使用的网站是:点这里跳转
网上有很多,随便打开个浏览器搜汉字转二进制也可以找到
计算机中有多种编码格式可用,比如:
UTF-8、GBK、Big5等,不同的编码翻译成二进制也是不同的
使用不同的编码编译同一段二进制时可能会出现不同结局
你给喜欢的女孩发送文件,使用编码A进行编码(内容转二进制)。
女孩使用编码B打开文件进行解码(二进制反转回内容)
自或多福吧。
可以用记事本打开文件,下面即可看到对应的格式
UTF-8是目前通用的格式,除非有特殊需求,否则一律使用UTF-8进行编码即可
内存存放的数据在计算机关机后就会消失。要长久保存数据,就要使用硬盘、光盘、U等设备。为了便于数据的管理和检索,引入了"文件”的概念。
一篇文章、一段视频、一个可执行程序, 都可以被保存为一个文件,并赋予一个文件名。
操作系统以文件为单位管理磁盘中的数据。一般来说,文件可分为文本文件、视频文件、颜文件、图像文件、可执行文件等多种类别。
在日常生活中,文件操作主要包括打开、关闭、读写等操作
向我们平时的操作:打开文件->读写文件->关闭文件
这里也可以打开后不进行读写直接关闭
在python,使用open函数,可以打开一个已经存在的文件或者创建一个新文件
写法:open(name,mode,encoding)
name :是要打开的目标文件名的字符串(可以包含文件所在的具体路径)。
mode: 设置打开文件的模式(访问模式): 只读、写入、追加等
encoding:编码格式 (推荐使用UTF-8)
f = open('python.txt','r',encoding = 'UTF-8')
注意,此时的’f’是’open’函数的文件对象,对象是python中一种特殊的数据类型,拥有属性和方法,可以使用对象属性或对象方法对其进行访问。
r:以只读模式打开文件。文件的指针将放在文件的开头,这是默认模式
w:打开一个文件只用于写入。如果该文件已存在则打开文件,并从头开始编辑,原文内容会被删除。如果该文件不存在则创建新文件
a:打开一个文件用于追加。如果该文件已存在则在末尾追加写入内容,不存在则创建新文件进行写入
文件对象.read(num)
num表示要从文件中读取数据的长度(单位:字节),如果没有传入num,那么就表示读取文件中所有数据
readlines可以按照行的方式把整个文件的内容进行一次性读取,并返回的是一个列表,其中每一行的数据为一个元素
f = open('python.txt')
content = f.readlines()
# ['hello world\n','abcdefg\n','aaa\n','bbb\n','ccc']
print(content)
# 关闭文件
f.close()
readline()方法:一次读取一行
f = open('python.txt')
content = f.readline()
print(f'第一行:{content}')
content = f.readline()
print(f'第二行:{content}')
# 关闭文件
f.close()
for循环读取文件
for line in open("python.txt","r")
print(line)
# 每一个line临时变量,就记录了文件的一行数据
close()关闭文件对象
f = open("python.txt","r")
f.close()
# 最后通过close,关闭文件对象,也就是关闭对这个文件的占用
# 如果不调用close,同时程序没有停止运行,那么这个文件将一直被python程序占用
with open 语法
with open("python.txt", "r") as f:
f.readlines()
# 通过在with open的语句块中对文件进行操作
# 可以在操作完成后自动关闭close文件,避免遗忘掉close方法
操作 | 功能 |
---|---|
文件对象 | 打开文件获得文件对象 |
文件对象.read(num) | 读取指定长度字节不指定num读取文件全部 |
文件对象.readline() | 读取一行 |
文件对象readlines() | 读取全部行,得到列表 |
for line in 文件对象 | for循环文件行,一次循环得到一行数据 |
文件对象.close() | 关闭文件对象 |
with open() as f | 通过with open语法打开文件,可以自动关闭 |
# 1. 打开文件
f = open('python.txt', 'w')
# 2.文件写入
f.write('hello world')
# 3. 内容刷新
f.flush()
注意:
直接调用write,内容并未真正写入文件,而是会积攒在程序的内存中,称之为缓冲区
当调用flush的时候,内容会真正写入文件
这样做是避免频繁的操作硬盘,导致效率下降(攒一堆,一次性写磁盘)
文件如果不存在,使用”w”模式,会创建新文件
文件如果存在,使用”w”模式,会将原有内容清空
# 1. 打开文件,通过a模式打开即可
f = open('python.txt', 'a')
# 2.文件写入
f.write('hello world')
# 3. 内容刷新
f.flush()
注意:
a模式,文件不存在会创建文件
a模式,文件存在会在最后,追加写入文件
当检测到一个错误时,Python解释器就无法继续执行了,反而出现了一些错误的提示,这就是所谓的“异常”, 也就是我们常说的BUG
bug单词的诞生
早期计算机采用大量继电器工作,马克二型计算机就是这样的。
1945年9月9日,下午三点,马克二型计算机无法正常工作了,技术人员试了很多办法,最后定位到第70号继电器出错。负责人哈珀观察这个出错的继电器,发现一只飞蛾躺在中间,已经被继电器打死。她小心地用摄子将蛾子夹出来,用透明胶布帖到“事件记录本”中,并注明“第一个发现虫子的实例。”自此之后,引发软件失效的缺陷,便被称为Bug。
例如:以r
方式打开一个不存在的文件。
f = open('linux.txt', 'r')
世界上没有完美的程序,任何程序在运行的过程中,都有可能出现:异常,也就是出现bug导致程序无法完美运行下去。
我们要做的,不是力求程序完美运行。
而是在力所能及的范围内,对可能出现的bug,进行提前准备、提前处理。
这种行为我们称之为:异常处理(捕获异常)
当我们的程序遇到了BUG, 那么接下来有两种情况:
① 整个程序因为一个BUG停止运行
② 对BUG进行提醒, 整个程序继续运行
显然在之前的学习中, 我们所有的程序遇到BUG就会出现①的这种情况, 也就是整个程序直接奔溃.
但是在真实工作中, 我们肯定不能因为一个小的BUG就让整个程序全部奔溃, 也就是我们希望的是达到② 的这种情况
那这里我们就需要使用到捕获异常
捕获异常的作用在于:提前假设某处会出现异常,做好提前准备,当真的出现异常的时候,可以有后续手段。
基本语法:
try:
可能发生错误的代码
except:
如果出现异常执行的代码
尝试以r
模式打开文件,如果文件不存在,则以w
方式打开
try:
f = open('linux.txt', 'r')
except:
f = open('linux.txt', 'w')
try:
print(name)
except NameError as e:
print('name变量名称未定义错误')
注意:
如果尝试执行的代码的异常类型和要捕获的异常类型不一致,则无法捕获异常。
一般try下方只放一行尝试执行的代码
当捕获多个异常时,可以把要捕获的异常类型的名字,放到except 后,并使用元组的方式进行书写。
try:
print(1/0)
except (NameError, ZeroDivisionError):
print('ZeroDivision错误...')
try:
print(num)
except (NameError, ZeroDivisionError) as e:
print(e)
try:
print(name)
except Exception as e:
print(e)
else表示的是如果没有异常要执行的代码
try:
print(1)
except Exception as e:
print(e)
else:
print('我是else,是没有异常的时候执行的代码')
finally表示的是无论是否异常都要执行的代码,例如关闭文件
try:
f = open('test.txt', 'r')
except Exception as e:
f = open('test.txt', 'w')
else:
print('没有异常,真开心')
finally:
f.close()
异常是具有传递性的,当函数func01中发生异常, 并且没有捕获处理这个异常的时候, 异常会传递到函数func02, 当func02也没有捕获处理这个异常的时候main函数会捕获这个异常, 这就是异常的传递性.
提示: 当所有函数都没有捕获异常的时候, 程序就会报错
上图中main函数:利用异常具有传递性的特点, 当我们想要保证程序不会因为异常崩溃的时候, 就可以在main函数中设置异常捕获, 由于无论在整个程序哪里发生异常, 最终都会传递到main函数中, 这样就可以确保所有的异常都会被捕获
Python 模块(Module),是一个 Python 文件,以 .py 结尾. 模块能定义函数,类和变量,模块里也能包含可执行的代码.
模块的作用: python中有很多各种不同的模块, 每一个模块都可以帮助我们快速的实现一些功能, 比如实现和时间相关的功能就可以使用time模块
我们可以认为一个模块就是一个工具包, 每一个工具包中都有各种不同的工具供我们使用进而实现各种不同的功能.
大白话:模块就是一个Python文件,里面有类、函数、变量等,我们可以拿过来用(导入模块去使用)
模块在使用前需要先导入 导入的语法如下:
[from 模块名] import [模块 | 类 | 变量 | 函数 | *] [as 别名]
import 模块名
from 模块名 import 类、变量、方法等
from 模块名 import *
import 模块名 as 别名
from 模块名 import 功能名 as 别名
import模块名
import 模块名
import 模块名1,模块名2
模块名.功能名()
# 导入时间模块
import time
print("开始")
# 让程序睡眠1秒(阻塞)
time.sleep(1)
print("结束")
from 模块名 import 功能名
from 模块名 import 功能名
功能名()
# 导入时间模块中的sleep方法
from time import sleep
print("开始")
# 让程序睡眠1秒(阻塞)
sleep(1)
print("结束")
导入所有方法时将sleep位置改为 *
from 模块名 import *
功能名()
as定义别名
# 模块定义别名
import 模块名 as 别名
# 功能定义别名
from 模块名 import 功能 as 别名
# 模块别名
import time as tt
tt.sleep(2)
print('hello')
# 功能别名
from time import sleep as sl
sl(2)
print('hello')
Python中已经帮我们实现了很多的模块. 不过有时候我们需要一些个性化的模块, 这里就可以通过自定义模块实现, 也就是自己制作一个模块
新建一个Python文件,命名为my_module1.py,并定义test函数
注意:
每个Python文件都可以作为一个模块,模块的名字就是文件的名字. 也就是说自定义模块名必须要符合标识符命名规则
在实际开发中,当一个开发人员编写完一个模块后,为了让模块能够在项目中达到想要的效果,
这个开发人员会自行在py文件中添加一些测试信息,例如,在my_module1.py文件中添加测试代码test(1,1)
def test(a, b):
print(a + b)
test(1, 1)
问题:
此时,无论是当前文件,还是其他已经导入了该模块的文件,在运行的时候都会自动执行test
函数的调用
解决方案:
def test(a, b):
print(a + b)
# 只在当前文件中调用该函数,其他导入的文件内不符合该条件,则不执行test函数调用
if __name__ == '__main__':
test (1, 1)
注意事项
当导入多个模块的时候,且模块内有同名功能. 当调用这个同名功能的时候,调用到的是后面导入的模块的功能
__all__
如果一个模块文件中有__all__
变量,当使用from xxx import *
导入时,只能导入这个列表中的元素
从物理上看,包就是一个文件夹,在该文件夹下包含了一个 init.py 文件,该文件夹可用于包含多个模块文件
从逻辑上看,包的本质依然是模块
当我们的模块文件越来越多时,包可以帮助我们管理这些模块, 包的作用就是包含多个模块,但包的本质依然是模块
步骤如下:
新建包my_package
新建包内模块:my_module1
和 my_module2
模块内代码如下
[New] → [Python Package] → 输入包名 → [OK] → 新建功能模块(有联系的模块)
注意:新建包后,包内部会自动创建__init__.py
文件,这个文件控制着包的导入行为
方式一:
import 包名.模块名
包名.模块名.目标
方式二:
注意:必须在__init__.py
文件中添加__all__ = []
,控制允许导入的模块列表
from 包名 import *
模块名.目标
箭头指向位置my_module1报红证明不可用
注意:
__all__针对的是 ’ from … import * ‘ 这种方式
对 ‘ import xxx ’ 这种方式无效
我们知道,包可以包含一堆的Python模块,而每个模块又内含许多的功能。
所以,我们可以认为:一个包,就是一堆同类型功能的集合体。
在Python程序的生态中,有许多非常多的第三方包(非Python官方),可以极大的帮助我们提高开发效率,如:
科学计算中常用的:numpy包
数据分析中常用的:pandas包
大数据计算中常用的:pyspark、apache-flink包
图形可视化常用的:matplotlib、pyecharts
人工智能常用的:tensorflow
……
这些第三方的包,极大的丰富了Python的生态,提高了开发效率。
但是由于是第三方,所以Python没有内置,所以我们需要安装它们才可以导入使用哦。
第三方包的安装非常简单,我们只需要使用Python内置的pip程序即可。
打开我们许久未见的:命令提示符程序,在里面输入:
pip install 包名称
pip install numpy
即可通过网络快速安装第三方包
pytho不会,但命令提示符还是会调出来的
桌面→win+r→cmd→回车
由于pip是连接的国外的网站进行包的下载,所以有的时候会速度很慢。
我们可以通过如下命令,让其连接国内的网站进行包的安装:
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple 包名称
该网站是清华大学提供的一个网站,可供pip程序下载第三方包
命令:
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple numpy
效果一:2020年印美日新冠累计确诊人数
2020年是新冠疫情爆发的一年, 随着疫情的爆发, 国内外确诊人数成了大家关心的热点,
相信大家都有看过类似的疫情报告. 本案例对印度美国日本三个国家确诊人数的进行了
可视化处理, 形成了可视化的疫情确诊人数报告.
效果二:全国疫情地图可视化
效果三:动态GDP增长图
数据来源:<<百度疫情实时大数据报告>>,及公开的全球各国GDP数据
JSON是一种轻量级的数据交互格式。可以按照JSON指定的格式去组织和封装数据
JSON本质上是一个带有特定格式的字符串
主要功能:json就是一种在各个编程语言中流通的数据格式,负责不同编程语言中的数据传递和交互.
类似于:
国际通用语言-英语
中国56个民族不同地区的通用语言-普通话
各种编程语言存储数据的容器不尽相同,在Python中有字典dict这样的数据类型, 而其它语言可能没有对应的字典。
为了让不同的语言都能够相互通用的互相传递数据,JSON就是一种非常良好的中转数据格式。
以Python和C语言互传数据为例
# json数据的格式可以是:
{"name":"admin","age":18}
# 也可以是:
[{"name":"admin","age":18},{"name":"root","age":16},{"name":"张三","age":20}]
Python数据和Json数据的相互转化
# 导入json模块
import json
# 准备符合格式json格式要求的python数据
data = [{"name": "老王", "age": 16}, {"name": "张三", "age": 20}]
# 通过 json.dumps(data) 方法把python数据转化为了 json数据
data = json.dumps(data)
# 通过 json.loads(data) 方法把json数据转化为了 python数据
data = json.loads(data)
如果想要做出数据可视化效果图, 可以借助pyecharts模块来完成
概况?:
Echarts?是个由百度开源的数据可视化,凭借着良好的交互性,精巧的图表设计,得到了众多开发者的认可. 而?Python?是门富有表达力的语言,很适合用于数据处理. 当数据分析遇上数据可视化时pyecharts 诞生了
pip install pyecharts
pyecharts模块中有很多的配置选项, 常用到2个类别的选项:
全局配置选项
系列配置选项
这里全局配置选项可以通过set_global_opts方法来进行配置, 相应的选项和选项的功能如下
line.set_global_opts(
title_opts=TitleOpts("测试", pos_left="center", posbottom="1%"),
legend_opts=LegendOpts(is_show=True),
toolbox_opts=toolboxOpts(is_show=True),
visualmap_opts=visualmapOpts(is_show=True),
toolbox_opts=tooltipOpts(is_show=True),
)
# 导入json模块
import json
# 对数据进行整理, 让数据符合json格式
# 把不符合json数据格式的 "jsonp_1629350871167_29498(" 去掉
data = data.replace("jsonp_1629350871167_29498(", "")
# 把不符合json数据格式的 ");" 去掉
data = data[:-2]
# 数据格式符合json格式后,对数据进行转化
data = json.loads(data)
# 获取日本的疫情数据
data = data["data"][0]['trend']
# x1_data存放日期数据
x1_data = data['updateDate']
# y1_data存放人数数据
y1_data = data['list'][0]["data"]
# 获取2020年的数据
x1_data = data['updateDate'][:314]
# 获取2020年的数据
y1_data = data['list'][0]["data"][:314]
# 导入折线图模块
from pyecharts.charts import Line
# 导入配置选项模块
import pyecharts.options as opts
#创建折线图
l = Line(init_opts=opts.InitOpts(width="1600px",height="800px"))
这里的Line()是构建类对象
l.add_xaxis() # 添加x轴数据
l.add_yaxis() # 添加y轴数据