文章目录
- 第一章 基础语法
- 1.字面量
- 2.注释
- 3.变量
- 4.数据类型
- 5.数据类型转换
- 6.标识符
- 7.运算符
- 8.字符串拓展
- 1.字符串的三种定义方式
- 2.字符串拼接(不用)
- 3.字符串格式化(了解)
- 4.格式化的精度控制
- 5.字符串格式化2(常用)
- 6.对表达式格式化
- 小练习
- 9.数据输入
- 10.python中定义字符串前面加b、u、r的含义
- 第二章 判断语句
- 1.布尔类型
- 2.if语句基本格式
- 3.if else 语句
- 4.if elif else语句
- 5.判断语句的嵌套
- 第三章 循环语句
- 1.while循环
- 1.基本语法
- 2.基础案例
- 3.嵌套应用
- 4.嵌套案例
- 2.for 循环
- 1.for循环的基本语法
- 2.range语句
- 3.变量作用域
- 4.for循环的嵌套应用
- 5.循环中断:break ,continue
- 第四章 函数
- 1.函数介绍
- 2.函数定义
- 3.函数参数
- 4.函数返回值
- None类型
- 5.函数说明文档
- 6.函数嵌套调用
- 7.变量作用域
- 1.局部变量
- 2.全局变量
- global关键字
- 第五章函数进阶
- 1.函数的多返回值
- 2.函数的多种传参方式
- 3.匿名函数
- 1.函数作为参数传递
- 2.lambda匿名函数
- 第六章数据容器
- 1.初识数据容器
- 2.数据容器:list(列表)
- 1.列表的定义
- 2.列表的下标索引
- 3.列表的常用操作(增删改查)
- 3.1列表的查询功能
- 3.2列表的修改功能(方法):
- 插入元素:
- 追加元素:
- 删除元素
- 总览
- 综合练习
- 4.list(列表)的遍历
- while循环
- for循环
- 练习案例
- 3.数据容器:tuple(元组)
- 1.元组的定义
- 2.元组的操作
- 3.元组的特点
- 练习案例
- 4.数据容器:str(字符串)
- 1.字符串的下标(索引)
- 2.字符串的常用操作
- 1.查找特定字符串的下标索引值
- 2.字符串的替换
- 3.字符串的分割
- 4.字符串的规整操作
- 5.统计字符串中某字符串的出现次数
- 6.统计字符串的长度
- 字符串常用操作汇总
- 5.数据容器(序列)的切片
- 6.数据容器:set(集合)
- 1.集合的特点
- 2.集合的定义
- 3.集合的常见操作
- 集合常用功能总结
- 综合练习
- 7.数据容器:dict(字典、映射)
- 1.字典的含义
- 2.字典的定义
- 3.字典的常用操作
- 总结
- 练习题
- 数据容器对比
- 数据容器通用操作
- 拓展:字符串比大小
- 第七章 文件操作
- 1.文件的编码
- 2. 文件的读取
- open()打开函数
- read()方法:
- close() 关闭文件对象
- with open 语法
- 3.文件的写入
- 4.文件的追加
- 5.文件备份案例
- 第八章 Pyhton异常、模块、包
- 1.异常
- 2.异常捕获
- 3.异常的传递
- 4.python模块
- 1.模块导入方式
- 2.as定义别名
- 5.自定义模块
- 6.测试模块
- 7.__ all __
- 8.自定义包
- 9.安装第三方包
第一章 基础语法
1.字面量
字面量:在代码中,被写下来的的固定的值,称之为字面量
类型 | 描述 | 说明 |
---|---|---|
数字(Number) | 支持整数(int)浮点数(float)复数(complex)布尔(bool) | 整数(int),如:10、-10 |
浮点数(float),如:13.14、-13.14 | ||
复数(complex),如:4+3j,以j结尾表示复数 | ||
布尔(bool)表达现实生活中的逻辑,即真和假,True表示真,False表示假。True本质上是一个数字记作1,False记作0 | ||
字符串(String) | 描述文本的一种数据类型 | 字符串(string)由任意数量的字符组成 |
列表(List) | 有序的可变序列 | Python中使用最频繁的数据类型,可有序记录一堆数据 |
元组(Tuple) | 有序的不可变序列 | 可有序记录一堆不可变的Python数据集合 |
集合(Set) | 无序不重复集合 | 可无序记录一堆不重复的Python数据集合 |
字典(Dictionary) | 无序Key-Value集合 | 可无序记录一堆Key-Value型的Python数据集合 |
字符串(string),又称文本,是由任意数量的字符如中文、英文、各类符号、数字等组成。所以叫做字符的串
- print(10),输出整数10
- print(13.14),输出浮点数13.14
- print(“我爱编程”),输出字符串:我爱编程
2.注释
注释:在程序代码中对程序代码进行解释说明的文字。
作用:注释不是程序,不能被执行,只是对程序代码进行解释说明,让别人可以看懂程序代码的作用,能够大大增强程序的可读性。
-
单行注释:以 #开头,#右边 的所有文字当作说明,而不是真正要执行的程序,起辅助说明作用
#我是单行注释 print("Hello World") 运行结果: Hello World
-
多行注释: 以 一对三个双引号 引起来 ( “”“ 注释内容 ”“” )来解释说明一段代码的作用使用方法
""" 我是多行注释 我可以写多行 """ print("hello,world") 运行结果: hello,world
3.变量
变量:在程序运行时,能储存计算结果或能表示值的抽象概念。
简单的说,变量就是在程序运行时,记录数据用的
- 变量,从名字中可以看出,表示“量”是可变的。所以,变量的特征就是,变量存储的数据,是可以发生改变的。
- 变量的目的是存储运行过程的数据。存储的目的是为了:重复使用
#将数字10存到data变量里
data = 10
4.数据类型
数据是有类型的。目前在入门阶段,我们主要接触如下三类数据类型:
类型 | 描述 | 说明 |
---|---|---|
string | 字符串类型 | 用引号引起来的数据都是字符串 |
int | 整型(有符号) | 数字类型,存放整数 如 -1,10, 0 等 |
float | 浮点型(有符号) | 数字类型,存放小数 如 -3.14, 6.66 |
那么,问题来了,如何验证数据的类型呢?
我们可以通过type()语句来得到数据的类型:
语法:type(被查看类型的数据)
示例代码:
#1.用print语句,直接输出类型信息
print(type("这是字符串"))
print(type(666))
print(type(3.14))
#运行结果
<class 'str'>
<class 'int'>
<class 'float'>
5.数据类型转换
数据类型之间,在特定的场景下,是可以相互转换的,如字符串转数字、数字转字符串等
跟C语言里面的强制转换很像
数据类型转换,将会是我们以后经常使用的功能。
如:
- 从文件中读取的数字,默认是字符串,我们需要转换成数字类型
- 后续学习的input()语句,默认结果是字符串,若需要数字也需要转换
- 将数字转换成字符串用以写出到外部系统等等
常见的转换语句
语句(函数) | 说明 |
---|---|
int(x) | 将x转换为一个整数 |
float(x) | 将x转换为一个浮点数 |
str(x) | 将对象 x 转换为字符串 |
同前面学习的type()语句一样,这三个语句,都是带有结果的(返回值)
我们可以用print直接输出
或用变量存储结果值
-
任何类型,都可以通过str(),转换成字符串
-
字符串内必须真的是数字,才可以将字符串转换为数字
-
浮点数转整数会丢失精度,也就是小数部分
6.标识符
在Python程序中,我们可以给很多东西起名字,比如:
- 变量的名字
- 方法的名字
- 类的名字,等等
这些名字,我们把它统一的称之为标识符,用来做内容的标识。
所以,标识符:是用户在编程的时候所使用的一系列名字,用于给变量、类、方法等命名。
标识符命名规则中,只允许出现:
- 英文
- 中文(不推荐使用中文)
- 数字(数字不可以开头)
- 下划线(_)
-
区分大小写
-
不可使用关键字
变量的命名规范
- 见名知意
- 下划线命名法
- 英文字母全小写
7.运算符
a = 10,b = 20
运算符 | 描述 | 实例 |
---|---|---|
+ | 加 | 两个对象相加 a + b 输出结果 30 |
- | 减 | 得到负数或是一个数减去另一个数 a - b 输出结果 -10 |
* | 乘 | 两个数相乘或是返回一个被重复若干次的字符串 a * b 输出结果 200 |
/ | 除 | b / a 输出结果 2 |
// | 取整除 | 返回商的整数部分 9//2 输出结果 4 , 9.0//2.0 输出结果 4.0 |
% | 取余 | 返回除法的余数 b % a 输出结果 0 |
** | 指数 | a**b 为10的20次方, 输出结果 100000000000000000000 |
赋值运算符
运算符 | 描述 | 实例 |
---|---|---|
= | 赋值运算符 | 把 = 号右边的结果 赋给 左边的变量,如 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 |
8.字符串拓展
1.字符串的三种定义方式
- 单引号方式 name = ‘张三’
- 双引号方式 name = “张三”
- 三引号方式 name = ”’ 张三 “‘
字符串的引号嵌套
- 单引号定义法,可以内含双引号
- 双引号定义法,可以内含单引号
- 可以使用转移字符(\)来将引号解除效用,变成普通字符串
print(“ I\ ‘m ”)
2.字符串拼接(不用)
- 变量过多,拼接起来实在是太麻烦了
- 字符串无法和数字或其它类型完成拼接。
字符串无法和非字符串变量进行拼接。因为类型不一致,无法接上
3.字符串格式化(了解)
name = "小明"
message = "大家好,我叫%s"%name
print(message)
#运行结果:
大家好,我叫小明
其中的,%s
-
% 表示:我要占位
-
s 表示:将变量变成字符串放入占位的地方
所以,综合起来的意思就是:我先占个位置,等一会有个变量过来,我把它变成字符串放到占位的位置
Python中,其实支持非常多的数据类型占位
最常用的是如下三类:
格式符号 | 转化 |
---|---|
%s | 将内容转换成字符串,放入占位位置 |
%d | 将内容转换成整数,放入占位位置 |
%f | 将内容转换成浮点型,放入占位位置 |
多个变量占位,变量要用括号括起来,并按照占位的顺序填入
str ="字符串abc"
int = 10
float = 3.14
print("这是字符串%s,这是整型数%d,这是浮点数%f"%(str,int,float))
#运行结果:
这是字符串字符串abc,这是整型数10,这是浮点数3.140000
4.格式化的精度控制
我们可以使用辅助符号"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)
-
%.2f:表示不限制宽度,只设置小数点精度为2,(如11.345设置%.2f后,结果是11.35)
5.字符串格式化2(常用)
语法:f”{变量} {变量}”的方式进行快速格式化
这种写法不做精度控制,也不理会类型。适用于快速格式化字符串(可以说是原样输出了)
6.对表达式格式化
表达式:一条具有明确执行结果的代码语句
如:
1 + 1、5 * 2,就是表达式,因为有具体的结果,结果是一个数字
又或者,常见的变量定义:
name = “张三” age = 11 + 11
等号右侧的都是表达式呢,因为它们有具体的结果,结果赋值给了等号左侧的变量。
在无需使用变量进行数据存储的时候,可以直接格式化表达式,简化代码哦
至此,已经学会了两种字符串格式化的方法
-
f"{表达式}"
-
“%s%d%f” % (表达式、表达式、表达式)
小练习
name,公司名
stock_price,当前股价
stock_code,股票代码
stock_price_daily_growth_factor,股票每日增长系数,浮点数类型,比如1.2
growth_days,增长天数
name = "橘猫"
stock_price = 19.99
stock_code = 003032
stock_price_daily_growth_factor = 1.2
growth_days = 7
price = stock_price*stock_price_daily_growth_factor**growth_days
print(f"公司{name},股票代码{stock_code},当前股价{stock_price}")
print("每日增长系数%d,经过%d天的增长后,股价达到了:%d"%(stock_price_daily_growth_factor,growth_days,price))
9.数据输入
关键词:input()函数
- input()语句的功能是,获取键盘输入的数据
- 可以使用:input(提示信息),用以在使用者输入内容之前显示提示信息。
- 要注意,无论键盘输入什么类型的数据,获取到的数据永远都是字符串类型
input不管你输入的什么数据类型,它输出的统一都是字符串,所以如果我们需要别的类型时,需要进行强转
10.python中定义字符串前面加b、u、r的含义
1.1 基本格式
str = b"xxxx"
str = u"xxxx"
str = r"xxxx"
str = f"xxxx"
1.2 描述及对比
(1)字符串前面加b表示后面字符串是bytes类型,以便服务器或浏览器识别bytes数据类型;
(2)字符串前面加u表示以Unicode格式进行编码,往往用来解决中文乱码问题,一般英文字符串基本都可以正常解析,而中文字符串必须表明用什么编码,否则就会乱码。
(3)字符串前面加r表示以raw string格式进行定义,可以防止字符串规避反斜杠\的转义。
例如:
str1 = "\thello"
str2 = r"\thello"
print("str1 =",str1)
print("str2 =",str2)
输出
str1 = hello
str2 = \thello
(4)字符串前面加f表示能支持大括号里面的表达式。
例如:
python = "蟒蛇"
print("我要好好学{python}!")
print(f"我要好好学{python} !")
输出
我要好好学{python} !
我要好好学蟒蛇 !
(5)在python3中,bytes和str的相互转换
str.encode('utf-8')
bytes.decode('utf-8')
例如:
print("你好".encode(encoding="utf-8"))
输出b’\xe4\xbd\xa0\xe5\xa5\xbd’
print(b'\xe4\xbd\xa0\xe5\xa5\xbd'.decode())
输出你好
往往用于图片、音视频等文件的读写时,可用bytes数据。
第二章 判断语句
1.布尔类型
布尔类型的字面量:
- True 表示真(是、肯定)
- False 表示假 (否、否定)
定义变量存储布尔类型数据:变量名称 = 布尔类型字面量
布尔类型不仅可以自行定义,,同时也可以通过计算的来。
也就是使用比较运算符进行比较运算得到布尔类型的结果。
运算符 | 描述 | 示例 |
---|---|---|
== | 判断内容是否相等,满足为True,不满足为False | 如a=3,b=3,则(a == b) 为 True |
!= | 判断内容是否不相等,满足为True,不满足为False | 如a=1,b=3,则(a != b) 为 True |
> | 判断运算符左侧内容是否大于右侧满足为True,不满足为False | 如a=7,b=3,则(a > b) 为 True |
< | 判断运算符左侧内容是否小于右侧满足为True,不满足为False | 如a=3,b=7,则(a < b) 为 True |
>= | 判断运算符左侧内容是否大于等于右侧满足为True,不满足为False | 如a=3,b=3,则(a >= b) 为 True |
<= | 判断运算符左侧内容是否小于等于右侧满足为True,不满足为False | 如a=3,b=3,则(a <= b) 为 True |
2.if语句基本格式
if 要判断的条件:
条件成立时,要做的事
#1.定义变量
age = 30
#2.进行判断
if age >= 18:
print("我已经成年了")
判断语句的结果,必须是布尔类型 True 或 False
True会执行if内的代码语句
False则不会执行
3.if else 语句
if 条件1:
条件1满足应做的事情
条件1满足应做的事情
......
else:
不满足条件时要做的事情1
不满足条件时要做的事情2
else后,不需要判断条件
和if的代码块一样,else的代码块同样需要4个空格作为缩进
4.if elif else语句
elif 将elseif缩写了
if 条件1:
条件1满足应做的事情
条件1满足应做的事情
......
elif 条件2:
条件2满足应做的事情
条件2满足应做的事情
......
else:
使用if elif else的注意点有:
- elif可以写多个
- 判断是互斥且有序的,上一个满足后面的就不会判断了
- 可以在条件判断中,直接写input语句,节省代码量
5.判断语句的嵌套
字面意思就是一个if语句里面又套了一个if语句
基础语法:
if 条件1:
要做什么事
if 条件2:
要做什么事
嵌套的关键点,在于:空格缩进
通过空格缩进,来决定语句之间的:层次关系
如图:
- 判断有2层
- 当外层if满足条件(图中编号1)时,才会执行内层if判断(图中编号2)
- 当外层if(编号1)不满足,直接执行外层esle
第三章 循环语句
1.while循环
1.基本语法
while 条件:
执行的事情1
执行的事情2
执行的事情3
#示例代码
i = 0
while i<100:
print("hello,world")
i+=1
-
while的条件需得到布尔类型,True表示继续循环,False表示结束循环
-
需要设置循环终止的条件,如i += 1配合 i < 100,就能确保100次后停止,否则将无限循环
-
空格缩进和if判断一样,都需要设置
2.基础案例
设置一个范围1-100的随机整数变量,通过while循环,配合input语句,判断输入的数字是否等于随机数
- 无限次机会,直到猜中为止
- 每一次猜不中,会提示大了或小了
- 猜完数字后,提示猜了几次
提示:
无限次机会,终止条件不适合用数字累加来判断,可以考虑布尔类型本身(True or False)
需要提示几次猜中,就需要提供数字累加功能
"""
演示while循环的基础案例 - 猜数字
"""
# 获取范围在1-100的随机数字
import random
num = random.randint(1, 100)
# 定义一个变量,记录总共猜测了多少次
count = 0
# 通过一个布尔类型的变量,做循环是否继续的标记
flag = True
while flag:
guess_num = int(input("请输入你猜测的数字:"))
count += 1
if guess_num == num:
print("猜中了")
# 设置为False就是终止循环的条件
flag = False
else:
if guess_num > num:
print("你猜的大了")
else:
print("你猜的小了")
print(f"你总共猜测了{count}次")
3.嵌套应用
while 条件1:
执行的事情1
执行的事情2
执行的事情3
while 条件2:
执行的事情1
执行的事情2
执行的事情3
嵌套循环的使用难点:循环条件的控制,层次越多越复杂,需要细心+耐心
"""
演示while循环的嵌套使用
嵌套循环需要注意的地方:
1.注意条件的控制,避免无限循环
2.多层嵌套,主要空格缩进来确定层次关系
"""
# 外层:表白100天的控制
# 内层:每天的表白都送10只玫瑰花的控制
i = 1
while i <= 100:
print(f"今天是第{i}天,准备表白.....")
# 内层循环的控制变量
j = 1
while j <= 10:
print(f"送给小美第{j}只玫瑰花")
j += 1
print("小美,我喜欢你")
i += 1
print(f"坚持到第{i - 1}天,表白成功")
补充知识:
end = ‘ ’
- 默认print语句输出内容会自动换行
- 在print语句中,加上 end=’’ 即可输出不换行
制表符\t
在字符串中,有一个特殊符号:\t,效果等同于在键盘上按下:tab键。
它可以让我们的多行字符串进行对齐。
4.嵌套案例
"""
演示使用while的嵌套循环
打印输出九九乘法表
"""
# 定义外层循环的控制变量
i = 1
while i <= 9:
# 定义内层循环的控制变量
j = 1
while j <= i:
# 内层循环的print语句,不要换行,通过\t制表符进行对齐
print(f"{j} * {i} = {j * i}\t", end='')
j += 1
i += 1
print() # print空内容,就是输出一个换行
2.for 循环
1.for循环的基本语法
- while循环的循环条件是自定义的,自行控制循环条件
- for循环是一种”轮询”机制,是对一批内容进行”逐个处理”
- 同while循环不同,for循环是无法定义循环条件的。只能从被处理的数据集中,依次取出内容进行处理。所以,理论上讲,Python的for循环无法构建无限循环(被处理的数据集不可能无限大)
#从待处理数据集中:逐个取出数据,赋值给临时变量
语法:
for 临时变量 in 待处理数据集:
循环满足条件时执行的代码
# 定义字符串name
name = ”itheima”
# for循环处理字符串
for x in name:
print(x)
练习题
"""
演示for循环的练习题:数一数有几个a
"""
# 统计如下字符串中,有多少个字母a
name = "itheima is a brand of itcast"
# 定义一个变量,用来统计有多少个a
count = 0
# for 循环统计
# for 临时变量 in 被统计的数据:
for x in name:
if x == "a":
count += 1
print(f"被统计的字符串中有{count}个a")
2.range语句
for 临时变量 in 待处理数据集(可迭代对象):
循环满足条件时执行的代码
语法中的:待处理数据集,严格来说,称之为:可迭代类型
可迭代类型指,其内容可以一个个依次取出的一种类型,包括:
- 字符串
- 列表
- 元组等
目前我们只学习了字符串类型,其余类型在后续章节会详细学习它们
for循环语句,本质上是遍历:可迭代对象。
语法1:
range(num)
获取一个从0开始,到num结束的数字序列(不含num本身)左闭右开
如range(5)取得的数据是:[0, 1, 2, 3, 4]
语法2:
range(num1, num2)
获得一个从num1开始,到num2结束的数字序列(不含num2本身)
如,range(5, 10)取得的数据是:[5, 6, 7, 8, 9]
语法3:
range(num1, num2, step)
获得一个从num1开始,到num2结束的数字序列(不含num2本身)
数字之间的步长,以step为准(step默认为1)
如,range(5, 10, 2)取得的数据是:[5, 7, 9]
for i in range(5):
print(i)
输出:
0
1
2
3
4
3.变量作用域
如图代码,思考一下:红框中的print语句,能否访问到变量 i ?
规范上:不允许
实际上:可以
回看for循环的语法,我们会发现,将从数据集(序列)中取出的数据赋值给:临时变量
for 临时变量 in 待处理数据集(可迭代对象):
循环满足条件时执行的代码
临时变量,在编程规范上,作用范围(作用域),只限定在for循环内部
如果在for循环外部访问临时变量:
- 实际上是可以访问到的
- 在编程规范上,是不允许、不建议这么做的
如果实在需要在循环外访问循环内的临时变量,可以在循环外预先定义(一般不要这样做,因为i变量的取值如下图所示,并不能改变多少)
如图,每一次循环的时候,都会将取出的值赋予i变量。
- 由于i变量是在循环之前(外)定义的
- 在循环外访问i变量是合理的、允许的
4.for循环的嵌套应用
"""
演示嵌套应用for循环
"""
# 坚持表白100天,每天都送10朵花
# range
i = 0
for i in range(1, 101):
print(f"今天是向小美表白的第{i}天,加油坚持。")
# 写内层的循环了
for j in range(1, 11):
print(f"给小美送的第{j}朵玫瑰花")
print("小美我喜欢你")
print(f"第{i}天,表白成功")
5.循环中断:break ,continue
continue
- 暂时跳过某次循环,直接进行下一次
break
- 提前退出循环,不再继续
-
continue和break,在for和while循环中作用一致
-
在嵌套循环中,只能作用在所在的循环上,无法对上层循环起作用
#每天送5朵花,送10天
i = 1
j = 1
while i<=10:
print(f"今天是送花的第{i}天")
i+=1
while j<=5:
print(f"这是送的第{j}朵花")
j+=1
if j==3:
break #如果是break,到达3之后,后面全部跳过
#如果是continue,只会在等于3的时候跳,后面的照样执行
第四章 函数
1.函数介绍
函数:是组织好的,可重复使用的,用来实现特定功能的代码段。
我们使用过的:input()、print()、str()、int()等都是Python的内置函数
提问: 为什么随时都可以使用len()统计长度?
因为,len()是Python内置的函数:
- 是提前写好的
- 可以重复使用
- 实现统计长度这一特定功能的代码段
使用函数的好处是:
- 将功能封装在函数内,可供随时随地重复利用
- 提高代码的复用性,减少重复代码,提高开发效率
2.函数定义
#函数的定义
def 函数名(传入参数):
函数体
return 返回值
#函数调用
函数名(传入参数)
① 参数如不需要,可以省略(后续章节讲解)
② 返回值如不需要,可以省略(后续章节讲解)
③ 函数必须先定义后调用
"""
演示函数基础定义练习案例:自动查核酸
"""
# 定义函数
def check():
# 编写函数体输出信息
print("请出示您的健康码以及72小时核酸证明!")
# 调用函数
check()
3.函数参数
传入参数的功能是:在函数进行计算的时候,接受外部(调用时)提供的数据
"""
演示函数使用参数
"""
# 定义2数相加的函数,通过参数接收被计算的3个数字
def add(x, y, z):
result = x + y + z
print(f"{x} + {y} + {z}的计算结果是:{result}")
# 调用函数,传入被计算的3个数字
add(5, 6, 7)
函数定义中,提供的x,y和z,称之为:形式参数(形参),表示函数声明将要使用2个参数
- 参数之间使用逗号进行分隔
函数调用中,提供的5,6和7,称之为:实际参数(实参),表示函数执行时真正使用的参数值
- 传入的时候,按照顺序传入数据,使用逗号分隔
总结
- 函数定义中的参数,称之为形式参数
- 函数调用中的参数,称之为实际参数
- 函数的参数数量不限(也可以没有),使用逗号分隔开
- 传入参数的时候,要和形式参数一一对应,逗号隔开
4.函数返回值
所谓“返回值”,就是程序中函数完成事情后,最后给调用者的结果
函数体在遇到return后就结束了,所以写在return后的代码不会执行。
语法就是:通过return关键字,就能向调用者返回数据
def 函数(参数)
函数体
return 返回值
变量 = 函数(参数)
"""
改用上面的代码
"""
# 定义2数相加的函数,通过参数接收被计算的3个数字
def add(x, y, z):
result = x + y + z
return result
# 调用函数,传入被计算的3个数字
b = add(5, 6, 7)
print(b)
None类型
思考:如果函数没有使用return语句返回数据,那么函数有返回值吗?
实际上是:有的。
Python中有一个特殊的字面量:None,其类型是:<class ‘NoneType’>
无返回值的函数,实际上就是返回了:None这个字面量
None表示:空的、无实际意义的意思
函数返回的None,就表示,这个函数没有返回什么有意义的内容。
也就是返回了空的意思。
def say_hello():
print("hello...")
# return None None可以主动使用return返回,效果等同于不写return语句:
#使用变量接收这个函数的返回值
result = say_hello()
#打印返回值
print(result) #结果None
#打印返回值类型
print(type(result)) #结果<class 'NoneType'>
None类型应用场景
None作为一个特殊的字面量,用于表示:空、无意义,其有非常多的应用场景。
- 用在函数无返回值上
- 用在if判断上
在if判断中,None等同于False
一般用于在函数中主动返回None,配合if判断做相关处理
- 用于声明无内容的变量上
定义变量,但暂时不需要变量有具体值,可以用None来代替
#暂不赋予变量具体值
name = None
5.函数说明文档
函数是纯代码语言,想要理解其含义,就需要一行行的去阅读理解代码,效率比较低。
我们可以给函数添加说明文档,辅助理解函数的作用。
其实就是给函数写个注释,说明一下这个函数是干啥的
语法如下:
def add(x,y):
"""
函数说明
:param x: 形参x的说明
:param y: 形参y的说明
:return: 返回值的说明
"""
函数体
return 返回值
通过多行注释的形式,对函数进行说明解释,内容应写在函数体之前
param 用于解释参数
return 用于解释返回值
在PyCharm编写代码时,可以通过鼠标悬停,查看调用函数的说明文档
6.函数嵌套调用
所谓函数嵌套调用指的是一个函数里面又调用了另外一个函数。
如下效果:
如果函数A中,调用了另外一个函数B,那么先把函数B中的任务都执行完毕之后才会回到上次 函数A执行的位置
7.变量作用域
变量作用域指的是变量的作用范围(变量在哪里可用,在哪里不可用)
主要分为两类:局部变量和全局变量
1.局部变量
所谓局部变量是定义在函数体内部的变量,即只在函数体内部生效
变量a是定义在testA
函数内部的变量,在函数外部访问则立即报错。
局部变量的作用:在函数体内部,临时保存数据,即当函数调用完成后,则销毁局部变量
2.全局变量
所谓全局变量,指的是在函数体内、外都能生效的变量
思考:如果有一个数据,在函数A和函数B中都要使用,该怎么办?
答:将这个数据存储在一个全局变量里面
global关键字
使用 global关键字 可以在函数内部声明变量为全局变量, 如下所示:
综合小练习
-
定义一个全局变量:money,用来记录银行卡余额(默认5000000)
-
定义一个全局变量:name,用来记录客户姓名(启动程序时输入)
定义如下的函数: -
查询余额函数
-
存款函数
-
取款函数
-
主菜单函数
要求: -
程序启动后要求输入客户姓名
-
查询余额、存款、取款后都会返回主菜单
-
存款、取款后,都应显示一下当前余额
-
客户选择退出或输入错误,程序会退出,否则一直运行
"""
演示函数综合案例开发
"""
# 定义全局变量money name
money = 5000000
name = None
# 要求客户输入姓名
name = input("请输入您的姓名:")
# 定义查询函数
def query(show_header):
if show_header:
print("-------------查询余额------------")
print(f"{name},您好,您的余额剩余:{money}元")
# 定义存款函数
def saving(num):
global money # money在函数内部定义为全局变量
money += num
print("-------------存款------------")
print(f"{name},您好,您存款{num}元成功。")
# 调用query函数查询余额
query(False)
# 定义取款函数
def get_money(num):
global money
money -= num
print("-------------取款------------")
print(f"{name},您好,您取款{num}元成功。")
# 调用query函数查询余额
query(False)
# 定义主菜单函数
def main():
print("-------------主菜单------------")
print(f"{name},您好,欢迎来到银行ATM。请选择操作:")
print("查询余额\t[输入1]")
print("存款\t\t[输入2]")
print("取款\t\t[输入3]") # 通过\t制表符对齐输出
print("退出\t\t[输入4]")
return input("请输入您的选择:")
# 设置无限循环,确保程序不退出
while True:
keyboard_input = main()
if keyboard_input == "1":
query(True)
continue # 通过continue继续下一次循环,一进来就是回到了主菜单
elif keyboard_input == "2":
num = int(input("您想要存多少钱?请输入:"))
saving(num)
continue
elif keyboard_input == "3":
num = int(input("您想要取多少钱?请输入:"))
get_money(num)
continue
else:
print("程序退出啦")
break # 通过break退出循环
第五章函数进阶
1.函数的多返回值
如果一个函数要有多个返回值,该如何书写代码?
def test_return():
return 1,2
x,y = test_return() #按照返回值的顺序,写对应顺序的多个变量接收即可
print(x) #变量之间用逗号隔开,支持不同类型的数据return
print(y)
2.函数的多种传参方式
使用方式上的不同, 函数有4中常见参数使用方式:
- 位置参数(根据参数位置来传递参数)
- 关键字参数(通过“键=值”形式传递参数,可以不限参数顺序 ,可以和位置参数混用,位置参数需在前)
- 缺省参数(不传递参数值时会使用默认的参数值 默认值的参数必须定义在最后)
- 不定长参数( 位置不定长传递以*号标记一个形式参数,以元组的形式接受参数,形式参数一般命名为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 ='TOM',age = 20,gender = '男')
#可以不按照固定顺序
user_info(age = 20,name ='TOM',gender = '男')
#可以和位置参数混用,位置参数必须在前,且匹配参数顺序
user_info("小明",age = 20,gender = '男') #一般不要这样用
注意:函数调用时,如果有位置参数时,位置参数必须在关键字参数的前面,但关键字参数之间不存在先后顺序
不定长参数
不定长参数:不定长参数也叫可变参数. 用于不确定调用的时候会传递多少个参数(不传参也可以)的场景.
作用: 当调用函数时不确定参数个数时, 可以使用不定长参数
不定长参数的类型: ①位置传递 ②关键字传递
def user_info(*args): #args是固定的拼写,不可以自定义
print(args)
#('TOM')
user_info('TOM')
#('TOM',18)
user_info('TOM',18)
注意:传进的所有参数都会被args变量收集,它会根据传进参数的位置合并为一个元组(tuple),args是元组类型,这就是位置传递
缺省参数
缺省参数:缺省参数也叫默认参数,用于定义函数,为参数提供默认值,调用函数时可不传该默认参数的值(注意:所有位置参数必须出现在默认参数前,包括函数定义和调用)。
作用: 当调用函数时没有传递参数, 就会使用默认是用缺省参数对应的值.
def user_info(name,age,gender='男'): #为参数提供默认值,调用函数时可不传该默认参数的值
print(f'您的名字是{name},年龄是{age},性别是{gender}')
user_info('TOM',20)
user_info('TOM',18,'女')
关键字传递
注意: 参数是“键=值”形式的形式的情况下, 所有的“键=值”都会被kwargs接受, 同时会根据“键=值”组成字典.
def user_info(**kwargs): #kwargs是固定的拼写,不可以自定义
print(kwargs)
#('name':TOM','age':18,'id':110)
user_info(name:TOM',age:18,id:110)
3.匿名函数
1.函数作为参数传递
在前面的函数学习中,我们一直使用的函数,都是接受数据作为参数传入:
- 数字
- 字符串
- 字典、列表、元组等
其实,我们学习的函数本身,也可以作为参数传入另一个函数内。
def test_func(compute):
result = compute(1,2)
print(result)
def compute(x,y):
return x+y
test_func(compute) #结果:3
函数compute,作为参数,传入了test_func函数中使用。
-
test_func需要一个函数作为参数传入,这个函数需要接收2个数字进行计算,计算逻辑由这个被传入函数决定
-
compute函数接收2个数字对其进行计算,compute函数作为参数,传递给了test_func函数使用
-
最终,在test_func函数内部,由传入的compute函数,完成了对数字的计算操作
所以,这是一种,计算逻辑的传递,而非数据的传递。
就像上述代码那样,不仅仅是相加,相减、相除、等任何逻辑都可以自行定义并作为函数传入。
1.函数本身是可以作为参数,传入另一个函数中进行使用的。2. 将函数传入的作用在于:传入计算逻辑,而非传入数据。
2.lambda匿名函数
函数的定义中
-
def关键字可以定义带有名称的函数
-
lambda关键字,可以定义匿名函数(无名称)
- 有名称的函数,可以基于名称重复使用。
- 无名称的匿名函数,只可临时使用一次。
匿名函数定义语法:
lambda 传入参数:函数体(一行代码)
- lambda 是关键字,表示定义匿名函数
- 传入参数表示匿名函数的形式参数,如:x, y 表示接收2个形式参数
- 函数体,就是函数的执行逻辑,要注意:只能写一行,无法写多行代码
- 通过def关键字,定义一个函数,并传入,如下图:
def test_func(computer):
result = computer(1,2)
print(result)
def computer(x,y):
return x+y
test_func(computer)
#结果:3
- 也可以通过lambda关键字,传入一个一次性使用的lambda匿名函数
def test_func(computer):
result = computer(1,2)
print(result)
test_func(lambda x,y:x+y)
#结果:3
使用def和使用lambda,定义的函数功能完全一致,只是lambda关键字定义的函数是匿名的,无法二次使用
注意事项:
- 匿名函数用于临时构建一个函数,只用一次的场景匿名
- 函数的定义中,函数体只能写一行代码,如果函数体要写多行代码,不可用lambda匿名函数,应使用def定义带名函数
第六章数据容器
1.初识数据容器
学习数据容器,就是为了批量存储或批量使用多份数据
思考一个问题:如果我想要在程序中,记录5名学生的信息,如姓名。
如何做呢?
- 定义五个变量(不高级且低效)
name1 ='王丽红'
name2 ='周杰轮'
name3 ='林俊姐'
name4 ='张学油'
name5 ='刘德滑'
-
一个变量完成(优雅、高效,这就是数据容器,一个容器可以容纳多份数据)
#一个变量存多份数据,优雅实在是优雅 name_list = ['王丽红','周杰轮','林俊姐','张学油','刘德滑'] print(name_list)
注意用中括号表示,跟C语言的数组很像
Python中的数据容器:
一种可以容纳多份数据的数据类型,容纳的每一份数据称之为1个元素
每一个元素,可以是任意类型的数据,如字符串、数字、布尔等。
数据容器根据特点的不同,如:
-
是否支持重复元素
-
是否可以修改
-
是否有序,等
分为5类,分别是:
列表(list)、元组(tuple)、字符串(str)、集合(set)、字典(dict)
2.数据容器:list(列表)
1.列表的定义
基本语法:
#字面量
[元素1,元素2,元素3....]
#定义变量
变量的名称 = [元素1,元素2,元素3....]
#定义空变量
变量的名称 = []
变量的名称 = list()
列表内的每一个数据,称之为元素
- 以 [ ] 作为标识
- 列表内每一个元素之间用, 逗号隔开
元素的数据类型没有任何限制,甚至元素也可以是列表,这样就定义了嵌套列表
2.列表的下标索引
跟C语言的数组很像哦!!! 列表[下标],即可取出
- 列表中的每一个元素,都有其位置下标索引,从前向后的方向,从0开始,依次递增
我们只需要按照下标索引,即可取得对应位置的元素。
- 或者,可以反向索引,也就是从后向前:从-1开始,依次递减(-1、-2、-3…)
一般不这样用,正向的就很好
- 如果列表是嵌套的列表,同样支持下标索引(二维数组哈哈哈哈)
要注意下标索引的取值范围,超出范围无法取出元素,并且会报错
3.列表的常用操作(增删改查)
列表除了可以:
- 定义
- 使用下标索引获取值
以外,列表也提供了一系列功能:
- 插入元素
- 删除元素
- 清空列表
- 修改元素
- 统计元素个数
等等功能,这些功能我们都称之为:列表的方法
3.1列表的查询功能
跟C语言的结构体很像很像,通过 . 来引出方法里面的函数
回忆:函数是一个封装的代码单元,可以提供特定功能。
在Python中,如果将函数定义为class(类)的成员,那么函数会称之为:方法
#函数
def add(x,y)
return x+y
#方法
class Student
def add(self,x,y)
return x+y
#方法和函数功能一样, 有传入参数,有返回值,只是方法的使用格式不同:
1.函数的使用
num = add(1,2)
2.方法的使用
student = Student()
num =student.add(1,2)
查找某元素的下标
-
功能:查找指定元素在列表的下标,如果找不到,报错ValueError
-
语法:列表.index(元素)
index就是列表对象(变量)内置的方法(函数)
my_list = ["a","b","c"] print(my_list.index("b")) #结果:1
3.2列表的修改功能(方法):
修改特定位置(索引)的元素值:
一句话,直接改就行了
- 语法:列表[下标] = 值
- 可以使用如上语法,直接对指定下标(正向、反向下标均可)的值进行:重新赋值(修改)
#正向下标
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()
语法:列表.insert(下标, 元素),在指定的下标位置,插入指定的元素
my_list = [5,6,7]
my_list.insert(2,"A")
print(my_list) #结果:[5,6,"A",7]
插入的元素代替原先元素的位置,原先的元素向后移
追加元素:
函数一:append()
语法:列表.append(元素),将指定元素,追加到列表的尾部
my_list = [4,6,5]
my_list.append(4)
print(my_list) #结果:[4,5,4,4]
my_list = [4,6,5]
my_list.append([5,5,5])
print(my_list) #结果:[4,5,4,[5,5,5]]
函数二:extend()
语法:列表.extend(其它数据容器),将其它数据容器的内容取出,依次追加到列表尾部
my_list = [4,6,5]
my_list.extend([5,5,5])
print(my_list) #结果:[4,5,4,5,5,5]
删除元素
- 语法1: del 列表[下标]
- 语法2:列表.pop(下标)
my_list = [4,6,5]
#方式一
del my_list[1]
print(my_list) #结果:[4,5]
#方式二
my_list.pop(1)
print(my_list) #结果:[4,5]
删除某元素在列表中的第一个匹配项
语法:列表.remove(元素)
my_list = [4,6,5,5,3]
my_list.remove(5)
print(my_list) #结果:[4,6,5,3]
清空列表内容
语法:列表.clear()
my_list = [4,6,5,5,3]
my_list.clear()
print(my_list) #结果:[]
统计某元素在列表内的数量
语法:列表.count(元素)
my_list = [4,6,5,5,3]
print(my_list.count(5)) #结果:2
统计列表内,有多少元素
语法:len(列表)
可以得到一个int数字,表示列表内的元素数量
my_list = [4,6,5,"efs",3]
print(len(my_list)) #结果:5
总览
编号 | 使用方式 | 作用 |
---|---|---|
1 | 列表.append(元素) | 向列表中追加一个元素 |
2 | 列表.extend(容器) | 将数据容器的内容依次取出,追加到列表尾部 |
3 | 列表.insert(下标, 元素) | 在指定下标处,插入指定的元素 |
4 | del 列表[下标] | 删除列表指定下标元素 |
5 | 列表.pop(下标) | 删除列表指定下标元素 |
6 | 列表.remove(元素) | 从前向后,删除此元素第一个匹配项 |
7 | 列表.clear() | 清空列表 |
8 | 列表.count(元素) | 统计此元素在列表中出现的次数 |
9 | 列表.index(元素) | 查找指定元素在列表的下标找不到报错ValueError |
10 | len(列表) | 统计容器内有多少元素 |
学习编程,不仅仅是Python语言本身,以后根据方向,会学习更多的框架技术。
除了经常用的,大多数是记忆不下来的。
经过上述对列表的学习,可以总结出列表有如下特点:
- 可以容纳多个元素(上限为2**63-1、9223372036854775807个)
- 可以容纳不同类型的元素(混装)
- 数据是有序存储的(有下标序号)
- 允许重复数据存在
- 可以修改(增加或删除元素等)
综合练习
有一个列表,内容是:[21, 25, 21, 23, 22, 20],记录的是一批学生的年龄
请通过列表的功能(方法),对其进行
1.定义这个列表,并用变量接收它
2.追加一个数字31,到列表的尾部
3.追加一个新列表[29, 33, 30],到列表的尾部
4.取出第一个元素(应是:21)
5.取出最后一个元素(应是:30)
6.查找元素31,在列表中的下标位置
#1.定义这个列表,并用变量接收它
age = [21, 25, 21, 23, 22, 20]
#2.追加一个数字31,到列表的尾部
age.append(31)
#3.追加一个新列表[29, 33, 30],到列表的尾部
age.extend([29,33,30])
#4.取出第一个元素(应是:21)
first = age[0]
#5.取出最后一个元素(应是:30)
first = age[-1]
#6.查找元素31,在列表中的下标位置
print(age.index(31))
4.list(列表)的遍历
while循环
既然数据容器可以存储多个元素,那么,就会有需求从容器内依次取出元素进行操作。
将容器内的元素依次取出进行处理的行为,称之为:遍历、迭代。
a = 0
while a<len[列表]:
路人甲 = 列表[a]
对路人甲进行处理
a+=1
for循环
for 临时变量 in 数据容器
对临时变量进行处理
示例代码:
my_list = [1,2,3]
for i in my_list:
print(i)
结果:
1
2
3
whlie | for | |
---|---|---|
在循环控制上 | while循环可以自定循环条件,并自行控制 | for循环不可以自定循环条件,只可以一个个从容器内取出数据 |
在无限循环上 | while循环可以通过条件控制做到无限循环 | for循环理论上不可以,因为被遍历的容器容量不是无限的 |
在使用场景上 | while循环适用于任何想要循环的场景 | for循环适用于,遍历数据容器的场景或简单的固定次数循环场景 |
练习案例
定义一个列表,内容是:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
- 遍历列表,取出列表内的偶数,并存入一个新的列表对象中
- 使用while循环和for循环各操作一次
list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
list2 = []
a = 0
while a < len(list1):
if list1[a] % 2 == 0:
list2.append(list1[a])
a += 1
print(list2)
结果:
[2, 4, 6, 8, 10]
list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
list2 = []
for a in list1:
if a%2==0:
list2.append(a)
print(list2)
结果:
[2, 4, 6, 8, 10]
3.数据容器:tuple(元组)
1.元组的定义
思考:列表是可以修改的。如果想要传递的信息,不被篡改,列表就不合适了。
元组同列表一样,都是可以封装多个、不同类型的元素在内。
但最大的不同点在于:元组一旦定义完成,就不可修改
所以,当我们需要在程序内封装数据,又不希望封装的数据被篡改,那么元组就非常合适了
元组定义:定义元组使用小括号,且使用逗号隔开各个数据,数据可以是不同的数据类型。
#定义元组字面量
(元素,元素,元素.....)
# 定义元组变量
变量名称 = (元素,元素,元素.....)
#定义空元组
变量名称 =() #方式1
变量名称 =tuple() #方式2
#定义3个元素的元组
t1 = (1,"hello",True)
#定义1个元素的元组
t2 = ('hello',) #注意:必须带有逗号,否则不是元组类型
#元组也支持嵌套
t1 =((1,2,3)(4,5,6))
print(t1[0][0]) #结果:1
2.元组的操作
元组由于不可修改的特性,所以其操作方法非常少
编号 | 方法 | 作用 |
---|---|---|
1 | index() | 查找某个数据,如果数据存在返回对应的下标,否则报错 |
2 | count() | 统计某个数据在当前元组出现的次数 |
3 | len(元组) | 统计元组内的元素个数 |
#根据下标(索引)取出数据
t1 = (1,2,'hello')
print(t1[2]) #结果:'hello'
#根据index(),查找特定元素的第一个匹配项
t1 = (1,2,'hello',3,4,'hello')
print(t1.index('hello')) #结果:2
#统计某个数据在元组内出现的次数
t1 = (1,2,'hello',3,4,'hello')
print(t1.conunt('hello')) #结果:2
#统计元组内的元素个数
t1 = (1,2,3)
print(len(t1)) #结果:3
注意
- 不可以修改元组的内容,否则会直接报错
- 可以修改元组内的list的内容(修改元素、增加、删除、反转等)
t1 = (1,2,['A','B'])
- 不可以替换list为其它list或其它类型
元组的遍历
#while循环
t1 =(5,6,8)
a = 0
while a<len(t1):
print(t1[a])
a+=1
运行结果:
5,6,8
t1 =(5,6,8)
for a in t1:
print(a)
运行结果:
5,6,8
3.元组的特点
经过上述对元组的学习,可以总结出列表有如下特点:
-
可以容纳多个数据
-
可以容纳不同类型的数据(混装)
-
数据是有序存储的(下标索引)
-
允许重复数据存在
-
不可以修改(增加或删除元素等)
-
支持for循环
多数特性和list一致,不同点在于不可修改的特性。
练习案例
定义一个元组,内容是:(‘周杰轮’, 11, [‘football’, ‘music’]),记录的是一个学生的信息(姓名、年龄、爱好)
请通过元组的功能(方法),对其进行
- 查询其年龄所在的下标位置
- 查询学生的姓名
- 删除学生爱好中的football
- 增加爱好:coding到爱好list内
t1 = ('周杰轮', 11, ['football', 'music'])
4.数据容器:str(字符串)
字符串是字符的容器,一个字符串可以存放任意数量的字符。
1.字符串的下标(索引)
和其它容器如:列表、元组一样,字符串也可以通过下标进行访问
- 从前向后,下标从0开始
- 从后向前,下标从-1开始
同元组一样,字符串是一个:无法修改的数据容器。
如果必须要做,只能得到一个新的字符串,旧的字符串是无法修改
#通过下标获取特定位置字符
str1 = "hello world"
print(str[0]) #结果:h
print(str[-1]) #结果:d
2.字符串的常用操作
1.查找特定字符串的下标索引值
语法:字符串.index(字符串)
str1 = "hello world"
print(str1.index("wo")) #结果:6 注意空格也算一个字符
2.字符串的替换
语法:字符串.replace(字符串1,字符串2)
功能:将字符串内的全部:字符串1,替换为字符串2
注意:不是修改字符串本身,而是得到了一个新字符串哦
str1 = "hello world"
str2 = str1.replace("wo","you")
print(str1) #结果 :hello world
print(str2) #结果: hello yourld
可以看到,字符串name本身并没有发生变化 而是得到了一个新字符串对象
3.字符串的分割
语法:字符串.split(分隔符字符串)
功能:按照指定的分隔符字符串,将字符串划分为多个字符串,并存入列表对象中
注意:字符串本身不变,而是得到了一个列表对象
str1 = "hello everyone hello world"
list1 = str1.split(" ")
print(list1)
print(type(list1))
#结果:
['hello', 'everyone', 'hello', 'world']
<class 'list'>
可以看到,字符串按照给定的 <空格>进行了分割,变成多个子字符串,并存入一个列表对象中。
4.字符串的规整操作
注意字符串不能被修改,只是得到了一个新字符串
- 去前后空格
语法:字符串.strip()
str1 = " hello everyone hello world "
list1 = str1.strip()
print(list1)
print(str1)
#结果:
hello everyone hello world
hello everyone hello world
- 去前后指定字符串
语法:字符串.strip(字符串)
str1 = "112hello everyone hello world212"
list1 = str1.strip("12")
print(list1)
print(str1)
#结果:
hello everyone hello world
112hello everyone hello world212
注意,传入的是“12” 其实就是:”1”和”2”都会移除,是按照单个字符。
5.统计字符串中某字符串的出现次数
语法:字符串.count(字符串)
str1 = "112hello everyone hello world212"
list1 = str1.count("21")
print(list1)
print(str1)
#结果:
1
112hello everyone hello world212
6.统计字符串的长度
语法:len(字符串)
str1 = "12 ab !@#$ 你好"
print(len(str1))
可以看出:
- 数字(1、2、3…)
- 字母(abcd、ABCD等)
- 符号(空格、!、@、#、$等)
- 中文
均算作1个字符
字符串常用操作汇总
编号 | 操作 | 说明 |
---|---|---|
1 | 字符串[下标] | 根据下标索引取出特定位置字符 |
2 | 字符串.index(字符串) | 查找给定字符的第一个匹配项的下标 |
3 | 字符串.replace(字符串1, 字符串2) | 将字符串内的全部字符串1,替换为字符串2不会修改原字符串,而是得到一个新的 |
4 | 字符串.split(字符串) | 按照给定字符串,对字符串进行分隔不会修改原字符串,而是得到一个新的列表 |
5 | 字符串.strip()字符串.strip(字符串) | 移除首尾的空格和换行符或指定字符串 |
6 | 字符串.count(字符串) | 统计字符串内某字符串的出现次数 |
7 | len(字符串) | 统计字符串的字符个数 |
5.数据容器(序列)的切片
序列是指:内容连续、有序,可使用下标索引的一类数据容器
列表、元组、字符串,均可以可以视为序列。
序列支持切片,即:列表、元组、字符串,均支持进行切片操作
切片:从一个序列中,取出一个子序列
语法:序列[起始下标:结束下标:步长]
表示从序列中,从指定位置开始,依次取出元素,到指定位置结束,得到一个新序列:
- 起始下标表示从何处开始 【可以留空,留空视作从头开始】
- 结束下标(不含)表示何处结束 【可以留空,留空视作截取到结尾】
- 步长表示,依次取元素的间隔
步长1表示,一个个取元素
步长2表示,每次跳过1个元素取
步长N表示,每次跳过N-1个元素取
步长为负数表示,反向取(注意,起始下标和结束下标也要反向标记)
注意,此操作不会影响序列本身,而是会得到一个新的序列(列表、元组、字符串)
示例代码:
my_list = [1, 2, 3, 4, 5]
new_list = my_list[1:4] # 下标1开始,下标4(不含)结束,步长1
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_str[::-1] # 从头(最后)开始,到尾结束,步长-1(倒序)
print(new_str) # 结果:"54321"
my_list = [1, 2, 3, 4, 5]
new_list = my_list[3:1:-1] # 从下标3开始,到下标1(不含)结束,步长-1(倒序)
print(new_list) # 结果:[4, 3]
my_tuple = (1, 2, 3, 4, 5)
new_tuple = my_tuple[:1:-2] # 从头(最后)开始,到下标1(不含)结束,步长-2(倒序)
print(new_tuple) # 结果:(5, 3)
可以看到,这个操作对列表、元组、字符串是通用的
同时非常灵活,根据需求,起始位置,结束位置,步长(正反序)都是可以自行控制的
6.数据容器:set(集合)
1.集合的特点
可以理解为数学中的集合,概念
- 确定性:集合中的元素都是确定的。
- 互异性:集合中的元素都是不同的。
- 无序性:集合中的元素没有特定的顺序
我们目前接触到了列表、元组、字符串三个数据容器了。基本满足大多数的使用场景。为何又需要学习新的集合类型呢?
通过特性来分析:列表可修改、支持重复元素且有序, 元组、字符串不可修改、支持重复元素且有序
有没有看出一些局限?
局限就在于:它们都支持重复元素。如果场景需要对内容做去重处理,列表、元组、字符串就不方便了。
而集合,最主要的特点就是:不支持元素的重复(自带去重功能)、并且内容无序
和列表、元组、字符串等定义基本相同:
- 列表使用:[]
- 元组使用:()
- 字符串使用:“”
- 集合使用:{}
集合有如下特点:
- 可以容纳多个数据
- 可以容纳不同类型的数据(混装)
- 数据是无序存储的(不支持下标索引)
- 不允许重复数据存在
- 可以修改(增加或删除元素等)
- 支持for循环
2.集合的定义
基本语法:
#定义集合字面量
{元素,元素,......}
#定义集合变量
变量名称 = {元素,元素,......}
#定义空集合
变量名称 = set()
set1 = {1,2,3,4,1,1,2,3,5}
print(set1)
#结果
{1, 2, 3, 4, 5}
3.集合的常见操作
首先,因为集合是无序的,所以集合不支持:下标索引访问
但是集合和列表一样,是允许修改的,所以我们来看看集合的修改方法
-
添加新元素
语法:集合.add(元素)。将指定元素,添加到集合内
结果:集合本身被修改,添加了新元素
set1 = {1,2} set1.add(3) print(set1) #结果:{1,2,3} #注意:一次只能添加一个新元素
-
移除元素
语法:集合.remove(元素),将指定元素,从集合内移除
结果:集合本身被修改,移除了元素
set1 = {1,2,3}
set1.remove(3)
print(set1) #结果:{1,2}
- 从集合中随机取出元素
语法:集合.pop(),功能,从集合中随机取出一个元素
结果:会得到一个元素的结果。同时集合本身被修改,元素被移除
set1 = {1,2,3}
set2 = set1.pop()
print(set1) #结果:{2, 3}
print(set2) #结果:1
-
清空集合
语法:集合.clear(),功能,清空集合
结果:集合本身被清空
set1 = {1,2,3}
set1.clear()
print(set1) #结果:set() 空集合
-
取出2个集合的差集
语法:集合1.difference(集合2),
功能:取出集合1和集合2的差集(集合1有而集合2没有的)
结果:得到一个新集合,集合1和集合2不变
set1 = {1,2,3}
set2 = {1,5,6}
set3 = set1.difference(set2)
print(set1)
print(set2)
print(set3)
#结果:
{1, 2, 3}
{1, 5, 6}
{2, 3}
-
消除2个集合的差集
语法:集合1.difference_update(集合2)
功能:对比集合1和集合2,在集合1内,删除和集合2相同的元素。
结果:集合1被修改,集合2不变
set1 = {1,2,3}
set2 = {1,5,6}
set1.difference_update(set2)
print(set1)
print(set2)
#结果:
{2, 3}
{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}
print(len(set1)) #结果:3
-
for循环遍历
要注意:集合不支持下标索引,所以也就不支持使用while循环。
set1 = {1,2,3}
for i in set1:
print(i)
#结果:
1
2
3
集合常用功能总结
编号 | 操作 | 说明 |
---|---|---|
1 | 集合.add(元素) | 集合内添加一个元素 |
2 | 集合.remove(元素) | 移除集合内指定的元素 |
3 | 集合.pop() | 从集合中随机取出一个元素 |
4 | 集合.clear() | 将集合清空 |
5 | 集合1.difference(集合2) | 得到一个新集合,内含2个集合的差集原有的2个集合内容不变 |
6 | 集合1.difference_update(集合2) | 在集合1中,删除集合2中存在的元素集合1被修改,集合2不变 |
7 | 集合1.union(集合2) | 得到1个新集合,内含2个集合的全部元素原有的2个集合内容不变 |
8 | len(集合) | 得到一个整数,记录了集合的元素数量 |
综合练习
有如下列表对象:my_list = [1, 2,1,2,”A”,”B”,”A”]
请:
- 定义一个空集合
- 通过for循环遍历列表
- 在for循环中将列表的元素添加至集合
- 最终得到元素去重后的集合对象,并打印输出
my_list = [1, 2, 1, 2, "A", "B", "A"]
set1 = set()
for i in my_list:
set1.add(i)
print(set1)
#结果:
{1, 2, 'A', 'B'}
7.数据容器:dict(字典、映射)
1.字典的含义
生活中的字典:
通过【字】 ,就能找到对应的【含义】。
所以,我们可以认为,生活中的字典就是记录的一堆:【字】:【含义】【字】:【含义】…【字】:【含义】
Python中字典和生活中字典十分相像:
生活中的字典 | Python中的字典 |
---|---|
【字】:【含义】 | Key: Value |
老师有一份名单,记录了学生的姓名和考试总成绩。
现在需要将其通过Python录入至程序中,并可以通过学生姓名检索学生的成绩。
使用字典最为合适:
可以通过Key(学生姓名),取到对应的Value(考试成绩)。
所以,为什么使用字典? 因为可以使用字典,实现用key取出Value的操作
2.字典的定义
字典的定义,同样使用{},不过存储的元素是一个个的:键值对,如下语法:
#定义字典字面量
{key:value,key:value,......}
#定义字典变量
mydict = {key:value,key:value,......}
#定义空字典
mydict ={} #空字典定义方式1
mydict = dict() #空字典定义方式2
- 使用{}存储原始,每一个元素是一个键值对
- 每一个键值对包含Key和Value(用冒号分隔)
- 键值对之间使用逗号分隔
- Key和Value可以是任意类型的数据(key不可为字典)
- Key不可重复,重复会对原有数据覆盖
前文中记录学生成绩的需求,可以如下记录:
stu_score ={"王力鸿":99,"周杰轮":88,"林俊接":77}
1.字典同集合一样,不可以使用下标索引,但是字典可以通过Key值来取得对应的Value
#语法,字典[key]可以取到对应的Value
stu_score ={"王力鸿":99,"周杰轮":88,"林俊接":77}
print(stu_score["王力鸿"]) #结果:99
print(stu_score["周杰轮"]) #结果:88
print(stu_score["林俊接"]) #结果:77
2.字典的Key和Value可以是任意数据类型(Key不可为字典)
那么,就表明,字典是可以嵌套的。
需求如下:记录学生各科的考试信息
stu_score ={
"王力鸿":{"语文":77,"数学":66,"英语":33},
"周杰轮":{"语文":88,"数学":86,"英语":55},
"林俊接":{"语文":99,"数学":96,"英语":66}}
嵌套字典的内容获取,如下所示:
stu_score ={
"王力鸿":{"语文":77,"数学":66,"英语":33},
"周杰轮":{"语文":88,"数学":86,"英语":55},
"林俊接":{"语文":99,"数学":96,"英语":66}}
print(stu_score["王力鸿"]) #结果:{'语文': 77, '数学': 66, '英语': 33}
print(stu_score["王力鸿"]["语文"]) #结果:77
print(stu_score["周杰轮"]["英语"]) #结果:55
3.字典的常用操作
-
新增元素
语法:字典[Key] = Value,结果:字典被修改,新增了元素
stu_score ={
"王力鸿":99,
"周杰轮":88,
"林俊接":77}
#新增,张学油的考试成绩
stu_score['张学油'] = 66
print(stu_score)
#结果:{'王力鸿': 99, '周杰轮': 88, '林俊接': 77, '张学油': 66}
-
更新元素
语法:字典[Key] = Value,结果:字典被修改,元素被更新
注意:字典Key不可以重复,所以对已存在的Key执行上述操作,就是更新Value值
stu_score ={
"王力鸿":99,
"周杰轮":88,
"林俊接":77}
stu_score['王力鸿'] = 66
print(stu_score)
#结果:{'王力鸿': 66, '周杰轮': 88, '林俊接': 77}
-
删除元素
语法:字典.pop(Key),结果:获得指定Key的Value,同时字典被修改,指定Key的数据被删除
stu_score ={
"王力鸿":99,
"周杰轮":88,
"林俊接":77}
value =stu_score.pop("王力鸿")
print(stu_score) #结果:{'周杰轮': 88, '林俊接': 77}
print(value) #结果:99
-
清空字典
语法:字典.clear(),结果:字典被修改,元素被清空
stu_score ={
"王力鸿":99,
"周杰轮":88,
"林俊接":77}
stu_score.clear()
print(stu_score) #结果:{}
-
获取全部的key
语法:字典.keys(),结果:得到字典中的全部Key
stu_score ={
"王力鸿":99,
"周杰轮":88,
"林俊接":77}
key = stu_score.keys()
print(key) #结果:dict_keys(['王力鸿', '周杰轮', '林俊接'])
-
遍历字典
语法:for key in 字典.keys()
stu_score ={
"王力鸿":99,
"周杰轮":88,
"林俊接":77}
keys = stu_score.keys()
for i in keys:
print(f"学生:{i},分数:{stu_score[i]}")
#结果:学生:王力鸿,分数:99
学生:周杰轮,分数:88
学生:林俊接,分数:77
注意:字典不支持下标索引,所以同样不可以用while循环遍历
-
计算字典内的全部元素(键值对)数量
语法:len(字典)
结果:得到一个整数,表示字典内元素(键值对)的数量
stu_score ={
"王力鸿":99,
"周杰轮":88,
"林俊接":77}
print(len(stu_score)) #结果:3
总结
编号 | 操作 | 说明 |
---|---|---|
1 | 字典[Key] | 获取指定Key对应的Value值 |
2 | 字典[Key] = Value | 添加或更新键值对 |
3 | 字典.pop(Key) | 取出Key对应的Value并在字典内删除此Key的键值对 |
4 | 字典.clear() | 清空字典 |
5 | 字典.keys() | 获取字典的全部Key,可用于for循环遍历字典 |
6 | len(字典) | 计算字典内的元素数量 |
经过上述对字典的学习,可以总结出字典有如下特点:
- 可以容纳多个数据
- 可以容纳不同类型的数据
- 每一份数据是KeyValue键值对
- 可以通过Key获取到Value,Key不可重复(重复会覆盖)
- 不支持下标索引
- 可以修改(增加或删除更新元素等)
- 支持for循环,不支持while循环
练习题
有如下员工信息,请使用字典完成数据的记录。
并通过for循环,对所有级别为1级的员工,级别上升1级,薪水增加1000元
people ={
"王力鸿":{"部门":"科技部","工资":3000,"级别":1},
"周杰轮":{"部门":"市场部","工资":5000,"级别":2},
"林俊接":{"部门":"市场部","工资":7000,"级别":3},
"张学油":{"部门":"科技部","工资":4000,"级别":1},
"刘德滑":{"部门":"市场部","工资":6000,"级别":2}}
print("全体成员信息如下:")
for i in people:
print(i,people[i])
print("涨薪后信息为:")
for j in people:
if people[j]["级别"]==1:
people[j]["级别"] +=1
people[j]["工资"]+=1000
print(j, people[j])
#运行结果:
全体成员信息如下:
王力鸿 {'部门': '科技部', '工资': 3000, '级别': 1}
周杰轮 {'部门': '市场部', '工资': 5000, '级别': 2}
林俊接 {'部门': '市场部', '工资': 7000, '级别': 3}
张学油 {'部门': '科技部', '工资': 4000, '级别': 1}
刘德滑 {'部门': '市场部', '工资': 6000, '级别': 2}
涨薪后信息为:
王力鸿 {'部门': '科技部', '工资': 4000, '级别': 2}
周杰轮 {'部门': '市场部', '工资': 5000, '级别': 2}
林俊接 {'部门': '市场部', '工资': 7000, '级别': 3}
张学油 {'部门': '科技部', '工资': 5000, '级别': 2}
刘德滑 {'部门': '市场部', '工资': 6000, '级别': 2}
数据容器对比
列表 | 元组 | 字符串 | 集合 | 字典 | |
---|---|---|---|---|---|
元素数量 | 支持多个 | 支持多个 | 支持多个 | 支持多个 | 支持多个 |
元素类型 | 任意 | 任意 | 仅字符 | 任意 | Key:ValueKey:除字典外任意类型Value:任意类型 |
下标索引 | 支持 | 支持 | 支持 | 不支持 | 不支持 |
重复元素 | 支持 | 支持 | 支持 | 不支持 | 不支持 |
可修改性 | 支持 | 不支持 | 不支持 | 支持 | 支持 |
数据有序 | 是 | 是 | 是 | 否 | 否 |
使用场景 | 可修改、可重复的一批数据记录场景 | 不可修改、可重复的一批数据记录场景 | 一串字符的记录场景 | 不可重复的数据记录场景 | 以Key检索Value的数据记录场景 |
基于各类数据容器的特点,它们的应用场景如下:
- 列表:一批数据,可修改、可重复的存储场景
- 元组:一批数据,不可修改、可重复的存储场景
- 字符串:一串字符串的存储场景
- 集合:一批数据,去重存储场景
- 字典:一批数据,可用Key检索Value的存储场景
数据容器通用操作
1.数据容器尽管各自有各自的特点,但是它们也有通用的一些操作。
首先,在遍历上:
- 5类数据容器都支持for循环遍历
- 列表、元组、字符串支持while循环,集合、字典不支持(无法下标索引)
尽管遍历的形式各有不同,但是,它们都支持遍历操作。
2.除了遍历这个共性外,数据容器可以通用非常多的功能方法
len(容器):统计容器的元素个数
my_list = [1, 2, 3]
my_tuple = (1, 2, 3, 4, 5)
my_str = "hello"
print(len(my_list)) # 结果3
print(len(my_tuple)) # 结果5
print(len(my_str)) # 结果7
max(容器):统计容器的最大元素
my_list = [1, 2, 3]
my_tuple = (1, 2, 3, 4, 5)
my_str = "hello"
print(max(my_list)) # 结果3
print(max(my_tuple)) # 结果5
print(max(my_str)) # 结果o 根据ascall码表来比大小
min(容器):统计容器的最小元素
my_list = [1, 2, 3]
my_tuple = (1, 2, 3, 4, 5)
my_str = "hello"
print(min(my_list)) # 结果1
print(min(my_tuple)) # 结果1
print(min(my_str)) # 结果e
3.除了下标索引这个共性外,还可以通用类型转换
list(容器):将给定容器转换为列表
**str(容器):**将给定容器转换为字符串
**tuple(容器):**将给定容器转换为元组
set(容器):将给定容器转换为集合
4.通用排序功能
sorted(容器, [reverse=True])
将给定容器进行排序
注意,排序后都会得到列表(list)对象。
总览
功能 | 描述 |
---|---|
通用for循环 | 遍历容器(字典是遍历key) |
max | 容器内最大元素 |
min() | 容器内最小元素 |
len() | 容器元素个数 |
list() | 转换为列表 |
tuple() | 转换为元组 |
str() | 转换为字符串 |
set() | 转换为集合 |
sorted(序列, [reverse=True]) | 排序,reverse=True表示降序得到一个排好序的列表 |
拓展:字符串比大小
在程序中,字符串所用的所有字符如:
- 大小写英文单词
- 数字
- 特殊符号(!、\、|、@、#、空格等)都有其对应的ASCII码表值
每一个字符都能对应上一个:数字的码值字符串进行比较就是基于数字的码值大小进行比较的。
字符串是按位比较,也就是一位位进行对比,只要有一位大,那么整体就大。
第七章 文件操作
1.文件的编码
思考:计算机只能识别:0和1,那么我们丰富的文本文件是如何被计算机识别,并存储在硬盘中呢?
答案:使用编码技术(密码本)将内容翻译成0和1存入。
编码技术即:翻译的规则,记录了如何将内容翻译成二进制,以及如何将二进制翻译回可识别内容。
编码有许多,所以要使用正确的编码, 才能对文件进行正确的读写操作呢。
我们可以使用Windows系统自带的记事本,打开文件后,即可看出文件的编码是什么:
UTF-8是目前全球通用的编码格式除非有特殊需求,否则,一律以UTF-8格式进行文件编码即可。
2. 文件的读取
内存中存放的数据在计算机关机后就会消失。要长久保存数据,就要使用硬盘、光盘、U 盘等设备。为了便于数据的管理和检索,引入了“文件”的概念。
一篇文章、一段视频、一个可执行程序,都可以被保存为一个文件,并赋予一个文件名。操作系统以文件为单位管理磁盘中的数据。一般来说,文件可分为文本文件、视频文件、音频文件、图像文件、可执行文件等多种类别。
想想我们平常对文件的基本操作,大概可以分为三个步骤(简称文件操作三步走):① 打开文件 ② 读写文件 ③ 关闭文件
注意:可以只打开和关闭文件,不进行任何读写
open()打开函数
在Python,使用open函数,可以打开一个已经存在的文件,或者创建一个新文件,语法如下
open(name, mode, encoding)
name:是要打开的目标文件名的字符串(可以包含文件所在的具体路径)。
mode:设置打开文件的模式(访问模式):只读、写入、追加等。
encoding:编码格式(推荐使用UTF-8)
#示例代码
f = open("D:/a.txt", "r", encoding="UTF-8")
print(type(f)) #结果:<class '_io.TextIOWrapper'>
# encoding的顺序不是第三位,所以不能用位置参数,用关键字参数直接指定
注意:此时的
f
是open
函数的文件对象,对象是Python中一种特殊的数据类型,拥有属性和方法,可以使用对象.属性或对象.方法对其进行访问,后续面向对象会进行详细的介绍。
模式 | 描述 |
---|---|
r | 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。 |
w | 打开一个文件只用于写入。1.如果该文件已存在则打开文件,并从开头开始编辑,原有内容会被删除。2.如果该文件不存在,创建新文件。 |
a | 打开一个文件用于追加。1.如果该文件已存在,新的内容将会被写入到已有内容之后。2.如果该文件不存在,创建新文件进行写入。 |
read()方法:
文件对象.read(num)
#num表示要从文件中读取的数据的长度(单位是字节),如果没有传入num,那么就表示读取文件中所有的数据。
# 示例代码
f = open("D:/a.txt", "r", encoding="UTF-8")
a = f.read()
print(a)
readlines()方法:
#readlines可以按照行的方式把整个文件中的内容进行一次性读取,并且返回的是一个列表,其中每一行的数据为一个元素。
f = open('D:/a.txt')
content = f.readlines()
# ['hello world\n', 'abcdefg\n', 'aaa\n', 'bbb\n', 'ccc']
print(content)
# 关闭文件
f.close()
#readline()方法:一次读取一行内容
f = open('D:/a.txt')
content = f.readline()
print(f'第一行:{content}')
content = f.readline()
print(f'第二行:{content}')
# 关闭文件
f.close()
#for循环读取文件行
for line in open("D:/a.txt", "r"):
print(line)
# 每一个line临时变量,就记录了文件的一行数据
close() 关闭文件对象
f = open("D:/a.txt", "r")
f.close()
# 最后通过close,关闭文件对象,也就是关闭对文件的占用
# 如果不调用close,同时程序没有停止运行,那么这个文件将一直被Python程序占用。
with open 语法
with open("python.txt", "r") as f:
f.readlines()
# 通过在with open的语句块中对文件进行操作
# 可以在操作完成后自动关闭close文件,避免遗忘掉close方法
操作 | 功能 |
---|---|
文件对象 = open(file, mode, encoding) | 打开文件获得文件对象 |
文件对象.read(num) | 读取指定长度字节不指定num读取文件全部 |
文件对象.readline() | 读取一行 |
文件对象.readlines() | 读取全部行,得到列表 |
for line in 文件对象 | for循环文件行,一次循环得到一行数据 |
文件对象.close() | 关闭文件对象 |
with open() as f | 通过with open语法打开文件,可以自动关闭 |
3.文件的写入
# 1. 打开文件
f = open('D:/a.txt', 'w')
# 2.文件写入
f.write('hello world')
# 3. 内容刷新
f.flush() #可以直接f.close关闭,自动刷新
注意:
- 直接调用write,内容并未真正写入文件,而是会积攒在程序的内存中,称之为缓冲区。
- 当调用flush的时候,内容会真正写入文件。
- 这样做是避免频繁的操作硬盘,导致效率下降(攒一堆,一次性写磁盘)。
写操作注意
- 文件如果不存在,使用”w”模式,会创建新文件
- 文件如果存在,使用”w”模式,会将原有内容清空
总结
-
写入文件使用open函数的”w”模式进行写入
-
写入的方法有:
wirte(),写入内容
flush(),刷新内容到硬盘中
-
注意事项:
w模式,文件不存在,会创建新文件
w模式,文件存在,会清空原有内容
调用close(),自动使用flush()方法的功能
4.文件的追加
# 1. 打开文件,通过a模式打开即可
f = open('python.txt', 'a')
# 2.文件写入
f.write('hello world')
# 3. 内容刷新
f.flush()
注意:
- a模式,文件不存在会创建文件
- a模式,文件存在会在最后,追加写入文件
总结
-
追加写入文件使用open函数的”a”模式进行写入
-
追加写入的方法有(和w模式一致):
wirte(),写入内容
flush(),刷新内容到硬盘中
-
注意事项:
a模式,文件不存在,会创建新文件
a模式,文件存在,会在原有内容后面继续写入
可以使用”\n”来写出换行符
5.文件备份案例
需求:有一份账单文件,记录了消费收入的具体记录,内容如下:
name,date,money,type,remarks
周杰轮,2022-01-01,100000,消费,正式
周杰轮,2022-01-02,300000,收入,正式
周杰轮,2022-01-03,100000,消费,测试
林俊节,2022-01-01,300000,收入,正式
林俊节,2022-01-02,100000,消费,测试
林俊节,2022-01-03,100000,消费,正式
林俊节,2022-01-04,100000,消费,测试
林俊节,2022-01-05,500000,收入,正式
张学油,2022-01-01,100000,消费,正式
张学油,2022-01-02,500000,收入,正式
张学油,2022-01-03,900000,收入,测试
王力鸿,2022-01-01,500000,消费,正式
王力鸿,2022-01-02,300000,消费,测试
王力鸿,2022-01-03,950000,收入,正式
刘德滑,2022-01-01,300000,消费,测试
刘德滑,2022-01-02,100000,消费,正式
刘德滑,2022-01-03,300000,消费,正式
将内容复制并保存为 bill.txt文件
我们现在要做的就是:
- 读取文件
- 将文件写出到bill.txt.bak文件作为备份
- 同时,将文件内标记为测试的数据行丢弃
实现思路:
- open和r模式打开一个文件对象,并读取文件
- open和w模式打开另一个文件对象,用于文件写出
- for循环内容,判断是否是测试不是测试就write写出,是测试就continue跳过
- 将2个文件对象均close()
# 1. 打开文件
fr = open('D:/bill.txt', 'r', encoding='UTF-8')
fw = open('D:/bill.txt.bak', 'w', encoding='UTF-8')
#2.写入文件
for line in fr:
line = line.strip() #去掉前后空格
if line.split(",")[4] == "测试":#
continue
fw.write(line)
fw.write("\n") #因为前面对内容进行了strip()操作,所以要手动的写出换行符
# 3. 关闭,内容刷新
fw.close()
fr.close()
第八章 Pyhton异常、模块、包
1.异常
当检测到一个错误时,Python解释器就无法继续执行了,反而出现了一些错误的提示,这就是所谓的==“异常”,== 也就是我们常说的BUG
异常演示:
例如:以r
方式打开一个不存在的文件。
f = open('linux.txt', 'r')
2.异常捕获
世界上没有完美的程序,任何程序在运行的过程中,都有可能出现:异常,也就是出现bug,导致程序无法完美运行下去。
我们要做的,不是力求程序完美运行。而是在力所能及的范围内,对可能出现的bug,进行提前准备、提前处理。
这种行为我们称之为:异常处理(捕获异常)
为什么需要捕获异常?
当我们的程序遇到了BUG, 那么接下来有两种情况:
① 整个程序因为一个BUG停止运行
② 对BUG进行提醒, 整个程序继续运行
显然在之前的学习中, 我们所有的程序遇到BUG就会出现①的这种情况, 也就是整个程序直接奔溃.但是在真实工作中, 我们肯定不能因为一个小的BUG就让整个程序全部奔溃, 也就是我们希望的是达到② 的这种情况那这里我们就需要使用到捕获异常捕获异常的作用在于:提前假设某处会出现异常,做好提前准备,当真的出现异常的时候,可以有后续手段。
1.捕获常规异常—基本语法:
这个基本异常捕获已经可以捕获全部异常,第四点没必要用
try:
可能发生错误的代码
except:
如果出现异常执行的代码
# 1.基本捕获语法
try:
f = open("D:/abc.txt", "r", encoding="UTF-8")
except:
print("出现异常了,因为文件不存在,我将open的模式,改为w模式去打开")
f = open("D:/abc.txt", "w", encoding="UTF-8")
2.捕获指定异常
# 2.捕获指定的异常
try:
print(name)
# 1 / 0
except NameError as e:
print("出现了变量未定义的异常")
print(e)
① 如果尝试执行的代码的异常类型和要捕获的异常类型不一致,则无法捕获异常。 ② 一般try下方只放一行尝试执行的代码。
把捕获异常的原因存到e变量里面,打印出来
3.捕获多个异常
当捕获多个异常时,可以把要捕获的异常类型的名字,放到except 后,并使用元组的方式进行书写。
# 3.捕获多个异常
try:
# 1 / 0
print(name)
except (NameError, ZeroDivisionError) as e:
print("出现了变量未定义 或者 除以0的异常错误")
# 未正确设置捕获异常类型,将无法捕获异常
4.捕获所有异常
else表示的是如果没有异常要执行的代码。
try:
f = open("D:/123.txt", "r", encoding="UTF-8")
except Exception as e:
print("出现异常了")
f = open("D:/123.txt", "w", encoding="UTF-8")
else:
print("好高兴,没有异常。")
5.异常的finally
finally表示的是无论是否异常都要执行的代码,例如关闭文件。
try:
f = open("D:/123.txt", "r", encoding="UTF-8")
except Exception as e:
print("出现异常了")
f = open("D:/123.txt", "w", encoding="UTF-8")
else:
print("好高兴,没有异常。")
finally:
print("我是finally,有没有异常我都要执行")
f.close()
3.异常的传递
异常是具有传递性的。
当函数func01中发生异常, 并且没有捕获处理这个异常的时候, 异常会传递到函数func02, 当func02也没有捕获处理这个异常的时候main函数会捕获这个异常, 这就是异常的传递性。
提示: 当所有函数都没有捕获异常的时候, 程序就会报错
利用异常具有传递性的特点, 当我们想要保证程序不会因为异常崩溃的时候, 就可以在main函数中设置异常捕获, 由于无论在整个程序哪里发生异常, 最终都会传递到main函数中, 这样就可以确保所有的异常都会被捕获
4.python模块
Python 模块(Module),是一个 Python 文件,以 .py 结尾. 模块能定义函数,类和变量,模块里也能包含可执行的代码。
模块的作用: python中有很多各种不同的模块, 每一个模块都可以帮助我们快速的实现一些功能, 比如实现和时间相关的功能就可以使用time模块我们可以认为一个模块就是一个工具包, 每一个工具包中都有各种不同的工具供我们使用,进而实现各种不同的功能。
**大白话:**模块就是一个Python文件,里面有类、函数、变量等,我们可以拿过来用(导入模块去使用)
1.模块导入方式
模块在使用前需要先导入 导入的语法如下:
[form 模块名] import [模块|类|变量|函数|*][as 别名]
常用的组合形式如:
- import 模块名
- from 模块名 import 类、变量、方法等
- from 模块名 import *
- import 模块名 as 别名
- from 模块名 import 功能名 as 别名
基本语法:
1.import模块名
import会把里面所有的模块都会导入进来
import 模块名
import 模块名1,模块名2
模块名.功能名()
# 导入时间模块
import time
print("开始")
time.sleep(1)# 让程序睡眠1秒(阻塞)
print("结束")
2.from 模块名 import 功能名
因为导入的模块里面的函数不一定都会用上,所以只需要导入用到的即可
from 模块名 import 功能名
功能名()
# 导入时间模块中的sleep方法
from time import sleep
print("开始")# 让程序睡眠1秒(阻塞)
sleep(1)
print("结束")
**3.from 模块名 import ***
导入模块的全部功能,与第一个一样,区别在于,不用加 . 了。
from 模块名 import *
功能名()
# 导入时间模块中所有的方法
from time import *
print("开始")# 让程序睡眠1秒(阻塞)
sleep(1)
print("结束")
2.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')
5.自定义模块
Python中已经帮我们实现了很多的模块. 不过有时候我们需要一些个性化的模块, 这里就可以通过自定义模块实现, 也就是自己制作一个模块。
**案例:**新建一个Python文件,命名为my_module1.py,并定义test函数
注意: 每个Python文件都可以作为一个模块,模块的名字就是文件的名字. 也就是说自定义模块名必须要符合标识符命名规则
# 导入不同模块的同名功能
from my_module1 import test
from my_module2 import test
test(1, 2)
注意事项:当导入多个模块的时候,且模块内有同名功能. 当调用这个同名功能的时候,调用到的是后面导入的模块的功能。
6.测试模块
在实际开发中,当一个开发人员编写完一个模块后,为了让模块能够在项目中达到想要的效果,这个开发人员会自行在py文件中添加一些测试信息,例如,在my_module1.py
文件中添加测试代码test(1,1)
#my_module1.py
#当其他文件调用这个模块时,会从上到下运行一遍,这个时候test函数就会被运行,但是这个文件我又不想删除,以后想要做测试用,那么我应该怎么做呢
def test(a, b):
print(a + b)
test(1, 1)
#my_module1.py
def test(a, b):
print(a + b)
# 只在当前文件中调用该函数,其他导入的文件内不符合该条件,则不执行test函数调用
if __name__ == '__main__':
test (1, 1)
在每个文件中都有一个内部变量name,当我在运行这个文件时,他就是main函数,但是如果是被其他文件调用过来的,则不是。
7.__ all __
如果一个模块文件中有__all__
变量,当使用from xxx import *
导入时,只能导入这个列表中的元素
__all__变量可以控制import *的时候哪些功能可以被导入
8.自定义包
基于Python模块,我们可以在编写代码的时候,导入许多外部代码来丰富功能。
但是,如果Python的模块太多了,就可能造成一定的混乱,这个时候就可以通过Python包的功能来管理。
当我创建软件包时,会自动生成init.py文件
包的作用: 当我们的模块文件越来越多时,包可以帮助我们管理这些模块, 包的作用就是包含多个模块,但包的本质依然是模块
什么是包?
从物理上看,包就是一个文件夹,在该文件夹下包含了一个 init.py 文件,该文件夹可用于包含多个模块文件
从逻辑上看,包的本质依然是模块
操作流程:
1.新建软件包
2.软件包与文件夹的区别,会在下面自动生成init.py(一般为空)。
"""
演示自定义模块1
my_module1.py
"""
def info_print1():
print("我是模块1的功能函数代码")
"""
自定义模块2
my_module2.py
"""
def info_print2():
print("我是模块2的功能函数代码")
# 创建一个包
# 导入自定义的包中的模块,并使用
#第一种导入方法
import my_package.my_module1
import my_package.my_module2
my_package.my_module1.info_print1()
my_package.my_module2.info_print2()
#第二种导入方法
from my_package import my_module1
from my_package import my_module2
#可以合起来写from my_package import my_module1,my_module2
my_module1.info_print1()
my_module2.info_print2()
#第三种导入方法
from my_package.my_module1 import info_print1
from my_package.my_module2 import info_print2
info_print1()
info_print2()
控制导入模块的行为
from 包名 import *
注意:必须在__init__.py
文件中添加__all__ = []
,控制允许导入的模块列表
9.安装第三方包
我们知道,包可以包含一堆的Python模块,而每个模块又内含许多的功能。
所以,我们可以认为:一个包,就是一堆同类型功能的集合体。
在Python程序的生态中,有许多非常多的第三方包(非Python官方),可以极大的帮助我们提高开发效率,
如:
- 科学计算中常用的:numpy包
- 数据分析中常用的:pandas包
- 大数据计算中常用的:pyspark、apache-flink包
- 图形可视化常用的:matplotlib、pyecharts
- 人工智能常用的:tensorflow等
这些第三方的包,极大的丰富了Python的生态,提高了开发效率。但是由于是第三方,所以Python没有内置,所以我们需要安装它们才可以导入使用哦。
第三方包的安装非常简单,我们只需要使用Python内置的pip程序即可。
安装:在命令提示符程序,输入:pip install 包名称即可通过网络快速安装第三方包。
pip的网络优化:
由于pip是连接的国外的网站进行包的下载,所以有的时候会速度很慢。
我们可以通过如下命令,让其连接国内的网站进行包的安装:
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple 包名称
https://pypi.tuna.tsinghua.edu.cn/simple 是清华大学提供的一个网站,可供pip程序下载第三方包
- PyCharm安装第三方包