文章目录
- python概述
- 计算机资源
- Why Python
- python解释器
- 解释器的种类
- python版本
- python解释器
- 开发工具
- PyCharm
- vscode
- cursor
- 程序的三种结构
- python中的变量
- python中的输入输出
- python中的标准输入
- python中的格式化输出❗
- 转义字符
- 运算符(基本运算符不写)
- 短路求值⭐(***考试最喜欢考的,不常用但难懂***)
- 逻辑运算符
- 数据类型转换
- 运算符总结
- 三目运算符(三元运算符)⭐
- 循环结构
- for循环
- while循环
- break和continue在for和while中的应用
- 数据容器⭐⭐⭐⭐⭐
- 字符串
- 字符串的输入
- 字符串的输出
- 字符串切片(列表,元组都支持)**只管头不管尾**
- 字符串查找,find(),**列表不能用find**
- 字符串修改方法replace(), split(), join()
- 字符串判断方法
- 列表
- 列表的操作(增删改查)
- 查询:
- 增加
- 删除
- 修改
- 列表的嵌套
- 错题:
- 元组
- 元组的定义 `()`
- 工作中的应用场景
- 元组的操作方法(只能查询)
- 字典!!!
- 学习要求
- 字典定义
- 常见问题
- 增删改查(相同语法)
- 删除
- 查询
- 其他方法
- 列表和字典的结合
- 字典的 get() 方法,用于安全地获取字典中的值
- 集合
- 集合的操作方法(增、删、查,没有改!)
- 数据容器的公共方法
- 数据容器的相互转换
- 原来的基本数据类型转换
- 容器的转换方法
- 注意!!
- 推导式(数据容器)
- 推导式语法
- 代码调试 debug
- pycharm的
- python函数⭐⭐⭐⭐⭐⭐⭐⭐
- 函数基本概念
- 函数的学习目标
- 函数的作用和使用步骤
- 函数定义和调用:
- 关于返回值:
- 函数的说明文档
- 函数嵌套
- 变量作用域(局部变量、全局变量)⭐⭐
- 访问范围
- 局部变量
- 全局变量
- global关键字(只能用来申明)
- 注意!!
- 函数的参数进阶(实参、形参)⭐⭐⭐
- 形参、实参是什么??
- 函数调用的参数
- 函数定义时参数的类别
- **不定长参数**
- 不定长参数应用场景
- 面试题
- 参数混用
- 变量的可变、不可变类型⭐⭐
- 标准数据类型
- Python3 中常见的数据类型有:
- Python3 的⑦个标准数据类型中:
- 不可变数据类型
- 可变数据类型
- 元组拆包 ⭐
- 文件基本操作⭐
- 学习目标
- 基本的基本操作
- 文件操作三步走
- 读取文件方法
- `read()`:一次性读取全部内容
- `readlines()`:读取所有内容成列表,每个元素都是文件中的一行
- `readline()`:一行一行读取,
- 注意!编码问题 ⭐
- 文件访问方式(mode)
- 应用:文件备份
- 进阶一点的文件操作(文件夹)
- 使用os模块
- 文件操作
- 文件夹操作
- 例子
- 路径
- 相对路径
- 绝对路径
- 递归删除文件夹-shutil模块
- python中的异常 ⭐
- 异常捕获方法
- 捕获异常获取错误信息
- !!例子
- 常用错误
- python的模块和包 ⭐⭐
- python的内置模块
- python的自定义模块
- 导入模块方式
- 使用__name__对模块进行测试
- 魔术变量:`__name__`
- OK,结束
- 未来的大饼👇
以前学习的笔记,整理后放上来,方便未来回顾
python概述
计算机资源
- 硬件资源:
- cpu:核心数、频率(超频要超10G)、指令集(x86、ARM等)
- 内存:容量、频率、带宽、类型(ddr3、ddr4)
- 硬盘:SSD、HDD(←容量和读写速度(HDD和SSD特性不同))(自己插个眼,把细说的笔记链接放进来)
- 其他:IO设备、网卡…
- 软件资源:
- 操作系统(Windows、Linux、Android、macOS)
- 应用软件、开发工具、数据资源、网络资源
Why Python
-
是技术趋势、简单易学、应用广泛
-
python优点
- 简单、易学、免费开源、可移植性高、丰富的库资源
-
python的缺点
- 执行效率低(算力成本逐渐降低,这个缺点逐渐可以被忽略)
python解释器
由于Python属于高级语言,其并不能直接在计算机中运行,因为缺少Python语言的运行环境:Python解析器
解释器的种类
- CPython(使用c编写):语言开发的解释器官方,应用广泛的解释器。
- IPython:基于CPython的一种交互式解释器。(数据分析)
- 其他解释器:
- PyPy,基于Python语言开发的解释器。
- JPython,运行在Java平台的解释器,直接把Python代码编译成Java字节码执行。
- IronPython,运行在微软.Net平台上的Python解释器,可直接把Python代码编译成.Net的字节码。
- 微软.net
python版本
不同版本:语法不同、性能不同,
Python3语言更加简洁,性能更好。。。。
python解释器
- python解释器
- 解析器
- 编译器
- 运行环境
- 标准库
- pip包管理工具
开发工具
PyCharm
- 新手最顺手的开发工具
- pycharm是一种python IDE(集成开发环境)
- 优点
- 社区版和专业版
- 项目的概念
vscode
万能的vscode
cursor
高度集成了AI助手的vscode,14天一周期的永久白嫖真香
程序的三种结构
顺序结构
if分支结构(if、elif、else)
循环结构(while、for)
python中的变量
什么是变量?
python中的输入输出
输入:a = input()
输出:print(a)
python中的标准输入
"""
input()除了可以接收数据以外,还隐藏了两个特殊的功能:
①input()方法,永远都是str字符串类型
②input()方法还具有一个"暂停"功能,阻塞后续代码的继续执行,直到用户输入完成以后,代码才可以继续向下执行
"""
变量名称 = input('提示用户输入信息:')
id = 12
name = 'itheima'
print(f'姓名{name},学号{id:6d}') # 输出: 12
print(f'姓名{name},学号{id:06d}') # 输出:000012
python中的格式化输出❗
变量按照一定格式输出
通过百分号格式化输出字符串
name = 'czc'
age = 98
print('名字:%s,今年%d岁。' % (name, age))
%d # 整型变量
%s # 字符串
%.2f # 保留两位小数的浮点数
%6d # 6位整数,不足补零
%% # 输出一个百分号,只输一个百分号会报错
# f形式的格式化输出
# .format()形式的格式化输出只能在Python3中使用!
print('姓名:{},联系方式:{}'.format(name,mobile))
print(f'姓名:{name},联系方式:{mobile}') # 简写,推荐形式
title= '大白菜'
price = 3.5
print(f'今天蔬菜特价了,{title}只要{price:.3f}元/斤。') # {price:06d}
print
输出后不换行:print(_,end='')
print()
就相当于输出换一行:“\n
”
转义字符
"""
\t 制表符
\n 换行符
扩展:print()完整写法print(变量名称,end='\n')代表在输出变量以后,会自动在变量的后面追加一个\n
"""
print(name, end='') # 把默认end的\n删掉
print(age, end='') # 这样这两行都在一起
运算符(基本运算符不写)
短路求值⭐(考试最喜欢考的,不常用但难懂)
“短路求值”,一旦某个条件满足并确定了输出结果,就不再继续进行后续的判断。这可以提高代码的执行效率,避免不必要的计算和判断。
逻辑运算符
优先级:not > and > or
数据类型转换
- int()
- float()
- str()
- eval() # ‘10’、‘99.1’,不能:‘12dd’
运算符总结
+ | 加 - 两个对象相加 | a + b 输出结果 30 |
- | 减 - 得到负数或是一个数减去另一个数 | a - b 输出结果 -10 |
* | 乘 - 两个数相乘或是返回一个被重复若干次的字符串 | a * b 输出结果 200 |
/ | 除 - x除以y | b / a 输出结果 2 |
% | 取模 - 返回除法的余数 | b % a 输出结果 0 |
** | 幂 - 返回x的y次幂 | a**b 为10的20次方, 输出结果 100000000000000000000 |
// | 取整除 - 返回商的整数部分(向下取整) |
三目运算符(三元运算符)⭐
# 值1 if 条件判断 else 值2
a = fuck if fuck == 0 else 0.0 # 满足if条件则短路求值,不执行else后面的
max = n1 if n1 > n2 else n2
循环结构
for循环
range(5, 0, -1)
返回的是[5, 4, 3, 2, 1]
[!NOTE]
range()
方法
在 Python 中,range() 函数用于生成一个整数序列。range() 函数的一般形式是 range(start, stop, step),其中:
start 是序列的起始值。
stop 是序列的结束值,但不包括这个值。
step 是每次迭代中的增量(或减量)。
[!NOTE]
range(5)
会生成 0、1、2、3、4 这五个整数组成的序列。
range(n)
返回的既不是列表也不是元组,而是一个可迭代的range
对象。如果需要将其转换为列表,可以使用
list(range(n))
;如果要转换为元组,可以使用tuple(range(n))
。
for循环也能在后面用else:
??
如果执行了break则不会执行else
for i in xx:
if ss:
break
else:
sss
while循环
🤪
break和continue在for和while中的应用
🤪
数据容器⭐⭐⭐⭐⭐
容器:字符串、列表、元组、字典、集合
字符串
三引号可以用来定义字符串,三引号没有赋值就是注释,赋值了就是字符串。三引号支持换行
字符串中有引号,就交叉使用,或者使用转义字符”\“,告诉计算机,你只要把我当成字符串
"""这是注释"""
a = """这是赋值的字符串"""
b = '这也是字符串'
c = '''
这也是字符串
'''
字符串的输入
input()
字符串的输出
字符串的索引
a,b,c,d,e,f
0,1,2,3,4,5
print(str[0])
索引有正索引:012346
还有负索引:-1-2-3-4-5-6
字符串切片(列表,元组都支持)只管头不管尾
对操作对象截取其中的一部分数据,这个过程就是切片
字符串名称[其实位置:结束位置:步长]
[::-1] # 字符串反转,等效于reserve()
[:-1]:除掉最后一个元素
[::2]:所有偶数索引
✨✨✨
✨✨✨字符串不能用reverse()
来反转,只能用切片
✨✨✨
字符串查找,find(),列表不能用find
查找关键词在字符串中出现的位置,find方法:主要功能就是查找关键词在字符串中出现(第一个)的位置,找到了就返回开始的索引下标,没有找到,返回-1
find(',', 0)
,从索引为0的位置开始找
返回寻找到的字符串的索引(索引从0开始到n-1)(从第{索引}开始是find到的字符串)
具体用法:用来寻找文件的后缀名。思路:查找“.”所在的位置下标
例如:
file = GAT_AMD.py
index = file.find('.')
filename = file[:index] # 等效于file[0,7,1]
postfix = file[index:] # file[7::1]
print(f'{..}{..}')
字符串修改方法replace(), split(), join()
replace(old, new) # 把旧内容替换成新内容
split(分割符号) # 使用分割符号对字符串进行分割,返回列表,列表每个元素就是分隔符两边的数据
join(列表容器) # 和split相反,把一个列表拼接成字符串
字符串判断方法
isdigit() # 判断字符串是否全部由数字组成
用法
- 要把字符串转成数字类型,就可以先用isdigit判断一下
- 判断用户是否输入的是数字
if passwd.isdigit(): print(f'密码是:{passwd}')
列表
一种容器,用一个容器存储多个信息
name = ['a', 'b', 'c'] # 列表定义
列表的索引从0开始
print(name[0]) # 打印第一个元素
# 遍历列表
while i < len(name):
print(name[i])
i += 1
for i in names:
print(i)
列表的操作(增删改查)
查询:
a[索引下标]
# 基于列表下标len(列表名称)
# 求容器长度in方法
# 可以在字符串、列表、元组中使用,if 元素 in 数据容器 # 判断元素是否在容器中出现
增加
- append() # 追加操作,一个元素一个元素增加,方法本身不返回任何内容,所以追加完后要打印原列表
- 例如
list.append('孙权')
- 例如
- +加号 # 可以把两个列表进行合并操作
- 例如
print(list2 + list3)
- 例如
删除
- remove() # 根据元素删除元素,方法本身不返回任何内容
- 例如list1.remove(20)
修改
- 基本方法:
列表名称[索引] = 修改的值
例如list1[0] = '刘禅'
- 翻转与排序方法
- 翻转:
reverse()
:相当于切片中的[ : :-1]
list.reserve()
=list[: :-1]
- 排序:
sort(reverse=False)
:把列表的元素从小到大排序,该参数可以从大到小排- 关于字符串列表的排序?
- 翻转:
列表的嵌套
a = [[], [], []]
print(a[0])
print(a[1][0])
错题:
names = ['A','B','C','D','E','F','G','H'] for name in names: index = random.randint(0,2) offices[index].append(name)
# 将价格列表按升序排序
prices.sort()
print("升序排序后的价格列表:", prices)
元组
元组和列表的区别:元组不能进行修改和删除
列表是灵活的数据类型,能进行增删改查
元组的定义 ()
元组是一种数据类型,
可以在一个变量中同时保存多个数据
元组在定义完成后就不能修改
tuple1 = (10, 20, 30)
tuple2 = (10, )
# 如果但单元素的元组必须加一个逗号,不然就不是元组类型
print(tuple1)
for i in tuple1:
print(i)
print(tuple1[2]) #**第三个元素**
工作中的应用场景
- 函数的参数和返回值,一个函数可以接受任意多个参数,或者依次返回多个数据(了解)
def func(参数1,参数2,参数3):
return返回值1,返回值2,返回3 - 格式化字符串,百分号和format,格式化字符串后面的()本质上就是一个元组
print("姓名:%s,年龄:%d,家庭住址:%s’% (name,age,address)) - 让列表不可以修改,以保护数据安全
- python操作mysgl数据库,返回结果,默认也是元组类型
元组的操作方法(只能查询)
bb = a[index] # 访问元组中的某个元素
len(a) # 求元组中元素个数(总长度)
if x in a: # 判断x是否在元组a中
字典!!!
学习要求
字典、集合的定义和应用场景
数据容器的公共方法
列表推导式编写(简化代码)
字典定义
一个变量中同时保存多个值就成为容器
保存某一个事物的信息,可以体现出事物的信息
key不一定要是字符串
字典名称 = {key: value, key:value}
索引没有索引下标,key等价于索引下标
key是唯一的,
没有顺序要求
print(字段名称['key'])
常见问题
- 字典不允许切片
- 创建有数据的字典,只能通过{}大括号,不能通过
dict()
方法dict()
用来转换类型和创建空字典
- 字符串加引号,数字不用加引号
增删改查(相同语法)
字典名称[key] = value
如果字典中没有这个key,以上就是一个新增操作
如果字典中有这个key,以上就是修改操作
删除
del 字典名[key]
查询
- 获取字典中的某个元素,字典名称[key],代表访问指定的元素
- 字典也支持直接打印输出
- 字典也可以配合for循环进行遍历,但是要特别注意:只有字典中的key可以遍历出来(默认)
for key in dic:
print(key) # 打印键
print(dic[key])
其他方法
- keys():以列表方式返回字典中所有的key键
- values():以列表方式返回字典中所有的vaLue值
- items():以外面是列表,里面每一个元素都是元组的方式获取字典中的key,,value键值对=>[(key1,vaLue1),(key2,value2)]
注意:以上三个方法很少单独使用,都要配合for循环进行遍历操作
例如:!!!‼️❗
❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗
# ③使用for循环直接对字典进行遍历
for key in student:
print(key)
# 在④使用keys方法获取字典中所有的key键与上面的代码等价
for key in student.keys():
print(key)
# 使用vaLues()方法获取字典中所有的vaLue值
for value in student.values():
print(value)
# 使用items()方法获取字典中的key,vaLue键值对
for key, value in student.items():
print(f'{key}: {value}')
❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗
列表和字典的结合
- 列表:特别适合保存多个数据
- 字典:特别适合保存一个事物的信息,如一个人、一本书、一个商品等等
- 把列表+字典结合起来就可以同时保存多个事物的信息
字典的 get() 方法,用于安全地获取字典中的值
dic.get(key) 是字典的 get() 方法,用于安全地获取字典中的值。
集合
定义:集合(set)是一个无序的不重复的元素序列(天生去重)
dic1 = set{} # 定义空字典,不能使用大括号来定义集合
set1 = set() # 定义空集合
都是用大括号,如何区分字典和集合:看里面的数据结构,键值对和具体的值的区别
# 1、空集合的定义
set1 = set()
print(type(set1))
# 2、定义一个有数据的集合
set2 = {10, 20, 30, 40, 20, 50}
print(type(set2))
# 3、Set()方法也可以把其他类型的数据转换为集合,如字符串
set3 = set('abcdefg')
print(set3)
print(type(set3))
# 4、集合中元素的访问:由于集合中的数据没有顺序,所以其没有索引下标,数据的访问有两种方案
#①直接打印
print(set2)
#②使用for微环对其进行遍历操作(只能使用for循环)
for i in set2:
print(i)
集合的操作方法(增、删、查,没有改!)
增加方法:
add()
set1.add(10)
删除方法:
remove(),删除指定元素
set1.remove(20)
pop():随机删除一个元素,方法返回那个元素(列表中默认删除最后一个值)
set1.pop(索引)
# 列表可以用
查询方法:
if x in set: 但会True和False
数据容器的公共方法
+
合并:字符串、列表、元组
*
复制:字符串、列表、元组
[1,2,3]*3 = [1,2,3,1,2,3,1,2,3]
in
判断元素是否存在:字符串、列表、元组、字典、集合
max()
返回容器最大值:列表、元组、集合
max = max(list1)
min()
最小值:列表、元组、集合
数据容器的相互转换
原来的基本数据类型转换
int()
:把其他数据类型转换为int整数类型
float()
:把其他数据类型转换为fLoat浮点类型
str()
:把其他数据类型转换为str字符串类型
eval()
:只能转换字符中类型的数据,相当于把宁符中类型的数据转换为原数据类型(长得想什么就转换成什么)
容器的转换方法
list()
:把其他数据类型转换为list列表类型=>用来修改元组
tuple()
:把其他数据类型转换为tupLe元组类型=>转成元组来保护数据
set()
:把其他数据类型转换为set集合类型=>用于去重
去重:set5 = list(set(list5))
int():转整数类型
float():转小数类型
str():转字符串类型
eval():只能对字符串进行转换,相当于把字符串转换为原数据类型
eval('10') => int
eval('9.88') => float
eval('[{},{},{}]') => list
注意!!
集合和列表的方法:
pop():随机删除一个元素,方法返回那个元素(列表中默认删除最后一个值)
set1.pop(索引)
# 列表可以用
推导式(数据容器)
推导式comprehensions(又称解析式),是Python的一种独有特性。推导式是可以从一个数据序列构
建另一个新的数据序列(一个有规律的列表或控制一个有规律列表)的结构体。共有三种推导:列表
推导式、集合推导式、字典推导式。
[1, 2,3]推导式[1,4,9]
属于锦上添花的代码,主要负责把一个有规律的数据序列推导为另外一个有规律的数据序列
# 生成一个0-9的列表
# for循环
list = []
for i in range(10):
list.append(i)
# 简化为推导式
list = [i for i in range(10)]
推导式语法
变量名 = [表达式 for 变量 in 列表]
变量名 = [表达式 for 变量 in 列表 if 条件]
# 生成0-9所有的偶数
list = [i for i in range(10) if i % 2 == 0]
# 列表所有元素平方
list = [i ** 2 for i in range(10)]
代码调试 debug
pycharm的
step over:代码一步一步向下执行,遇到
函数则直接返回函数执行结果,不进入到
函数的内部
step into:代码一步一步向下执行,遇到
函数则直接进入到函数的内部
python函数⭐⭐⭐⭐⭐⭐⭐⭐
直接上实际例子:
#1、封装一个函数,生成4位长度的随机验证码
def func():
#第一步:定义一个字符串,用于生成验证码
str1 = '23456789abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ'
#第二步:定义一个空字符串,专门用于接收4位长度的验证码
code = ''
#第三步:生成4位长度的验证码其实就是循环4次,每次循环时要做两件事
#第一件事:从str1中随机获取一个字符
#第二件事:把获取到的随机字符,追加到code空字符串中
for i in range(4):
#第五步:如何从str1中抽取一个随机字符?答:使用索引随机
randnum=random.randint(0,len(str1))-1)
#第六步:把每次得到的随机字符拼接到code变量中
code += str1[randnum]
#第七步:把得到的结果作为函数的返回值
return code
#2、调用func函数
print(func())
函数基本概念
函数的学习目标
- 函数的作用及其使用步骤
函数的说明文档(学会阅读)
函数的嵌套
函数的应用案例(了解参数和返回值) - 变量的作用域
- 函数参数进阶
- 引用变量及可变类型、非可变类型
函数的作用和使用步骤
把一种功能的实现用函数封装起来,以便于重复调用,对于大型项目,函数就是一个个小积木
- 实现代码重用
- 模块化编程(面向过程)
什么是函数:函数是一个被命名的、独立的、完成特定功能的代码段,其可能给调用它的程序一个返回值。
函数定义和调用:
def 函数名(形参):
函数体
...
return 返回值
函数名(实参)
强调:函数在定义时,只是向内存中保存了一个函数的名称其内部的代码并没有真正的执行
def greet(name):
return '您好,' +name #返回值
print(greet('fuck'))
关于返回值:
- return后直接返回,函数结束
- return可以返回多个结果(以元组形式返回多个值)(仅在python中可以返回多个值)
- 没有return就不返回值(返回None)
函数的说明文档
使用一对三引号
函数的说明书,函数怎么用,有哪些参数和输出
def 函数bb(参数):
"""
函数的说明文档:
函数是干嘛的
有哪些参数
最终返回值
"""
# 快速查看函数的说明文档:
help(函数bb)
python所有系统函数都有说明文档,不会用都可以看说明文档,还有python官网的文档连接(有中文)
pycharm中查看说明文档按ctrl+Q
函数嵌套
举栗子
def testB():
print('testB start
print('testB函数体代码...
print('-testB end
#2、定义testA函数
def testA():
print('testA start
#所谓的嵌套就是在一个函数的内部又调用了另外一个函数
testB()
print(testA end
#3、执行testA函数
testA()
变量作用域(局部变量、全局变量)⭐⭐
局部变量和全局变量
函数外部区域是全局作用域(全局变量),函数内部区域的局部作用域(局部变量)
访问范围
局部变量
局部变量只能在局部作用域中访问
函数执行完毕后会垃圾回收
全局变量
全局访问
global关键字(只能用来申明)
!!不能这样:global num = 100
全局变量可以在局部作用域中访问但是不能修改
在局部作用域中对全局变量的修改
num = 10
def func():
num = 100 # 如果只是num = 100 那就是定义一个新局部变量,函数结束后回收掉
func()
print(num) # 输出10
对全局变量的修改👇(必须先申明全局变量)
# 修改全局变量
num = 10
def func():
global num # 声明全局变量
num = 100 # 如果只是num = 100 那就是定义一个新局部变量,函数结束后回收掉
func()
print(num) # 输出100
注意!!
global关键字只是针对不可变数据类型的变量进行修改操作(数值、字符串、布尔类型、元组类型),可变类型(字典、列表、集合)可以不加global关键字。
函数的参数进阶(实参、形参)⭐⭐⭐
形参、实参是什么??
形参:在函数定义时,所编写的参数就称之为形式参数(本质是个局部变量)
实参:在函数调用时,所传递的参数就称之为实际参数
函数调用的参数
位置参数、关键词参数
# 2、在函数调用时,函数一共有3个参数,所以调用时也需要传递3个参数,但是传递过程中有两种传递方式:①位置传参②关键词传参
#①位置传参,根据函数定义时参数的位置传递参数的值(强调参数的位置,顺序不能颠倒)
func('Tom',23,'10086')
#②关键词传参,根据”参数=值"方式来实现对参数的传递,优势:不需要考虑位置关系,只要参数名称没错,任何位置都可以
func(name='Jack', mobile='10010', age=19)
函数定义时参数的类别
在Python代码中,函数定义时的参数一共有3种类别:
- 普通参数,如
def func(name,age,mobile)
- 缺省参数(默认值参数),如
def func(name,age,gender='male')
- 不定长参数,如
def func(*args,**kwargs)
不定长参数
不定长参数也叫可变参数。用于不确定调用的时候会传递多少个参数(不传参也可以)的场景。
此时,可用包裹(packing)位置参数,或者包裹关键字参数,来进行参数传递,会显得非常方便。
*args
:不定长位置参数(不定长元组参数),*args
代表固定格式,args
代表变量的名称,可以接受列表形参(看下面的面试题)
def func(*args): # 接收的是元组
print(args)
func(1, 2, 3) # 输出的是(1, 2, 3)
**kwargs
:不定长关键词参数(不定长字典参数),**kwargs
代表固定格式,kwargs
代表变量名称,主要用于接收不定长关键词参数,可以接受字典形参(看下面的面试题)
关键词参数
def func(**kwsrgs):
print(kwargs)
func(a=1, b=2, c=3) # 输出的是字典{'a':1,'b':2,'c':3}
不定长参数应用场景
在实际Python开发工作中,*args
与**kwargs
还可以结合在一起使用!
注意事项:*args
必须放在左边,**kwargs
必须放在右边
def func(*args,**kwargs):
print(args)
print(kwargs)
func(1, 2, 3, a=4, b=5)
面试题
#需求:请封装一个函数,用于接收List1与dict1的值,然后对其进行求和操作,函数最终返回结果为1+2+3+4+5
def func(*args,**kwargs):
sum = 0
for i in args:
SUm += i
for value in kwargs.values():
sum += value
print(sum)
list1=[1,2,3]
dict1={'a':4, 'b':5}
func(*list1,**dict1)
参数混用
普通参数、缺省参数、不定长参数的混用,必须按顺序使用
①普通参数
②*args
③缺省参数
④**kwargs
def func(①普通参数②*args③缺省参数④**kwargs)
混用情况的省略参数必须用关键词方式赋值
def func(a, b, *args, c=4, **kwargs):
func(1,2, 3, c=100, d=5,e=6)
变量的可变、不可变类型⭐⭐
标准数据类型
Python3 中常见的数据类型有:
- Number(数字)
- String(字符串)
- bool(布尔类型)
- List(列表)
- Tuple(元组)
- Set(集合)
- Dictionary(字典)
Python3 的⑦个标准数据类型中:
- 不可变数据(4 个): Number(数字)、String(字符串)、Tuple(元组)、布尔;
- 可变数据(3 个): List(列表)、Dictionary(字典)、Set(集合)。
不可变数据类型
举栗子:👇
num1 = 200
num2 = num1
num2 = 100
"""
这里num2是100,但是num1还是200,因为不可变数据类型赋值都是指针指向新内存空间,num1指向值为200的内存空间始终没变,变得是num2的指针。。。。。。
"""
再举例子,这里用了新的id()
方法(查看内存地址)
num = 10
print(num)
print(id(num)) # 打印变量的内存地址:....0001
num2 = 10
print(id(num2)) # ....0001
num = 100
print(id(num)) # ....0002
# 探讨一种情况:
# 假设把变量num1赋值给变量num2,两者是什么关系呢?
# 结论:
# 如果把num1赋值给num2,相当于两者指向了相同的内存空间
# 问题:如果这个时候我更新了变量num1的值为100,问num2是否会受到影响
# 答:不会受到影响,因为数值10是一个数值类型=》不可变类型,一旦内存地址固定了,则里面的值就不能改变了,所以当我
# num1重新赋值,相当于在内存中新开辟了一块空间保存100,这num1和num2指向了不同的空间。所以不会产生任何影响
所谓的不可变类型就是当这个地址一旦固定,则其值无法改变的数据类型=>不可变类型
czc:要修改值,那就是在内存空间中新开一个空间放这个新值,然后把指针指向新的内存空间。所以对于函数接收的不可变数据类型就相当于一个新的变量指向这个值,当对他修改,就是新变量指针指向新值,这时候接受进来的老变量的指针还是指向原来的内存空间。所以这就是局部变量修改不会影响全局变量的原因,
要修改不可变数据类型就必须要提前声明global
[!NOTE] gpt纠正
对于不可变数据类型(如整数、浮点数、字符串、元组等),当你尝试在函数内部修改这些数据时,实际上是创建了一个新的对象,并将局部变量的引用指向这个新对象。原始的全局变量不会受到影响,除非你使用 global 关键字显式地声明它,这样你就可以在函数内部修改全局变量。这是因为不可变对象不能被改变,每次修改都会生成一个新的对象。
不可变类型包括:数值类型、布尔类型、字符串类型、元组类型
比如原来这块空间里面放了数字10,想把它设置为100,不行,因为这块空间无法调整!
可变数据类型
所谓的可变数据类型就是内存地址一旦固定,其值是可以发生改变的
列表、字典、集合类型
#定义一个函数
def func(names2): # names1和局部变量name2都指向相同内存空间
#局部作用域
names2.append('赵六')
#定义一个全局变量
names1 = ['张三',‘李四',‘王五']
#调用函数
func(names1)
print(names1) # 选择题:A.[张三李四王五] B。[张三李四王五赵六]
czc:对于可变数据类型就不会受全局变量和局部变量作用于的影响,传入可变数据类型相当于新建一个变量指针指向那片内存空间,但是那个内存空间里的值是可修改的,所以可以直接修改,不用新开辟内存空间后修改指针,所以在局部作用域中可变数据类型的修改可以影响全局作用域
[!NOTE] gpt纠正
对于可变数据类型(如列表、字典、集合等),当你在函数内部修改它们时,你实际上是在修改原始对象。这是因为可变对象可以被改变,所以不需要创建新的对象。即使在函数内部,你也是在操作同一个对象的引用。
元组拆包 ⭐
应用:
- 接受多返回值的函数
- 交换两参数
把元组的元素一个一个拆解出来
tuple1 = (10, 20)
a, b = (10, 20) # 也可以不写括号,同样本质是元组
# 用来交换
c1 = 10
c2 = 20
c1, c2 = c2, c1 # 不写括号也是元组
# 用来接收多参数返回的函数
a, b, c = fun(x)
文件基本操作⭐
学习目标
1.了解文件操作的作用
2.掌握文件的基本操作如打开、读写、关闭等
3.掌握Python操作文件和文件夹的方法
4.能独立完成文件操作案例的编写
文件操作的目的是实现文件的永久保存
基本的基本操作
文件操作三步走
- 打开文件:
open(name, mode)
- name 代表要打开的文件路径 + 文件名
- mode 代表访问模式:
r/w/a
(模式不止这三个还有很多很多),看下下面的细说r
:read,只读模式,代表只能对文件进行读取,属于默认模式,如果要访问的文件不存在,则直接报错!w
:write,只写模式,代表只能对文件进行写入操作,如果访问的文件不存在则自动创建,写入数据到文件时,会覆盖源数据!(只会创建文件,不会创建文件夹❗)a
:append,追加模式(只写模式的一种),与w类似,如果文件不存在则创建,写入数据到文件时不会覆盖源数据而是在后面追加
open()
方法打开的文件返回的是一个文件对象(句柄)(对象的概念后面再学),之后对文件的操作都是对这个对象来操作f = open('python.txt','r',encoding='utf-8')
- 读写文件
f.write(content)
只能把字符串类型的数据写入到文件中f.write('fuck you')
- 关闭文件(释放内存空间)
f.close()
读取文件方法
打开文件 f = open()
→ 读取文件 → 关闭文件
read()
:一次性读取全部内容
- 参数是指定读取多少个字符
read(1)
,代表读取1个字符,不指定就是读取所有内容
f = open('python.txt','r', encoding='utf-8')
content = f.read() #读取文件所有内容
content = f.read(1) #代表只读取文件中的一个字符
print(content)
f.close
readlines()
:读取所有内容成列表,每个元素都是文件中的一行
- 只适合读小文件!
f = open('python.txt', 'r', encoding='utf-8')
content = f.readlines(
print(content)
f.close()
readline()
:一行一行读取,
.readline()
一次就读一行(读取一次向后移动一次),直到文件读取完毕,通常配合while True:
使用
f = open('python.txt', 'r', encoding='utf-8′)
while True:
content = f.readline()
#判断,如果读取不到任何内容,则结束循环
if not content:
break
#反之,如果没有执行break,则代表文件中还有内容
print(content, end='') # 思考为什么要 end=''
print(content)
f.close()
注意!编码问题 ⭐
txt打开默认用utf8编码,python(大多数编程语言)输出的编码默认是ASCII编码
国际化组织 编码标准unicode → UTF-8
打开和写入要指定编码格式
f = open('python.txt','w',encoding='utf-8')
文件访问方式(mode)
r:只读
w:只写
a:追加
+:(增加读写功能 )加号代表既可以读取也可以写入
b:binary缩写形式,以二进制流的方式读取文件或写入数据到文件
rb
wb
ab
以上rb、wb、ab不仅可以针对文本文件,还可以针对图片、音频、视频文件进行读写操作
应用:文件备份
test.txt => test[backup].txt
104-1-find()方法
# find方法找后缀
oldname = 'test.txt' 拆解文件名与文件的后缀
index = oldname.rfind('.')
#获取文件名称
filename = oldname[:index] # 切片只管前不管后 => test
postfix = oldname[index:] # => .txt
# 拼接新文件名
newname = filename + '[backup]' + postfix
# 创建文件句柄
old_f = open(oldname, 'rb') # 二进制流形式读
new_f = open(newname, 'wb') # 二进制流形式写
# 大文件分块读
while True:
content = old_f.read(1024)
if not content:
break
new_f.write(content)
# 关闭文件
old_f.close()
new_f.close()
进阶一点的文件操作(文件夹)
使用os模块
文件操作
os.rename(旧文件名称,新文件名称)
os.remove('要删除的文件名称')
文件夹操作
os.mkdir(新文件夹名称) # 创建一个指定名称的文件夹
os.getcwd() # current work directory,获取当前工作目录名称
os.chdir(切换后目录名称) # change directory,切换目录
os.listdir(目标目录) # 获取指定目录下的文件信息,返回列表
os.rmdir(目标目录) # 用于删除一个指定名称的"空"文件夹
例子
# 获取当前目录
print(os.getcwd())
# 切换当前工作目录
os.chdir('data')
# 创建文件夹
if not os.path.exists('image')
os.mkdir('image')
# 获取一个目录下的所有文件
files = os.listdir()
print(files)
# 删除文件夹/目录
if os.path.exists('test')
os.rmdir('test')
路径
python路径用’/’
相对路径
方便后期代码的迁移
相对路径的参考点就是代码文件本身
同级关系的访问:
./python.txt
python.txt
上级关系:../python.txt
下级关系:data/python.txt
./data/python.txt
绝对路径
不方便后期代码迁移
递归删除文件夹-shutil模块
import shutil
使用慎重!
非空目录不能删除文件夹,要强行删除就要用:
shutil.rmtree('data')
进目录一个一个删掉后再删除目录
python中的异常 ⭐
罗列捕获异常的语法结构,知晓异常捕获的使用场景
什么是异常:当检测到一个错误(不是语法错误)时,解释器就无法继续执行了,反而出现了一些错误的提示,这就是所谓的"异常"。
异常≠错误
异常往往是由于输入信息异常或者未知的结果导致程序无法执行!
除数为0异常:
读取文件异常:FileNotFoundError
No such file or directory
异常捕获方法
完整方法
try:
可能出现异常的代码
except Exception as e: # 不需要获取异常信息的话"Exception as e"可以不写
如果try语句中的代码出现了异常,则立即执行后续代码
print(e) # 实际工作中可以写入到日志中
else:
当try语句中的代码没有出现异常,则执行else语句中的代码,反之,则不执行
finally:
特别适合实现一些收尾的工作,因为它是无论是否异常都会执行的代码=>f.close()
捕获异常获取错误信息
把异常信息写入日志文件(某天某日某时出现某错误)
try:
A 方案 可能出现异常的代码
except Exception as e:
B 方案 如果try语句中的代码出现了异常,则立即执行后续代码
print(e) # 实际工作中可以写入到日志中
!!例子
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except ZeroDivisionError:
return "除数不能为零"
except TypeError:
return "类型错误"
except ValueError:
return "值错误"
except (IndexError, KeyError):
return "索引或键不存在"
except Exception as e:
return f"未知错误: {type(e).__name__} - {str(e)}"
return wrapper
常用错误
exceptions_dict = {
"ZeroDivisionError": "除零错误 - 当除数为零时",
"TypeError": "类型错误 - 当操作或函数应用于不适当类型的对象时",
"ValueError": "值错误 - 当操作或函数接收到类型正确但值不适当的参数时",
"IndexError": "索引错误 - 当序列下标超出范围时",
"KeyError": "键错误 - 当字典中找不到指定的键时",
"FileNotFoundError": "文件未找到错误 - 当试图打开不存在的文件时",
"IOError": "输入/输出错误 - 当输入/输出操作失败时",
"NameError": "名称错误 - 当使用一个未定义的变量时",
"AttributeError": "属性错误 - 当对象没有指定的属性或方法时",
"SyntaxError": "语法错误 - 当代码不符合Python语法规则时",
ImportError: 导入错误:循环导入会导致
}
python的模块和包 ⭐⭐
模块分为内置模块和自定义模块
python的内置模块
import导入的都是模块,是一个python文件,模块能定义变量、函数、类
python的自定义模块
自己或者别人写的的模块,都是.py文件
不要和系统变量重名
导入模块方式
编写的每个文件都可以import导入
import * as a # 导入所有
from * import * # 用什么导入什么
time模块
随机模块 random
使用__name__对模块进行测试
代码在当前文件能执行,被被的代码导入的时候不执行:
用:
if __name__ = '__main__':
# 此代码只会在本代码中执行
魔术变量:__name__
- 随着运行环境的不同,返回的结果也不同(结果是字符串)
- 当被导入是
__name__
是本页面的文件名称,不等于__main__
OK,结束
未来的大饼👇
面向对象、魔法方法、封装与继承、多态、类属性方法、闭包、装饰器、前端(HTML、CSS)、网络编程(Socket、TCP服务器、http协议、静态Web服务器)、进程线程
python生成器、Python深浅拷贝、正则表达式、Python爬虫、数据可视化、日志