python基础
数据输入input()和输出print()
无论键盘输入什么类型的数据,input()获取的数据永远是字符串类型
1 输入 input(msg) 参数msg: String 提示信息 返回值: String 输入的信息 2 输出 print(*arg, sep=' ', end='\n') 参数: *args: 不定长参数,要输出的数据,不定长个数据 sep=' ': 输出的各数据中间的分隔符 默认是空格' ' end='\n': 输出的结束符 默认是换行'\n'
num = input("提示信息")
num1 = int(num)#input获取的数据都是字符串类型,按需自行转换为其他类型
print(num1)
"""直接print()相当于java中的println()"""
#不输出换行符(相当于java中的print())
print("...",end='')
print("123")
#...123
#设置数据中间的分割符为/
print("1","2","3",sep='/')#1/2/3
#返回字面量或变量存储的数据的数据类型<class ''>
type()
#数据类型转换(字符串转数字,数字转字符串)
int(x) #将x转换为一个整数
float(x) #将x转换为一个浮点数
str(x) #将对象x转换为字符串
#同type一样,都是带有结果的(返回值),可用print字节输出,也可以用变量存储
#万物皆可转字符串,但字符串转数字,需确保字符串内容都是数字才行
#浮点数转整数会丢失精度
标识符
用户编写代码时,对变量、类方法等编写的名字,叫做标识符
命名规则:
1、内容限定:
标识符命名中,只允许出现:.英文 .中午 .数字 .下划线(_)
注意 :数字不可以开头(不推荐使用中文)
2、大小写敏感(区分大小写)
3、不可使用关键字(与关键字大小写不一致可以使用)
命名规范:(不同于规则的强制性,规范是建议性要求)
.变量名 .类名 .方法名 (不同的表示符有不同的规范)
1、变量名:
1)见名知意
2)下滑线命名法:多个单词组合变量名,要使用下滑线做分隔
3)英文字母全小写:命名变量中的英文字母,应全部小写
运算符
#算数运算符
+ - * /
//(整除) %(取余) **(平方) 2**3=8
#赋值运算符
=
#复合赋值运算符
+= -= *= /= %= **= //=
c**=a 等效于 c=c**a
字符串
字符串的三种定义方式
1、‘单引号定义法’ 2、“双引号定义法” 3、“”“三引号定义法”“”
三引号定义法,和多行注释,同样支持换行操作,不使用变量接受它,就可以作为多行注释使用
引号的嵌套
单引号定义法包含双引号,双引号定义法包含单引号
可以使用:转移字符(\)来将引号解除效用,变成普通字符串
字符串的拼接(+)
(使用“+”,一般用于字面量和变量之间使用拼接)
#字符串字面量之间的拼接(+)
print("奔波霸"+"霸波奔")
#字符串字面量和字符串变量的拼接(+)
name="我重伤倒地"
print(name+",但还活着")
"""注意:无法通过+拼接 字符串 和 非字符串类型"""
字符串格式化(%s %d %f)
(使用%占位,再用变量填补,可用于字符串与非字符串进行拼接)
语法:"%占位符"%变量
#通过占位的形式,完成拼接
name="我重伤倒地"
print("%s,但还活着"%name)
"""
多个变量占位
变量要用括号括起来,以逗号分隔
并按照占位顺序排入
"""
#通过占位的形式,完成数字和字符串的拼接
class_num = 57
avg_salary = 16781
message = "该python课程共有%s期,毕业平均工资:%s" % (class_num,avg_salary)
print(message)
%表示:我要占位
s表示:将变量变成字符串
放入占位的地方
格式符号 | 转化 |
---|---|
%s | 将内容转换成字符串,放入占位位置 |
%d | 将内容转换成整型,放入占位位置 |
%f | 将内容转换成浮点型型,放入占位位置 |
格式化字符串中对数字的精度控制
使用辅助符号“m.n
”来控制数据的宽度和精度
- m,控制宽度,要求是数字(很少使用),设置的宽度小于数字本身,m不生效,大于则用空格补足
- n,控制小数点精度,要求是数字,会进行
小数的四舍五入
实例:
- %5d:表示宽度为5的整数,如数字11=》【空格】【空格】【空格】11
- %1d:宽度为1的整数,(宽度小于数字本身不生效)如数字11=》11
%5.2d:宽度为5小数点精度为2的整数,如数字11=》【空】【空】【空】11- %6.2f:宽度为5小数点精度为2的浮点数,如数字11.345=》【空格】11.35
- %.2f:不限制宽度,小数点精度为2,如11.234=》11.35
字符串格式化方式2(f"快速{格式化}")
语法:f"内容{变量}{变量}"
(f就是format格式化的首字母)
特点:(原本什么样就输出什么样)适合对精度没有要求的时候快速使用
- 不限制数据类型
- 不做精度控制
name="铁驭"
num1=3
print(f"协议{num1},保护{name}")
对表达式进行格式化 (无需使用变量时简化代码)
表达式:一条具有明确执行结果的代码语句
如:1+1、5*2,就是表达式,因为有具体结果
如:name=“张三”、age=11+11,”=“右侧的都是表达式,有具体结果,具体结果赋值给了左侧变量
f"{表达式}"
"%s\%d\%f" % (表达式、表达式、表达式)
print("协议%d,保护%s" % {3,"铁驭"})
print(f"协议{1*3},保护{铁驭}")
print("字符串再Python中的类型是:%s" % type{'字符串'})
"""再无需使用变量进行数据存储的时候,可直接格式化表达式,简化代码"""
比较运算符
> < >= <=
== !=(可用于字符串)
#计算结果为布尔类型
True False
判断语句(if…elif…else…)
if 判断条件:
为True时,执行的代码块
elif 判断条件2:
执行的代码块
else:
都不成立时,执行的代码块
"""不要忘记冒号":" """
"""每个代码块前要有相同的缩进,一般用4个空格/一个tab"""
循环语句(while…/for…)
flag = True#也可以用1和0代替,1为True,0
while 条件flag:
条件为True时,执行的代码块
if 终止条件:
flag = False
while 条件2:
条件2为True时,执行的代码块
#条件为True继续,False停止
#规划好终止条件,防止无线循环
#对待处理数据集中的元素挨个取出,并在每次循环赋值给当前临时变量
for 临时变量 in 待处理数据集(序列):
循环条件满足时执行的代码#(处理当前循环的临时变量或其他代码)
#注意#
"""for循环无法定义循环条件,只能被动取出数据处理"""
循环嵌套
for循环 或 while循环:
循环满足条件应做的事
for循环 或 while循环:
循环满足条件应做的事
#注意缩进
#for循环和while循环可以相互嵌套使用
range语句
带处理数据集,严格来说,称之为:序列类型
序列类型
指,其内容可以一个个依次取出的一种类型,包括:(字符串 列表 元组 等)
#获取从0开始,到num结束的序列(不含num本身)
#例:range(5)取得数据是:[0,1,2,3,4]
range(num)
#获取从num1开始,到num2结束的序列(不含num2本身)
#例:range(5,10)取得数据是:[5,6,7,8,9]
range(num1,num2)
#获取从num1开始,到num2结束的序列(不含num2本身) ,且步长为step(step默认为1)
#例:range(5,10,2)取得数据是:[5,7,9](从5开始,查两个取一个)
range(num1,num2,step)
用for循环遍历输出range序列
for x in range(4,10,2):
print(x)
#4
#6
#8
变量作用域
for循环中的临时变量,其作用域限定为:循环内
这种限定:
- 是规范限定,非强制限定
- 不遵守也正常运行,但不建议这样做
- 如需访问临时变量,可以预先在循环外定义它
i = 0
for i in range(4,10,2):
print(i)
print(i)
循环中断break和continue
continue:中断本次循环,直接进入下一次循环(暂时跳过某次循环,直接进行下一次)
break:直接结束循环
两者都可以用于:for和while循环,效果一致
for i in range(1,10):
语句1
for x in range(1,10)
语句2
break
语句3
语句4
yuer = 10000
for i in range(1,21):
import random
num = random.randint(1, 10)
if num <= 5:
print(f"员工{i},绩效分{num},低于5,不发工资,下一位")
continue
if yuer == 0:
print("工资发完了,结束发工资")
break
else:
yuer -= 1000
print(f"向员工{i}发放工资1000元,账户余额还剩余{yuer}元")
python函数
函数:已组织好的,可重复使用的,针对实现特定功能的代码段。
- 将功能封装在函数内,可随时随地重复使用
- 提高程代码的复用性,减少重复代码,提高开发效率
def 函数名(传入参数1,参数2):
函数体 #函数体遇到return后就结束了
return 返回值
#调用(并用变量接收返回值)
变量 = 函数名(参数)
'''
1.参数如不需要,可以省略
2.返回值如不需要,可以省略
3.函数必须先定义后使用
'''
None类型
Python中的一个特殊字面量:None,其类型是:<class’NoneType’>
用于表示:空、无意义
无返回值的函数,实际上就是返回了:None这个字面量
使用场景
-
用在函数无返回值上
- 在函数内,不使用return语句既默认返回None/或主动return None
-
用在if判断上
-
用在if判断中,None等同于False
-
一般用于在函数中主动返回None,配合if判断做相关处理
-
def check_age(age): if age >= 18: return "SUCCESS" else: return None#可不添加,默认返回None result = check_age(5) if not result: print("未成年,禁止进入")
-
-
用于声明无内容的变量上
-
定义变量,但暂时不需要变量有具体值,可以用None来代替
-
name = None
-
函数的说明文档
给函数添加说明文档,辅助理解函数的作用
def func(x,y):
"""
函数说明
:param x: 形参x的说明
:param y: 形参y的说明
:return: 返回值的说明
"""
函数体
return 返回值
通过多行注释的形式,对函数进行说明解释
- 内容应写在函数体之前
在用pyCharm编写代码时,调用函数处可以通过鼠标悬停
,查看调用函数的说明文档
func(5,6)#鼠标悬停到传参处,查看函数说明文档
函数的嵌套
在一个函数里面又调用了另外一个函数
流程:函数A中执行到嵌套的函数B,会将函数B全部执行完毕后,再继续执行剩余A的内容
递归:特殊的嵌套,函数嵌套自己
def f_a():
print("---2---")
def f_b():
print("---1---")
f_a()
print("---3---")
#调用函数f_a
f_b()
#执行效果
---1---
---2---
---3---
变量的作用域
局部变量:定义在函数内部的变量,在函数外部无法使用(在函数体内部临时保存数据,调用完成后,销毁局部变量)
全局变量:在函数体内、外都能生效的变量
global关键字
使用global关键字可以在函数内部声明变量为全局变量
num = 100
def f_a():
global num#设置内部定义的变量为全局变量
num = 200
print(num)
f_a()#200
print(num)#200
ATM银行案例
money = 5000000
name = input("请输入用户的姓名")
def query(show_header):
if show_header:
print("----------查询余额----------")
print(f"{name}您好,您的余额是{money}")
def saving(num):
global money
money += int(num)
print("----------存款----------")
print(f"{name}您好,成功存款{num}元")
query(False)
def get_money(num):
global money
money -= int(num)
print("----------取款----------")
print(f"{name},您好,成功取款{num}元")
query(False)
def main():
print("----------主菜单----------")
print(f"{name}您好,欢迎来到黑马ATM银行,请选择操作:")
print("查询余额\t[输入1]")
print("存款\t\t[输入2]")
print("取款\t\t[输入2]")
print("退出\t\t[输入4]")
return input("请输入您的选择:")
while True:
keyboard_input = main()
if keyboard_input == "1":
query(True)
continue
elif keyboard_input == "2":
num = input("您想要存多少钱?请输入:")
saving(num)
continue
elif keyboard_input == "3":
num = input("您想要取多少钱?请输入:")
get_money(num)
continue
else:
print("程序退出了")
break
函数和方法
在python中,如果将函数定义为class(类)的成员,那么函数会称之为:方法
函数的使用:
num = add(1,2)
方法的使用:
student = Student()
num = student.add(1,2)
数据容器(列表、元组、字符串、set、map)
数据容器:一种可以存储多个元素的Python数据类型
(每个元素,可以是任意类型的数据,如字符串、数字、布尔等。)
数据容器根据特点的不同,如:
- 是否支持重复元素
- 是否可以修改
- 是否有序,等
分为5类:列表(list)、元组(tuple)、字符串(str)、集合(set)、字典(dict)
list列表[ ](有序,可更改,可重复)
可变类型(可重复,任意数据类型的元素,可读可写,每一个位置上的元素可修改)
(可容纳不同类型的元素,有序存储(下标),允许重复数据存在,可以修改)
定义
#列表定义:以[]作为标识,列表内的每一个元素用,逗号隔开
#字面量
[元素1,元素2,元素3,元素4,...]
#定义变量
变量名称 = [元素1,元素2,元素3,元素4,...]
#定义空变量
变量名称 = []
变量名称 = list()
#嵌套
name_list = [[1,2,3],[4,5,6]]
列表的下标索引
列表的每一个元素,都有编号称之为下表索引
从前向后的方向,编号从0开始递增
从后向前的方向,编号从-1开始递减
(超出下标索引范围,无法去除元素,且会报错)
#列表[下标索引]
name_list = ['Tom','Lily','Rose']
print(name_list[0]) #结果:Tom
print(name_list[1]) #结果:Lily
print(name_list[2]) #结果:Rose
# - 反向索引
print(name_list[-1]) #结果:Rose
print(name_list[-2]) #结果:Lily
print(name_list[-3]) #结果:Tom
#嵌套索引的下标
name_list = [[1,2,3],[4,5,6]]
print(my_list[1][1]) #结果:4
常用操作
除了 定义/使用下标索引取内容
以外,列表也提供了一系列功能(列表的方法)
列表的方法: 插入元素/删除元素/清空元素/修改元素/统计元素个数
列表常见的功能(方法):
使用方式 | 作用 |
---|---|
列表.append(元素) | 追加单个元素(将指定元素,追加到列表的尾部) |
列表.extend(其他数据容器) | 追加一批元素(将其他数据容器的内容取出,依次追加到列表尾部) |
列表.insert(下标,元素) | 插入元素(在指定的下标位置,插入指定的元素) |
del 列表[下标] | 仅删除元素(函数) |
列表.pop(下标) | 删除元素外,并返回被删除元素(方法) |
列表.remove(元素) | 删除某元素在列表中的第一个匹配项 |
列表.clear() | 清空列表 |
列表[下标]=值 | 修改特定位置(索引)的值 |
列表.index(元素) | 查找指定元素在列表中的下标,如果找不到报错ValueError |
列表.count(元素) | 统计某元素在列表中的数量,并返回统计结果 |
len(列表) | 统计列表中全部的元素数量(列表长度 ) |
特点
列表(
- 1.可容纳多个数据,
- 2.可容纳不同类型的元素,
- 3.有序存储(下标),
- 4.允许重复数据存在,
- 5.可以修改)
学习编程,会学习很多东西,除了经常用的,大多数是记忆不下来的。
我们要做的是,有一个模糊印象,知晓有这样的用法即可。需要的时候查阅资料即可
列表的遍历
将容器内的元素依次取出进行处理的行为,称之为:遍历、迭代。
#while循环
index = 0
while index < len(列表):
元素 = 列表[index]
对元素进行处理
index += 1
#for循环
for 临时变量 in 数据容器:
对临时变量进行处理
两者的对比:
(for循环更简单,while更灵活)
(for用于从容器内依次取出元素并处理,while用于任何需要循环内的场景)
- 循环控制上
- while循环
可以自定循环条件
,并自行控制- for循环
不可以自定循环条件
,只可以一个个冲容器内取出数据- 无限循环上
- while循环可以通过条件控制做到无限循环
- for循环理论上不可以,因为被遍历的容器容量不是无限的
- 使用场景上
- while循环适用于任何想要的循环的场景
- for循环适用于,遍历数据容器的场景或简单的固定次数循环场景
tuple元组( )(有序,不可更改,可重复)
(不可变 可重复 任意数据类型的元素 可读)
列表是可修改的
如果想要传递的信息,不被篡改,列表就不合适了
元组同列表一样,都是可以封装多个、不同类型的元素在内。
最大的不同点在于:
元组一旦定义完成,就不可修改
所以我们需要在程序内封装数据,又不希望封装的数据被篡改,那么元组就非常合适了
定义
元组定义:定义元组使用小括号,且使用逗号隔开各个数据,数据可以是不同的数据类型
#定义元组字面量
(元素1,元素2,元素3,元素4,...)
#定义元组变量
变量名称 = (元素1,元素2,元素3,元素4,...)
#定义空元组
变量名称 = () #方式1
变量名称 = tuple() #方式2
#元组的嵌套
((1,2,3),(4,5,6))
#下标索引取内容
t5 = ((1,2,3),(4,5,6))
num = t5[1][2]
print(num) #6
注意:定义单个元素的元组(要在后面加上一个逗号)
#定义单个元素的元组(要在后面加上一个逗号)
#t4 = ("hello") #<class 'str'>
t4 = ("hello",) #<class 'tuple'>
print(f"t4类型为:{type(t4)},内容是:{t4}")
相关操作
因为元组的不可修改,所以操作较少
方法 | 作用 |
---|---|
元组.index(元素) | 查找某个数据,如果数据存在返回对应的下标,否则报错 |
元组.count(元素) | 统计某个数据在当前元组出现的次数 |
len(元组) | 统计元组内的元素个数 |
注意:
- 不可以修改元组的内容(但可以修改元组内的list元素内的内容)
特点
元组特点(
- 1.可容纳多个数据,
- 2.可容纳不同类型的元素,
- 3.有序存储(下标),
- 4.允许重复数据存在,
- 5.
不可以修改(但可以修改元组内的list元素内的内容)
, - 6.支持for循环)
多数特性和list一致,不同点在于不可修改的特性。
元组的遍历
#while循环
index = 0
while index < len(元组):
元素 = 元组[index]
对元素进行处理
index += 1
#for循环
for 临时变量 in 数据容器:
对临时变量进行处理
字符串
字符串是字符的容器,一个字符串可以存放任意数量的字符,每一个字符就是字符串的一个元素
通过下标索引取值
my_str = "Emotional damage"
value = my_str[2] #o
value2 = my_str[-16] #E
print(f"取正向下标为2的元素,值为:{value},取反向下标为-16的索引,值为{value2}")
同元组一样,字符串是一个:无法修改
的数据容器
常用操作
操作 | 说明 |
---|---|
字符串[下标] | 根据下标索引取出指定位置字符 |
字符串.index(字符串) | 查找给定字符的第一个匹配项的下标 |
字符串.replace(字符串1,字符串2) | 将字符串内的全部字符串1,用字符串2替换,不修改原字符串,而是返回一个新的 |
字符串.split(字符串) | 按给定的字符串,对字符串进行分割,不会修改原字符串,而是返回一个新的列表 |
字符串.strip() 字符串.strip(字符串) | 移除首尾的空格和换行符或指定字符串(是按给定字符串的全部单个字符,来进行移除),返回一个新的字符串 |
字符串.count(字符串) | 统计字符串内某字符串的出现次数 |
len(字符串) | 统计字符串的字符个数 |
#例:字符串.strip(字符串)
my_str = "1212asdfasdf1212"
new_my_str=my_str.strip("12")
print(f"字符串{my_str},替换后得到{new_my_str}")
#字符串1212asdfasdf1212,移除后得到asdfasdf
特点
字符串特点(
- 1.长度任意(取决于内存大小),
- 2.
只存储字符串
, - 3.有序存储(下标),
- 4.允许重复字符串存在,
- 5.
不可以修改
, - 6.支持for循环)
字符串的遍历
#while循环
index = 0
while index < len(字符串):
元素 = 字符串[index]
对元素进行处理
index += 1
#for循环
for 临时变量 in 字符串:
对临时变量进行处理
数据容器(序列)的切片
序列
序列是指:
内容连续、有序,可使用下标索引的一类数据容器
(列表、元组、字符串),均可以视为序列。
切片操作
序列支持切片
切片:从一个序列中取出一个子序列
语法:
序列[起始下标:结束下标:步长]
表示从序列中,从指定位置开始,依次取出元素,到指定位置结束,得到一个新序列:
- 起始可以省略,视作从头开始(起始下标表示从何处开始)
- 结束可以省略,视作到尾结束(结束下标(不含)表示何处结束)
- 步长可以省略,默认步长为1(可以为负数,表示倒序执行)
注意,此操作不会影响序列本身,而是会得到一个新的序列
(列表、元组、字符串) (因为考虑到元组和字符串都是不支持修改的)
#对list进行切片,从1开始,4结束,步长1
my_list = [0,1,2,3,4,5,6]
result = my_list[1:4] #步长默认是1,所以可以不写
print(f"结果1:{result1}") #结果1:[1,2,3]
#对tuple进行切片,从头开始,到最后结束,步长1
my_tuple = (0,1,2,3,4,5,6)
result2 = my_tuple[:] #起始和结束不写表示从头到尾,步长为1可以省略
print(f"结果2:{result2}") #结果2:(0,1,2,3,4,5,6)
#对str进行切片,从头开始,到最后结束,步长2
my_str = "01234567"
result3 = my_str[::2]
print(f"结果3:{result3}") #结果3:0246
#对str进行切片,从头开始,到最后结束,步长-1
my_str = "01234567"
result4 = my_str[::-1]
print(f"结果4:{result4}") #结果4:76543210
#对列表进行切片,从3开始,到最后结束,步长-1
my_list = [0,1,2,3,4,5,6]
result5 = my_list[3:1:-1]
print(f"结果5:{result5}") #结果6:[3,2]
#对元组进行排序,从头开始,到尾结束,步长-2
my_tuple = (0,1,2,3,4,5,6)
result6 = my_tuple[::-2]
print(f"结果6:{result6}") #结果6:(6,4,2,0)
set集合{ }(无序(不支持索引),可修改(增/删元素),不可重复(自带去重))
元素是不可变类型
列表可修改,支持重复元素且有序
元组、字符串不可修改、支持重复元素且有序
局限就在于:它们都支持重复元素
如果场景需要对内容作去重处理,列表、元组、字符串就不方便了
基本语法
#定义集合字面量
{元素,元素,......,元素}
#定义集合变量
变量名称 = {元素,元素,......,元素}
#定义空集合
变量名称 = set{}
和列表、元组、字符串等定义基本相同:
- 列表使用:[ ]
- 元组使用:( )
- 字符串使用:" "
- 集合使用:{ }
- 字典使用:{键值对}
集合的常用操作-修改
集合是无序的,所以集合不支持:下标索引访问
,所以集合不是序列 (一旦发生改变,元素就会洗牌了)
集合和列表一样,是允许修改
的,无法修改元素只能增加和删除元素
常用操作
操作 | 说明 |
---|---|
集合.add(元素) | 集合内添加一个元素 |
集合.remove(元素) | 移除集合内指定的元素 |
集合.pop() | 从集合中随机取出一个元素 |
集合.clear() | 将集合清空 |
集合1.difference(集合2) | 得到一个新集合,内含2个集合的差集,(原有的2个集合内容不变) |
集合1.difference_update(集合2) | 在集合1中,删除与集合2中相同的元素,(集合1被修改,集合2不变) |
集合1.union(集合2) | 得到1个新集合,内含2个集合的全部元素(去重),(原有的2个集合内容不变) |
len(集合) | 得到一个整数,记录了集合的元素数量 |
#添加新元素
#集合.add(元素)
my_set = {"Geats骑士核心ID","欲望驱动器","马格南升级带扣"}
my_set.add("推进器升级带扣")
my_set.add("欲望驱动器") #相同元素,会被去重,等于没有添加
print(f"添加元素后的结果{my_set}")
#添加元素后的结果{'推进器升级带扣', '欲望驱动器', '马格南升级带扣', 'Geats骑士核心ID'}
#移除元素
#集合.remove(元素)
my_set.remove("推进器升级带扣") #{'欲望驱动器', '马格南升级带扣', 'Geats骑士核心ID'}
print(f"添加元素后的结果{my_set}")
#随机取出一个元素
#集合.pop()
#无论取出哪一个元素,该元素在该集合中将不存在
element = my_set.pop()
print(f"集合被取出元素是:{element},取出元素后的集合:{my_set}") #可能为集合中任意一个元素
#清空集合
#集合.clear()
my_set.clear()
print(f"集合清空后,结果是{my_set}") #结果为:set() 空集合
#取出2个集合的差集
#语法:集合1.difference(集合2)
#功能:取出集合1和集合2的差集(集合1有而集合2没有的)
#结果:得到一个新集合,集合1和就集合2不变
set1 = {1,2,3}
set2 = {1,5,6}
set3 = set1.difference(set2)
print(set3) #结果:{2,3} 得到的新集合
print(set1) #结果:{1,2,3} 不变
print(set2) #结果:{1,5,6} 不变
#消除2个集合的差集
#语法:集合1.difference_update(集合2)
#功能:对比集合1和集合2,在集合1内,删除和集合2相同的元素
#结果:集合1被修改,集合2不变
set1 = {1,2,3}
set2 = {1,5,6}
set1.difference_update(set2)
print(f"消除差集后,集合1结果:{set1}") #结果:{2,3} 不变
print(f"消除差集后,集合1结果:{set2}") #结果:{1,5,6} 不变
#2个集合的合并
#语法:集合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) # 结果:{1,2,3}
print(set2) # 结果:{1,5,6}
#统计集合所有元素的数量
#语法:len(集合)
#功能:返回统计该集合中所有元素的数量
set1 = {1,2,3,4,5}
#set1 = {1,2,3,4,5,1,2,3,4,5} #依旧为5,先去重在统计
num = len(set1)
print(f"集合内的元素数量有:{num}个")
#集合的遍历
#集合不支持下标索引,不能用while循环
#可以用for循环
set1 = {1,2,3,4,5}
for element in set1:
print(f"集合的元素有:{element}")
特点
- 可容纳多个数据
- 可容纳不同类型的数据(混装)
- 数据是无序存储的(不支持下标索引)
- 不允许重复数据存在
- 可以修改(增加或删除元素等)
- 支持for循环
字典 {键值对} dictionary (无序,可更改,有索引(键),不可重复(键必须唯一))
k:不可变类型 必须唯一(不可为字典、列表等)
v:没有要求
#键必须是唯一的,但值则不必。
d = {key1 : value1, key2 : value2, key3 : value3 }
# 使用大括号 {} 来创建空字典
emptyDict = {}
#使用内建函数 dict() 创建字典
emptyDict = dict()
#字典的嵌套
e = {key1 : {vk1:v1,vk2:v2}, key2 : value2}
print(e[key1][vk1]) #v1
访问字典里的值
#不可通过下标索引,而是通过key检索value
tinydict = {'Name': 'Runoob', 'Age': 7, 'Class': 'First'}
print ("tinydict['Name']: ", tinydict['Name'])
print ("tinydict['Age']: ", tinydict['Age'])
#输出结果
#tinydict['Name']: Runoob
#tinydict['Age']: 7
#用字典里没有的键访问数据,会输出错误如下
新增元素
d1 = { "aa" : 1 , "bb" : 2 , "cc" : 3 }
#新增
d1["dd"] = 4
print(d1)
修改字典元素
tinydict = {'Name': 'Runoob', 'Age': 7, 'Class': 'First'}
tinydict['Age'] = 8 # 更新 Age
tinydict['School'] = "菜鸟教程" # 添加信息
print("tinydict['Age']: ", tinydict['Age'])
print("tinydict['School']: ", tinydict['School'])
#tinydict['Age']: 8
#tinydict['School']: 菜鸟教程
删除字典元素
能删单一的元素也能清空字典,清空只需一项操作。
tinydict = {'Name': 'Runoob', 'Age': 7, 'Class': 'First'}
# 删除键 'Name'
del tinydict['Name']
#或用pop()
result = tinydict.pop("Name")
print(f"被删除的元素的参数:{result}") #能返回被删除的参数
# 清空字典
tinydict.clear()
# 删除字典
del tinydict
获取全部的key
tinydict = {'Name': 'Runoob', 'Age': 7, 'Class': 'First'}
keys = tinydict.keys()
print(keys) #dict_keys(['Name', 'Age', 'Class'])
#同理dict.values()返回字典的所有值
遍历
tinydict = {'Name': 'Runoob', 'Age': 7, 'Class': 'First'}
#方式1:通过获取到全部的key来完成遍历
keys = tinydict.keys()
for i in keys:
print(f"键为:{i}")
print(f"值为:{tinydict[i]}")
#方式2:直接对字典进行for循环(每一次循环都是直接得到key)
#更简洁
for i in tinydict:
print(f"键为:{i}")
print(f"值为:{tinydict[i]}")
'''
运行结果为:
键为:Name
值为:Runoob
键为:Age
值为:7
键为:Class
值为:First
'''
常用操作
操作 | 说明 |
---|---|
字典[key] | 获取指定Key对应的Value值 |
字典[key] = value | 添加或更新键值对 |
字典.pop(Key) | 取出Key对应的Value并在字典内删除此Key的键值对 |
字典.clear() | 清空字典 |
字典.keys() | 获取字典的全部Key,可用于for循环遍历字典 |
len(字典) | 计算字典内的元素数量 |
注意:新增和更新元素的语法一致 ,如果Key不存在既新增,如果Key存在既更新(Key不可重复)
字典内置函数&方法
Python字典包含了以下内置函数:
序号 | 函数及描述 | 实例 |
---|---|---|
1 | len(dict) 计算字典元素数量,即键的总数。 | >>> tinydict = {‘Name’: ‘Runoob’, ‘Age’: 7, ‘Class’: ‘First’} >>> len(tinydict) 3 |
2 | str(dict) 输出字典,可以打印的字符串表示。 | >>> tinydict = {‘Name’: ‘Runoob’, ‘Age’: 7, ‘Class’: ‘First’} >>> str(tinydict) “{‘Name’: ‘Runoob’, ‘Class’: ‘First’, ‘Age’: 7}” |
3 | type(variable) 返回输入的变量类型,如果变量是字典就返回字典类型。 | >>> tinydict = {‘Name’: ‘Runoob’, ‘Age’: 7, ‘Class’: ‘First’} >>> type(tinydict) <class ‘dict’> |
Python字典包含了以下内置方法:
序号 | 函数及描述 |
---|---|
1 | dict.clear() 删除字典内所有元素 |
2 | dict.copy() 返回一个字典的浅复制 |
3 | dict.fromkeys() 创建一个新字典,以序列seq中元素做字典的键,val为字典所有键对应的初始值 |
4 | dict.get(key, default=None) 返回指定键的值,如果键不在字典中返回 default 设置的默认值 |
5 | key in dict 如果键在字典dict里返回true,否则返回false |
6 | dict.items() 以列表返回一个视图对象(返回可遍历的(键, 值) 元组列表) |
7 | dict.keys() 返回一个视图对象(返回字典中所有的key值) |
8 | dict.setdefault(key, default=None) 和get()类似, 但如果键不存在于字典中,将会添加键并将值设为default |
9 | dict.update(dict2) 把字典dict2的键/值对更新到dict里 |
10 | dict.values() 返回一个视图对象 |
11 | pop(key[,default]) 删除字典 key(键)所对应的值,返回被删除的值(key - 要删除的键 default - 当键 key 不存在时返回的值) |
12 | popitem() 返回并删除字典中的最后一对键和值 |
特点
- 可以容纳多个数据
- 可以容纳不同类型的数据
- 每一份数据是KeyValue键值对
- 可以通过key获取到Value,Key不可重复(重复会覆盖)
- 不支持下标索引
- 可以修改(增加或删除更新元素等)
- 支持for循环,不支持while循环
1)不允许同一个键出现两次。创建时如果同一个键被赋值两次,后一个值会被记住,如下实例:
2)键必须不可变,所以可以用数字,字符串或元组充当,而用列表就不行,如下实例:
tinydict = {['Name']: 'Runoob', 'Age': 7}
print ("tinydict['Name']: ", tinydict['Name'])
#报错
"""
Traceback (most recent call last):
File "test.py", line 3, in <module>
tinydict = {['Name']: 'Runoob', 'Age': 7}
TypeError: unhashable type: 'list'
"""
总结
数据容器可以从以下视角进行简单分类:
- 是否支持下标索引
- 支持:列表、元组、字符串
- 不支持:集合、字典
- 是否支持重复元素
- 支持:列表、元组、字符串
- 不支持:集合、字典
- 是否可以修改
- 支持:列表、集合、字典
- 不支持:元组、字符串
列表 | 元组 | 字符串 | 集合 | 字典 | |
---|---|---|---|---|---|
元素数量 | 支持多个 | 支持多个 | 支持多个 | 支持多个 | 支持多个 |
元素类型 | 任意 | 任意 | 仅字符串 | 任意 | 键值对Key:除字典外任意类型Value:任意类型 |
下标索引 | 支持 | 支持 | 支持 | 不支持 | 不支持 |
重复元素 | 支持 | 支持 | 支持 | 不支持 | 不支持 |
可修改性 | 支持 | 不支持 | 不支持 | 支持 | 支持 |
数据有序 | 是 | 是 | 是 | 否 | 否 |
使用场景 | 可修改、可重复的一批数据记录场景 | 不可修改、可重复的一批数据记录场景 | 一串字符的记录场景 | 去重的一批数据记录场景 | 用Key检索Value的一批数据记录场景 |
数据容器的通用操作 - 遍历
len(容器):统计容器的元素个数
max(容器):统计容器的最大元素
min(容器):统计容器的最小元素
容器通用转换功能
list() :将给定容器转换为列表
tuple() :将给定容器转换为元组
str() :将给定容器转换为字符串,(给定容器原来打印输出的样子转为字符串)
set() :将给定容器转换为集合,无序去重
字符串转列表/元组,将字符串里的每一个元素都取出来,作为列表/元组的每一个元素
字典转列表/元组,将Value全抛弃掉,只留下Key
容器通用排序功能
sorted(容器,[reverse=False]) ;将给定容器进行排序,reverse默认为False(reverse= True表示倒序排序)
注意:
排序的结果都会变成列表对象,
字典对象按照Key进行排序并抛弃value,
字符按照对应的ASCII码表的码值打小抄进行大小比较,
字符串是按位比较,一位位比较,只要有一位大,那么整体大(既整体字符串中每一位元素的码值的和来进行大小比较)
my_1ist=[3,1,2,5,4]
my_tuple=(3,1,2,5,4)
my_str "bdcefga"
my-set={3,1,2,5,4}
my_dict={"key3":1,"key1":2,"key2":3,"key5":4,"key4":5}
print(f"列表对象的排序结果:{sorted(my_List)}")
print(f"元组对象的排序结果:{sorted(my_tuple)}")
#列表对象的排序结果:[1,2,3,4,5]
#元组对象的排序结果:[1,2,3,4,5]
#字符串对象的排序结果:['a','b','c','d','e','f",·g']
#集合对象的排序结果:[1,2,3,4,5]
#字典对象的排序结果:['key1','key2','key3','key4','key5']
#反向排序
print(f"列表对象的排序结果:{sorted(my_List),reverse=True}")
print(f"元组对象的排序结果:{sorted(my_tuple),reverse=True}")
print(f"字符串对象的排序结果:{sorted(my_str),reverse=True}")
print(f"集合对象的排序结果:{sorted(my_set),reverse=True}")
print(f"字典对象的排序结果:{sorted(my_dict),reverse=True}")
功能 | 描述 |
---|---|
通用for循环 | 遍历容器(字典时遍历key) |
max() | 容器内最大元素 |
min() | 容器内最小元素 |
len() | 容器元素个数 |
list() | 转换为列表 |
tuple() | 转换为元组 |
str() | 转换为字符串 |
set() | 转换为集合 |
sorted(序列,[reverse = True]) | 排序,reverse=True表示降序,结果得到一个排好序的列表 |
总结
- 可变数据类型: 列表, 字典(增删,修改value), 集合(增删元素)
- 不可变数据类型: 数值类型, 字符串, 元组
- 可变数据类型实现某个功能, 直接改变可变的数据类型;
- 不可变数据类型实现某个功能,需要将结果赋值给另外一个变量;
- 是否实现for循环
- 可迭代数据类型: str, list, tuple, dict, set
- 不可迭代数据类型:数值类型
- 是否支持索引(while循环),切片, 重复和连接特性
- 有序的数据类型: str, list, tuple
- 无序的数据类型: dict, set
相关链接:https://blog.youkuaiyun.com/Sunny_Future/article/details/79018295
python函数进阶
多个返回值
def test_return():
return 1,2,"hello"
x,y,z = test_return()
print(x) #1
print(y) #2
print(z) #hello
按照返回值的顺序,写对应顺序的多个变量接收即可
变量之间用逗号隔开
支持不同类型的数据return
函数的多种传参方式
函数的4种常见参数使用方式:
-
1、位置参数
:调用函数时根据函数定义的参数位置来传递参数- 注意:传递的参数和定义的参数的顺序及个数必须一致
-
2、关键字参数
:- 作用:可以让函数更加清晰、容易使用,同时也清除了参数的顺序需求
- 注意:函数调用时,和位置参数混用时,位置参数必须在前面,而关键字参数之间不分先后顺序
-
3、缺省参数
:也叫默认参数,用于定义参数,为参数提供默认值,调用函数时可不传该默认参数的值(注意:所有位置参数必须出现在默认参数前,包括函数定义和调用)- 作用:当调用函数时没有传递参数,就会使用默认用缺省参数对应的值
- 注意:定义函数时,默认参数必须都定义在最后 ,例子:user_info(name,age=12,gender=‘男’):
-
4、不定长参数
:也叫可变参数,用于不确定调用的时候传递多少个参数(也可不传参)的场景-
作用:当调用函数时不确定参数个数时,可以使用不定长参数
-
不定长参数的类型 :
-
位置不定长传递:以*号标记一个形式参数,以元组的形式接收参数,形式参数一般命名为args(传进的所有参数都会被args变量收集,它会根据传进参数的位置合并为一个元组。args是元组类型)
def 函数名(*args): 代码块
-
关键字不定长传递:以**号标记一个形式参数,以字典的形式接收参数,形式参数一般命名为kwargs(参数是“键=值”形式的情况下,所有的“键=值”都会被kwargs接受,同时会根据“键=值”组成字典)
def 函数名(**kwargs): 代码块
-
-
注意:args和kwargs都是规范要求,*和**后面可以自定义起名,但建议使用规范写法
-
'''
位置参数
'''
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="小明",age=20,gender="男")
#可以不按照固定顺序
user_info(age=20,gender="男",name="小明")
#可以和位置参数混用,位置参数必须在前,且匹配参数顺序
user_info("小明",age=20,gender="男")
'''
缺省参数(默认值)
'''
def user_info(name,age=12,gender='男'): #默认参数必须都放在最后
print(f"您的名字是:{name},年龄是:{age},性别是:{gender}")
user_info('小天',13) #您的名字是:小天,年龄是:13,性别是:男
user_info('小天',13,'女') ##您的名字是:小天,年龄是:13,性别是:女
'''
不定长参数(可变参数)
位置不定长:
*号(规范写法:*args)
接受不定长形参合并为一个数组
关键之不定长:
**号(规范写法:**kwargs)
接收不定长形参(kw格式)组成一个字典
'''
##位置传递用*args(传递进args的不定长数量的形参,合并为一个元组存在)
def user_info(*args):
print(args)
user_info('TOM')
#结果打印输出('TOM',) #定义单个元素的元组(要在后面加上一个逗号)
user_info('TOM',18)
#结果打印输出('TOM',18)
##关键字传递用**kwargs(传递进kwargs的不定长数量键值对形参,组成一个字典存在)
#传入参数必须为键值对
def user_info(**kwargs):
print(kwargs)
user_info(name='TOM',age=18,id=110)
#结果打印输出{'name': 'TOM', 'age': 18, 'id': 110}
匿名函数
函数作为参数传递
def test_func(compute):
result = compute(1,2) #确定compute是函数
print(result)
def compute(x,y):
return x + y
test_func(compute) #结果:3
传入计算逻辑,而非数据。
就像上述代码那样,相加、相减、相除、等任何逻辑都可以自行定义并作为函数传入
Lambda匿名函数
#语法格式:
lambda 传入参数:函数体(一行代码,自带return功能)
#lambda是关键字,表示定义匿名函数
#传入参数表示匿名函数的形式参数,如:x,y表示接收2个形式参数
#函数体,就是函数的执行逻辑,要注意:只能写一行,无法写多行代码
注意:
- 匿名函数用于临时构建一个函数,只用一次的场景
- 匿名函数的定义中,函数体只能写一行代码,如果函数体要写多行代码,不可用lambda匿名函数,应使用def定义带名函数
def test_func(compute):
result = compute(1,2)
print(result)
test_func(lambda x,y:x + y) #结果:3(匿名函数只可临时使用一次,且只能写一行)
函数的定义中
- def关键字,可以定义带有名称的函数
- lambda关键字,可以定义匿名函数(无名称)
有名称的函数,可以基于名称重复使用。
无名称的匿名函数,只可临时使用一次
python文件操作
文件的编码
- 编码简介
编码就是一种规则集合,记录了内容和二进制间进行相互转换的逻辑。
编码有许多,我们最常用的是utf-8编码
- 为什么使用编码
计算机只认识0和1,所以需要将内容翻译成0和1才能保存在计算机中。
同时也需要编码,将计算机保存的0和1,反向翻译回可以识别的内容。
一、文件的读取
文件可分为 文本文件、视频文件、音频文件、图像文件、可执行文件等多种类别
1.打开
2.读写
3.关闭
1、打开文件
#open()
#with open()
#open()语法
open(name,mode,encoding)
#示例
f = open('python.txt','r',encoding='UTF-8')
#encoding的顺序不是第三位,所以不能用位置参数,用关键字参数直接指定
#此时的f是open函数的文件对象
#with open 语法(在语句块中操作文件,避免忘了close操作)
with open("python.txt","r")as f:
f.readlines()
#通过在with open的语句块中对文件进行操作
#可以在操作完成后自动关闭close文件,避免遗忘掉close方法
name:是要打开的目标文件名的字符串(可以包含文件所在的具体路径)
mode:设置打开文件的模式(访问模式):只读、写入、追加等
encoding:编码格式(推荐使用utf-8)
mode常用的三种基础访问模式
模式 | 描述 |
---|---|
r | 以只读方式打开文件。文件的指针将回放在文件的开头。这是默认模式 |
w | 打开一个文件只用于写入。如果该文件已存在则打开文件并覆写(并从头开始编辑,原有内容会被删除)。如果该文件不存在,创建该新文件 |
a | 打开一个文件用于追加。如果该文件已存在,则在已有内容之后追加新内容。如果该文件不存在,创建该新文件进行写入 |
2、读写文件
#read(num)方法:按照num的大小决定读取数据的长度,没有num这表示全读
#readlines()方法:按照行的方式把整个文件读取(一行为一个列表元素),最后返回该列表
#readline()方法:一次读取一行内容
#read()方法
文件对象.read(num)
#num表示要从文件中读取的数据的长度,如果不传num那么就表示读取文件中的所有数据
#readlines()方法
#readlines可以按照行的方式把整个文件中的内容进行一次性读取,并且返回的是一个列表,其中每一行的数据为一个元素
f = open('python.txt')
content = f.readlines()
print(content)
f.close()
#注意:如果在同一个程序中多次调用read,下一次read会从第一次读取停止处继续往后读(readlines也会受到影响)
#for循环读取文件行
for line in open('python.txt','r'):
print(f"每一行数据是:{line}")
3、关闭文件
#close()关闭文件对象
f = open('python.txt','r')
f.close()
#最后通过close,关闭文件对象,也就是关闭对文件的占用
#如果不调用close,同时程序没有停止运行,那么这个文件将一直被Python程序占用
操作汇总
操作 | 功能 |
---|---|
文件对象 = open(file,mode,encoding) | 打开文件获得文件对象 |
文件对象.read(num) | 读取指定长度的字节,不指定num表示读取文件全部(得到的是string类型) |
文件对象.readline() | 读取一行 |
文件对象.readlines() | 读取全部行,得到列表 |
for line in 文件对象 | for循环文件的行,一次循环得到一行数据 |
文件对象.close() | 关闭文件对象 |
with open() as f | 通过with open语法打开文件,可以自动关闭 |
二、文件的写入
写,调用write,内容并未真正写入文件,而是会积攒在程序的内存中,称之为缓冲区(暂时先写入内存中)
需要调用flush()刷新,内容才会真正写入文件(真正写入到硬盘中)
close包含flush的功能(不使用flush直接用close也可将内容写入硬盘)
这样做是避免频繁操作硬盘,导致频率下降(攒一堆,一次性写硬盘)
文件的写入时打开文件使用模式w
如果写入文件不存在,会自动创建(创建文件无需flush,但内容需flush后才能写入)
如果写入文件已存在,会直接覆写原文件
f = open("D:/python1.txt","w",encoding="UTF-8")
#文件写入:write(),写入内容(暂时写入到缓冲区(内存)中)
f.write("Hello World!!!")
#内容刷新:flush(),刷新内容到硬盘中
f.flush()
f.close() #close包含flush的功能,可直接使用close
三、文件的追加
与追加步骤完全相同,将打开文件使用模式a即可
a模式,文件不存在会创建文件
a模式,文件存在会在最后,追加写入文件
f = open("D:/python1.txt","a",encoding="UTF-8")
f.write("Hello World!!!")
f.write("\n你好世界!!!")#加上\n可实现追加换行
f.flush()
f.close()
#文件的综合案例
'''
将bill.txt文件备份,并将每一行最后一个字段为测试的行筛选掉
'''
fr = open("D:/bill.txt","r",encoding="UTF-8")
fw = open("D:/bill.txt.bak","w",encoding="UTF-8")
for line in fr:
# if line.count("测试") >= 1:
# continue
if line.strip().split(",")[-1] == "测试":
continue
fw.write(line)
fr.close()
fw.close()
#验证
f = open("D:/bill.txt.bak","r",encoding="UTF-8")
print(f.read())
f.close()
异常处理(捕获异常)
平常程序遇到bug会有以下两种情况
1、整个程序因为一个bug停止运行
2、对BUG进行提醒,整个程序继续运行
真实工作中,我们希望达到2的结果,那这里我们就需要捕获异常
'''
#捕获异常
捕获异常的作用在于:提前假设某处会出现异常,做好提前准备,当针对出现异常的时候,可以有后续手段
#捕获指定异常
1、如果尝试执行的代码的异常类型和要捕获的异常类型不一致,则无法捕获异常
2、一般try下方只放一行尝试执行的代码
#捕获多个异常
把要捕获的多个异常的类型名,以元组的方式进行书写,并放到except后
可选项
else finally
注意:均捕获出现的第一个异常
'''
#1、基本捕获异常
try: #一般try下方只放一行尝试执行的代码
可能发生错误的代码
except:
如果出现异常,要执行的代码
else: #异常的else (可选项)
如果没有出现异常时,要执行的代码
finally: #异常的finally
无论是否异常,都要执行的代码
#2、捕获指定异常
try:
#可能发生错误的代码
print(name)
except NameError as e:
#如果捕获到指定的异常执行的代码
print('name变量名称未定义错误')
#e是异常的对象,记录着异常的具体信息(可打印输出查看)
print(e)
#3、捕获多个异常
try:
print(1 / 0)
except(NameError,ZeroDivisionError):
print('出现了变量未定义 或者 除以0的异常错误')
#4、捕获所有异常
#可直接使用基本捕获异常方法
#也可指定捕获Exception对象(顶级的异常)
try:
可能发生错误的代码
except Exception as e:
print('出现了异常错误')
#示例
try:
f = open('linux.txt','r')
except:
f = open('linux.txt','w')
异常的传递
异常是具有传递性的
(报错信息中会显示依次异常传递的位置)
(作用:不需要去最低层,真正出现异常的那句话去捕获,可以通过异常的传递性在高的层级去捕获)
def func01(): #异常在funco1中没有被捕获
print("这是func01开始")
num 1 / 0
print("这是func0结束")
def func02(): #异常在func02中没有被捕获
print("这是fuDc02开始")
func01()
print("这是func02结束")
def main(): #异常在mian中被捕获
try:
func02()
except Exception as e:
print(f"出现了异常,异常的信息是:{e}")
main()
模块
模块导入
模块:以.py结尾的python文件,模块能定义函数、类、变量、可执行代码
作用:我们可以认为一个模块就是一个工具包,通过导入这些模块,帮助我们快速实现一些功能
一般写在代码的开头位置
当导入多个模块时,同名模块或功能,调用到的是后面导入的模块的功能(后一个会把前一个覆盖掉)-----》解决方法:起别名
当导入的模块处字体呈灰色,代表该模块或功能未使用
模块导入方式:
[from 模块名] import [模块|类|变量|函数|*] [as 别名]
常见的组合方式:
import 模块名
from 模块名 import 类、变量、方法等
from 模块名 import *
import 模块名 as 别名
from 模块名 import 功能名 as 别名
#导入模块调用功能需要 模块.功能()
#导入功能时直接 功能()
ctrl+鼠标左键 可以查看内置模块的源代码
自定义模块
直接创建一个python文件,并写入所需的功能的代码,然后即可导入使用
_ _ main_ _ 变量
if __name__ == __main__:
代码块
# python文件都会有一个变量__name__,运行时这个变量的名称就会标记为main
# 当前程序运行时__name__会被标记为__main__,则该if判断为true,可以执行后面的代码块
# 用于限制部分操作仅在当前文件运行时执行(例如测试函数等操作),防止调用该模块文件时的执行
_ _ all_ _ 变量
__all__ = ['test','test1']
def test():
print("test")
def test1():
print("test1")
def test2():
print("test2c")
# __all__变量
# 如果一个模块文件中有__all__=['','']变量时,当使用‘from 模块名 import *’导入时,只能导入这个列表中的元素
# all是使用该方法导入模块时,可使用的元素
#_ _all_ _用于指定使用‘from 模块名 import *’方法导入该模块时,那些功能可以被导入
python包
物理上看,包就是一个文件夹,区别在该文件夹下包含了一个_ _init_ _.py文件
,包可用于包含多个模块文件
逻辑上看,包的本质依然是模块
包:一个包,就是一堆同类型功能的集合体
包的作用:当模块文件越来越多时,包可以帮我们管理这些文件,包的作用就是包含多个模块,但包的本质依然是模块
注意:包下必须有_ _init _ _.py文件,否则只是一个普通文件夹
#导包方式与导模块基本相同
# import my_package.my_module1 as mm1
# mm1.test()
import my_package.my_module1
import my_package.my_module2
my_package.my_module1.test()
my_package.my_module2.test()
from my_package import *
from my_package import my_module1
from my_package import my_module2
my_module1.test()
my_module2.test()
from my_package.my_module1 import test as t1
from my_package.my_module2 import test as t2
t1()
t2()
#此处同包不同模块的功能同名,需要设别名,否则最后的覆盖前面的
在包中的 _ _init _ _ .py文件中添加 _ _all _ _=[ ],用于控制允许导入的模块列表,同样只有在使用from my_package import *
方法导包时有效
第三方包安装
python生态非常丰富,有非常多第三方包,能极大帮助我们提高开发效率,第三方没有内置,所以我们需要安装第三方包才能导入使用
安装第三方包:
使用python内置的pip程序
在命令符中输入pip install 包名称
即可安装第三方包
速度慢是因为pip默认使用的是国外的网站,可使用以下命令连接国内的网站pip install -i https://pypi.tuna.tsinghua.edu.cn/simple 包名称
也可在pycharm中安装,记得勾选上options并添加-i https://pypi.tuna.tsinghua.edu.cn/simple换用国内源
Json数据格式的转换
什么是JSON:是一种轻量化的数据交互格式。可以按照JSON指定的格式去组织和封装数据
JSON本质上是一个带有特定格式的字符串
主要功能:json就是一种在各个编程语言中流通的数据格式,负责不同编程语言中的数据传递和交互,类似于:
-
国际通用语言-英语
-
中国56个民族不同地区的通用语言-普通话
python数据(字典、列表)和json数据(字符串)使用dumps和loads相互转换
1、json_str = json.dumps(data)
将python数据转化为json数据
如果有中文,可以在data后带上ensure_ascii=False
参数来确保中文正常转换
2、py_data = json.loads(data)
将json数据转化为python数据
#使用python内置的json模块
import json
# 通过json.dumps(data)方法把python数据转化为json数据
data = [{"name": "老王", "age": 16}, {"name": "张三", "age": 20}] # 准备符合(json格式)要求的python数据
json_str = json.dumps(data, ensure_ascii=False)
data1 = {"name": "周杰伦", "addr": "台北"}
json_str = json.dumps(data1, ensure_ascii=False)
print(type(json_str)) #<class 'str'>
print(json_str) #{"name": "周杰伦", "addr": "台北"}
# 通过json.loads(data)方法把json数据转换为python数据
data = '[{"name": "老王", "age": 16}, {"name": "张三", "age": 20}]'
l = json.loads(data)
data1 = {"name": "周杰伦", "addr": "台北"}
d = json.loads(data)
print(type(l)) #<class 'list'>
print(l) #[{'name': '老王', 'age': 16}, {'name': '张三', 'age': 20}]
print(type(d)) #<class 'dict'>
print(d) #{'name': '周杰伦', 'addr': '台北'}
pyecharts模块
概况:
Echarts是个由百度开源的数据可视化,凭借着良好的交互性,精巧的图表设计,得到了众多开发者的认可。而Python是门富有表
达力的语言,很适合用于数据处理。当数据分析遇上数据可视化时pyecharts诞生了,(echarts适用于Javascript语言,pyecharts是后来推出专用于为python的模块)
工具网站:ab173.com
"""
演示基础折线图的使用
"""
# 导包
from pyecharts.charts import Line
from pyecharts.options import TitleOpts, LegendOpts,ToolboxOpts,VisualMapOpts
# from pyecharts._version import __author__,__version__
# print(__author__)
# print(__version__)
# 得到折线图对象
line = Line()
# 添加x轴数据
line.add_xaxis(['中国', '美国', '英国'])
# 添加y轴数据
line.add_yaxis("GDP", [100, 20, 10])
# 设置全局配置项,通过set_global_opts来设置
line.set_global_opts(
#标题
title_opts=TitleOpts(title="GDP展示", pos_left="center", pos_bottom="1%"),
#图例(默认显示)
legend_opts = LegendOpts(is_show=True),
#工具箱
toolbox_opts=ToolboxOpts(is_show=True),
#视觉映射
visualmap_opts=VisualMapOpts(is_show=True)
)
# 生成图表
line.render()
"""
演示地图可视化的基本使用
"""
from pyecharts.charts import Map
from pyecharts.options import VisualMapOpts
# 准备地图对象
map = Map()
# 准备数据
data = [
("北京市", 99),
("上海市", 199),
("湖南省", 299),
("台湾省", 399),
("广东省", 499)
]
# 添加数据
map.add("测试地图", data, "china")
# 设置全局选项
map.set_global_opts(
visualmap_opts=VisualMapOpts(
is_show=True, # 是否显示
is_piecewise=True, # 是否开启手动校准备范围
#设置在不同范围的颜色显示
pieces=[
{'min': 1, 'max': 99, 'label': '1-99', 'color': '#CCFFFF'},
{'min': 100, 'max': 199, 'label': '100-199', 'color': '#FF6666'},
{'min': 200, 'max': 299, 'label': '200-299', 'color': '#990033'},
{'min': 300, 'max': 399, 'label': '300-399', 'color': '#FF9966'},
{'min': 400, 'max': 499, 'label': '400-499', 'color': '#CC3333'}
]
)
)
# 绘图
map.render()
"""
演示第三个图表:GDP动态柱状图开发
"""
from pyecharts.charts import Bar,Timeline
from pyecharts.options import *
from pyecharts.globals import ThemeType
# 读取数据
f = open('D:/疫情折线图/GDP/GDP数据.csv', 'r', encoding='UTF-8')
data_lines = f.readlines()
# 删除第一条数据
data_lines.pop(0)
# 将数据转换为字典存储,格式为:
# {年份:[[国家,gdp],[国家,gdp],......],年份:[[国家,gdp],[国家,gdp],......]}
# 先定义一个字典对象
data_dict = {}
for line in data_lines:
year = int(line.split(",")[0]) # 年份
country = line.split(",")[1] # 国家
rate = float(line.split(",")[2]) # GDP(可将科学计数法变为正常的数字)
# 判断是否是否已经有指定key
# if year in data_dict:
# data_dict[year].append([country, rate])
# else:
# data_dict[year] = [[country, rate]]
try:
data_dict[year].append([country, rate])
except KeyError:
# data_dict[year] = []
# data_dict[year].append([country,rate])
data_dict[year] = [[country, rate]]
# print(data_dict)
# 创建一个时间线对象
timeline = Timeline(
#主题设置
{"theme":ThemeType.LIGHT}
)
# 排序年份
sorted_year_list = sorted(data_dict.keys(), reverse=False) # 设置升序
for year in sorted_year_list:
data_dict[year].sort(key=lambda element: element[1], reverse=True)
# 取出本年份前5名国家
year_data = data_dict[year][:5]
# 准备数据
x_data = []
y_data = []
for country_gdp in data_dict[year]:
x_data.append(country_gdp[0])
y_data.append(country_gdp[1] )
# 构建柱状图
bar = Bar()
#为了满足效果(反转后,GDP最大的在最上)
x_data.reverse()
y_data.reverse()
# 添加数据
bar.add_xaxis(x_data)
bar.add_yaxis("GDP(亿)", y_data, label_opts=LabelOpts(position="right"))
#反转xy轴
bar.reversal_axis()
#设置每一年的图表标题
bar.set_global_opts(
title_opts=TitleOpts(title = f"{year}全球前5的GDP数据")
)
timeline.add(bar,str(year))
#for循环每一年的数据,基于每一年的数据,创建每一年的bar对象
#在for中,将每一年的bar对象添加到时间线中
#设置时间线自动播放
timeline.add_schema(
play_interval=1000,
is_timeline_show=True,
is_auto_play=True,
is_loop_play=False
)
#通过时间线绘图
timeline.render("GDP动态柱状图.html")
对象
初始对象
理解使用对象完成数据组织的思路
作用:组织数据
对比生活中和程序中:
-
设计表格,称之为:设计类(class)
-
生产表格,称之为:创建对象、
-
填写表格,称之为:对象属性赋值
类的定义和使用
#类的定义和使用
class 类名称:
类的属性
类的行为
#class是关键字,表示要定义类了
#类的属性,既定义在类中的变量(成员变量)
#类的行为,既定义在类中的函数(成员方法)
#创建类对象的语法
对象 = 类名称()
# 1.设计一个类(类比生活中:设计一张登记表)
class Student:
name = None # 记录学生姓名
gender = None # 性别
nationality = None # 国籍
native_place = None # 籍贯
age = None # 年龄
def say(self):
print(f'我是{self.name},这是计划的一部分')
# 2.创建一个对象(类比生活中:打印一张登记表)
stu1 = Student()
# 3,对象属性进行赋值(类比生活中:填写表单)
stu1.name = "罗辑"
stu1.gender = "男"
stu1.nationality = "中国"
stu1.native_place = "北京省"
stu1.age = 31
# 4.获取对象中记录的信息
print(stu1.name)
print(stu1.gender)
print(stu1.nationality)
print(stu1.native_place)
print(stu1.age)
Student.say(stu1)#类调用方法
stu1.say()#对象调用方法(self会自动传入)
成员方法
在类中函数
#在类中
def 方法名(self,形参1,......,形参N):#self必须在参数列表中出现,对象调用传参时可以忽略
方法体
self关键字
是成员方法定义的时候,必须填写的(self出现在形参列表中,但是不占用参数位置,无需理会)
- 它用来表示类对象自身的意思
- 当我们使用类对象调用方法的是,self会自动被python传入
- 在方法内部,想要访问类的成员变量,必须使用self
类和对象
现实世界的事物由属性和行为组成,类也有属性和行为
使用程序中的类,可以完美的描述现实世界的事物
面向对象编程:
类是一种程序中的"设计图纸",需要基于图纸生产实体(对象),才能正常工作
对象是基于图纸生产的具体实体
总结:设计类、基于类创建对象、由对象做具体的工作(使用对象进行编程)
构造方法_ _init _ _()(属性的赋值)
使用_ _init _ _(),称之为构造方法
可以实现:
- 在创建类对象(构造类)的时候,构造方法会自动执行。
- 在创建类对象(构造类)的时候,将传入参数自动传递给_ _ init_ _(构造方法)使用。
"""
演示构造方法
"""
class Student:
#构造方法的参数中以经包含的属性(成员变量)可以省略
# name = None
# age = None
# tel = None
#__init__构造方法,一样需要使用self关键字
def __init__(self,name,age,tel):
self.name = name
self.age = age
self.tel = tel
print("创建了一个类对象")
stu1 = Student("汪淼",35,123456)
print(f'{stu1.name},{stu1.age},{stu1.tel}')
魔术方法(常用几种)
魔术方法:前后用_ _包裹的python内置方法
常用的几种
__str__
:字符串方法
print(对象)得到的是内存地址,可以通过_ _ str_ _方法,控制类转换为一个我们指定的字符串输出
__lt__
:小于、大于符号比较
__le__
:小于等于、大于等于符号比较
__eq__
:==符号比较
没有_ _ eq_ _方法,两个对象比较的是内存地址
class Student:
def __init__(self, name, age):
self.name = name
self.age = age
# __str__魔术方法
# 通过__str__控制类转换为指定字符串的行为
def __str__(self):
return f"Student对象,name={self.name},age={self.age}"
# __it__魔术方法
def __lt__(self, other):
return self.age < other.age
# __le__魔术方法
def __le__(self, other):
return self.age <= other.age
# __eq__魔术方法
def __eq__(self, other):
return self.age == other.age
stu = Student("周杏轮", 11)
# print(student) #结果:<__main__.Student object at 0x0000025FCC307C70>
# print(str(student)) #结果:<__main__.Student object at 0x0000025FCC307C70>
print(stu) # 转化后结果:Student对象,name=周杏轮,age=11
print(str(stu)) # 转化后结果:Student对象,name=周杏轮,age=11
stu1 = Student("01", 12)
stu2 = Student("02", 13)
stu3 = Student("03", 12)
print(stu1 < stu2) # True
print(stu1 > stu2) # False
print(stu1 <= stu2) # True
print(stu1 >= stu2) # False
print(stu1 <= stu3) # True
print(stu1 >= stu3) # True
#没有__eq__方法,俩个对象对比的是内存地址
print(stu1 == stu2) # False
print(stu1 == stu3) # True
封装
面向对象编程,是许多编程语言都支持的一种编程思想
简单理解是:基于模板(类)去创建实体(对象),使用对象完成功能开发
面向对象包含3大主要特征:封装、继承、多态
封装:将现实世界事物在类中描述为属性和方法,即为封装
- (从而完成程序对现实世界事物的描述)
继承
多态
私有成员(变量、方法)
现实事物有对使用者不公开的属性和行为,作为现实事物在程序中映射的类,相应的就需要定义私有成员
(私有的属性和方法只允许给这个事物本身使用的,而不是用户,同样的在程序中,类中的其他成员(方法\变量)可以访问这些私有的属性和方法)
私有成员的访问限制:
- 类对象无法访问私有成员
- 类中的其他成员可以访问私有成员(只能内部使用)
作用:在类中提供仅供内部使用的属性和方法、而不对外开放(类对象无法使用)
#定义私有成员变量和私有成员方法,只需要以_ _开头
# 定义一个类,内含私有成员变量和私有成员方法
class Phone:
__current_voltage = 0.5 # 当前手机运行电压
ad = __current_voltage/0.5 #类中的其他成员可以访问私有成员
def __keep_single_core(self):
print("让cpu以单核模式运行")
#类中的其他成员可以访问私有成员
def call_by_5g(self):
if self.__current_voltage >= 1:
print("5g通话已开启")
else:
self.__keep_single_core()
print("电量不足,无法使用5g通话,并已设置单核运行进行省电")
phone = Phone()
#对象无法访问类的私有成员
# phone.__keep_single_core()
# AttributeError: 'Phone' object has no attribute '__keep_single_core'. Did you mean: '_Phone__keep_single_core'?
# print(phone.__current_voltage)
# AttributeError: 'Phone' object has no attribute '__current_voltage'. Did you mean: '_Phone__current_voltage'?
phone.call_by_5g()
print(phone.ad)
继承
基础语法
#单继承
class 类名(父类名):
类内容体
#多继承
class 类名(父类1名,父类2名,...,父类N):
类内容
子类构建的类对象,可以
有自己的成员变量和成员方法
使用父类的成员变量和成员方法
单继承和多继承
单继承:一个类继承一个类
多继承:一个类继承多个类,按照顺序从左向右依次继承
多继承中,如果父类有同名方法或属性,先继承的优先级高于后继承(从左到右)既:先继承的保留,后继承的被覆盖
pass关键字
pass是一个占位语句,用来保证函数(方法)或类定义的完整性,表示无内容,空的意思
class my_phone(NFCReader,Phone,RemoteControl):
#pass关键字:补全语法
pass
#没有什么新成员需要补充,有需要保证类的完整性
复写父类方法
复写:在子类中重新定义同名成员即可覆写
调用同名父类成员:
-
方法1:调用父类成员
- 使用成员变量:父类名.成员变量
- 使用成员方法:父类名.成员方法(self)
-
方法2:使用super()调用父类成员
- 使用成员变量:super().成员变量
- 使用成员方法:super().成员方法()
类型注解
在代码涉及数据交互的地方(帮助第三方IDE工具,如PyCharm)提供数据类型的注解,协助做代码提示
开发者自身对变量进行类型的备注
(只是个提示性的备注,不是决定性的,不会影响到程序的运行)(注解错代码也不会报错)
(一般,无法直接看出变量类型时会添加变量的类型详解)
通过ctrl+p查看
'''语法1:变量:类型'''
#基础数据类型注解
var_1:int 10
var_2:float=3.1415926
var_3:bool True
var_4:str "itheima"
#类对象类型注解
class student:
pass
stu:student = student()
#基础容器类型注解
my_1ist:list=[1,2,3]
my_tuple:tuple (1,2,3)
my_set:set {1,2,3}
my_dict:dict {"itheima":666}
my_str:str "itheima"
#容器类型详细注解
my_list:list[int][1,2,3]
my_tuple:tuple[str,int,bool]("itheima",666,True)
my_set:set[int]{1,2,3}
my_dict:dict[str,int]={"itheima":666}
#注意:
#元组类型设置类型详细注解,需要将每一个元素都标记出来
#字典类型设置类型详细注解,需要2个类型,第一个是key第二个是value
#除了使用变量:类型,这种语法做注解外,也可以在注释中进行类型注解。
'''语法2:在注释中进行类型注解'''
#语法:
#type:类型
class student:
pass
stu = student()
import random, json
var_1 = random.randint(1, 10) # type:int
var_2 = json.loads(data) # type:dict[str,int]
def func():
return stu
var_3 = func() # type:student
'''函数和方法的形参类型注解语法'''
def 函数方法名(形参名:类型, 形参名:类型,......):
pass
def 函数方法名(形参名:类型, 形参名:类型,......) -> 函数返回值类型:
pass
#注意返回值类型注解的符号使用:->
def add(x:int, y:int):
return x + y
def add(x:int, y:int) -> int:
return x + y
def func(data:list) -> NoneType:
pass
Union类型(联合类型)
使用Union[类型,......,类型]
可以定义联合类型注解
from typing import Union
my_list:list[Union[str,int]] = [1,2,"itheima","itcast"]
my_dict:dict[str, Union[str,int]={"name":"周杰轮","age":31}
def func(data: Union[int, str]) -> Union[int, str]:
pass
#func()
多态
指的是,多个状态,即完成某个同样的行为(函数),使用不同的对象,得到不同的状态
多态指的是,同一个行为,使用不同的对象获得不同的状态。
如,定义函数(方法),通过类型注解声明需要父类对象,实际传入子类对象进行
工作,从而获得不同的工作状态
class Animal:
def speak(self):
pass
class Dog(Animal):
def speak(self):
print("汪汪汪")
class Cat(Animal):
def speak(self):
print("喵喵喵")
抽象类
抽象类:包含抽象方法的类
抽象方法:方法体没有具体实现的方法(pass)
抽象类就好比定义了一个标准,包含了一些抽象方法,要求子类必须实现
抽象类多用于做顶层设计(设计标准)(而不是拿来直接使用的)用子类继承抽象父类并实现抽象方法(实现标准)(以便子类做具体实现)
注意:对子类是一种软性约束,要求子类必须复写(实现)父类的一些方法,并且配合多态去使用,获得不同的工作状态
配合多态,完成
- 抽象的父类设计(设计标准)
- 具体的子类实现(实现标准)
class Animal:
def speak(self):
pass
class Dog(Animal):
def speak(self):
print("汪汪汪")
class cat(Animal):
def speak(self):
print("喵喵喵")
"""
这种设计的含义是:
父类用来确定有哪些方法
具体的方法实现,由子类自行决定
这种写法,就叫做抽象类(也可以称之为接口)
抽象类:含有抽象方法的类称之为抽象类
抽象方法:方法体是空实现的(pass)称之为抽象方法
"""