Python语法1
Python语法1
作者:王珂
邮箱:49186456@qq.com
文章目录
- Python语法1
- @[TOC]
- 前言
- 一、环境搭建
- 1.1 安装Python解释器
- 1.2 安装第三方包
- 1.3 安装Pycharm
- 1.4 虚拟环境
- 二、Python语法
- 2.1 基础语法
- 2.1.1 注释
- 2.1.2 变量
- 2.1.3 数据类型
- 2.1.4 关键字和标识符
- 2.2 输出
- 2.2.1 %格式化输出
- 2.2.2 f-strings格式化输出
- 2.2.3 print函数
- 2.3 输入
- 2.4 运算符
- 2.4.1 算术运算符
- 2.4.2 赋值运算符
- 2.4.3 符合赋值运算符
- 2.4.4 比较运算符
- 2.4.5 逻辑运算符
- 2.4.6 三目运算符
- 2.5 分支语句
- 2.6 循环语句
- 2.6.1 for循环
- 2.6.2 while循环
- 2.7 容器类型
- 2.7.1 字符串
- 2.7.2 列表
- 2.7.3 元组
- 2.7.4 集合
- 2.7.5 字典
- 2.7.6 容器公共运算符
- 2.7.7 容器公共函数
- 2.8 函数
- 2.8.1 函数定义
- 2.8.2 函数参数
- 函数调用时不用关系形参的位置
- 2.8.3 函数返回值
- 2.8.4 函数作用域
- 2.8.5 函数执行流程
- 2.8.6 组包和拆包
- 2.8.5 引用
- 2.8.6 lambda表达式
- 2.8.6 可变与不可变数据类型
- 2.8.7 闭包
- 2.8.8 装饰器
- 2.9 异常
- 2.9.1 异常捕获
- 2.10 模块
- 2.10.1 模块导入
- 2.10.2 自定义模块
- 2.11 包
- 3. 文件
- 3.1 文件读写
- 3.1.1 文件模式
- 3.1.2 读取文件
- 3.1.3 写入文件
- 3.1.4 移动光标
- 3.2 文件操作
- 3.3 文件夹操作
- 其它
文章目录
- Python语法1
- @[TOC]
- 前言
- 一、环境搭建
- 1.1 安装Python解释器
- 1.2 安装第三方包
- 1.3 安装Pycharm
- 1.4 虚拟环境
- 二、Python语法
- 2.1 基础语法
- 2.1.1 注释
- 2.1.2 变量
- 2.1.3 数据类型
- 2.1.4 关键字和标识符
- 2.2 输出
- 2.2.1 %格式化输出
- 2.2.2 f-strings格式化输出
- 2.2.3 print函数
- 2.3 输入
- 2.4 运算符
- 2.4.1 算术运算符
- 2.4.2 赋值运算符
- 2.4.3 符合赋值运算符
- 2.4.4 比较运算符
- 2.4.5 逻辑运算符
- 2.4.6 三目运算符
- 2.5 分支语句
- 2.6 循环语句
- 2.6.1 for循环
- 2.6.2 while循环
- 2.7 容器类型
- 2.7.1 字符串
- 2.7.2 列表
- 2.7.3 元组
- 2.7.4 集合
- 2.7.5 字典
- 2.7.6 容器公共运算符
- 2.7.7 容器公共函数
- 2.8 函数
- 2.8.1 函数定义
- 2.8.2 函数参数
- 函数调用时不用关系形参的位置
- 2.8.3 函数返回值
- 2.8.4 函数作用域
- 2.8.5 函数执行流程
- 2.8.6 组包和拆包
- 2.8.5 引用
- 2.8.6 lambda表达式
- 2.8.6 可变与不可变数据类型
- 2.8.7 闭包
- 2.8.8 装饰器
- 2.9 异常
- 2.9.1 异常捕获
- 2.10 模块
- 2.10.1 模块导入
- 2.10.2 自定义模块
- 2.11 包
- 3. 文件
- 3.1 文件读写
- 3.1.1 文件模式
- 3.1.2 读取文件
- 3.1.3 写入文件
- 3.1.4 移动光标
- 3.2 文件操作
- 3.3 文件夹操作
- 其它
前言
本文主要介绍Python的基础语法,以便在日后的工作中查阅参考。
官网:
https://www.python.org/
Python的作者Guido von Rossum(吉多·范·罗苏姆),中国Python程序员都叫他 龟叔,荷兰人。
-
1991年,第一个Python编译器诞生。它是用C语言实现的,并能够调用C语言的库文件。从一出生Python已经具有了:类,函数,异常处理,包含表和词典在内的核心数据类型,以及模块为基础的拓展系统。
-
Python从一开始就特别在意可拓展性。Python可以在多个层次上拓展·从高层上,你可以直接引入.py文件·在底层,你可以引用C语言的库。Python程序员可以快速的使用Python写.py文件作为拓展模块,但当性能是考虑的重要因素时,Python程序员可以深入底层,写C程序,编译为.so文件引入到Python中使用·Python就好像是使用钢构建房一样,先规定好大的框架。而程序员可以在此框架下相当自由的拓展或更改。
-
Python支持解释运行,并能调用C库进行拓展。Python有强大的标准库。由于标准库的体系已经稳定,所以Python的生态系统开始拓展到第三方包。这些包,如Django、web.pywxpython、numpy、matplotlib、PlL·将Python升级成了物种丰富的热带雨林。
Python的版权:开源、免费;
Python解释器
Python是一个解释型语言,Python的解释器有多个语言实现
-
CPython: 官方的解释器,使用C语言实现。
开发中使用的是3.6之后的版本,使用最多的是3.7, 3.8, 3.9。
-
JPython: 使用java语言实现的Python解释器,效率低于CPython,但是多任务模式性能优化明显。
-
icornPython: CPython解释器的升级版本,能够提供部分交互效果。
-
PyPy:Python实现的,支持JIT即时编译。
-
lronPython:可以运行在.NET和Mono平台。
一、环境搭建
1.1 安装Python解释器
1.2 安装第三方包
Python包的概念见2.11章节
包是一类模块的集合,每个模块包含了很多功能。在Python的生态中,有许多第三方包,如下:
-
numpy 科学计算
-
pandas 数据分析
-
pyspark, apache-flink 大数据计算
-
matplotlib, pyecharts 图形可视化
-
tensorflow, pytorch 人工智能
第三方的包需要安装后才可以导入使用
安装第三方包
Python内置的pip程序用于安装第三方包
pip install 包名称
默认从官方地址安装,在国内会比较慢,可以选择从国内地址安装
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple 包名称
清华Python包安装地址是清华大学提供的一个网站,可供pip程序下载第三方包
配置永久从镜像源下载
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
1.3 安装Pycharm
- 配置系统解释器
File -> Settings -> Project: [项目名称]
2. 在pycharm中安装第三方包
1.4 虚拟环境
可用创建python的虚拟环境,在虚拟做的操作(如安装第三方包)只对虚拟环境有效,不会影响原有环境
安装虚拟环境程序
pip3 install virtualenv
会在python安装目录的Scripts目录下安装virtualenv.exe
构建虚拟环境
1)创建目录D:\opt\Python\VirtualEnv
2)切换到该目录
cd D:\opt\Python\VirtualEnv
3)执行命令
# virtualenv -p 虚拟环境的版本 虚拟环境的名称
virtualenv -p D:\opt\Python\Python310\python.exe myenv
4)激活虚拟环境
cd D:\opt\Python\VirtualEnv\myenv\Scripts
activate
5)退出虚拟环境
deactivate
二、Python语法
2.1 基础语法
2.1.1 注释
-
单行注释
# 这是单行注释
-
多行注释
""" 多行注释可以用三对单引号,也可以用三对双引号书写。 多行注释不能写在在行尾。 """
2.1.2 变量
变量名 = 值
2.1.3 数据类型
1)不同的数据类型保存在不同的区域
2)不同的数据类型使用的数据结构不同
3)不同的数据类型占用的空间大小不同
4)不同的数据类型具备的功能不同
基本数据类型
-
int
-
long
-
float
-
bool
True, False
string类型
-
‘’
-
“”
list(数组)
list1 = [1, 2, 3, 4, 5]
set(集合)
set1 = {1, 2, 3, 4, 5}
tuple(元组)
tuple1 = (1, 2, 3, 4, 5)
dict(字典JSON)
dict1 = { a: '1', b: '2' }
数据类型的转换
数据类型转换函数
- int()
s_age = '41'
n_age = int(s_age)
-
float()
-
str()
-
eval()
去除字符串左右两边的引号,剩余的内容是什么就是什么类型。
str1 = '10' eval(str1) # 结果为int,值为10 str2 = '20.1' eval(str2) # 结果为flot,值为20.1
2.1.4 关键字和标识符
关键字
标识符
1)由字母数字下滑线组成
2)不能以数字开头
3)严格区分大小写
4)不能使用关键字
标识符的命名规范
-
下划线分割法
Python中的变量名,函数名,方法名,文件名等使用下划线分隔法
-
大驼峰
-
小驼峰
2.2 输出
2.2.1 %格式化输出
格式:‘要输出的字符信息 %占位符’ % 变量
格式化符号 | 转换 |
---|---|
%s | 字符串 |
%d | 有符号的十进制整数 |
%0xd | 不足x位的前面补0,超出时原样输出 |
%f | 浮点数 |
%.xf | 保留x位小数(会进行四舍五入) |
%c | |
%u | |
%o | |
%x | |
%X | |
%e | |
%E | |
%g | |
%G |
print('老王今年%d岁了' % 41)
str1 = '老王今年%d岁了' % 41
多占位符格式化输出
在格式化输出时,百分号%后面只能跟一个参数,多个参数时要用()括起来。
‘格式化字符串 %占位符1, %占位符2, …’ % (变量1, 变量2, …)
name = '老王'
age = 41
gender = '男'
print('%s是%s性,今年的年龄是%d' % (name, gender, age))
注意:
注意:多占位符格式化字符串时,要注意:
1)占位待的数量和变量的数量必须保持一致,不能多,也不能少
2)位符与变量顺序要依次对应,不能交又赋值也不能跳跃
3)赋值占位符与变量一定要数据类型完全对应
4)在格式化字符串时,百分号后只能有一个数据,所以如果有多个变量需要使用括号括起来
2.2.2 f-strings格式化输出
f-strings是python3.6以上的版本才支持
f-strings格式化输出字符穿,可以在字符串中包含Python表达式。f-strings以 f 为前缀,格式化字符串使用一对单引号,双引号,三引号格式化字符串。
# .2f表示:保留2位小数
# 03d表示:不足3位,前面用0补齐
print(f'老王的名字是{name},身高是{height: .2f}')
2.2.3 print函数
def print(self, *args, sep=' ', end='\n', file=None):
sep 打印多个值时用空格分割
end 打印结束时的输出(默认换行)
2.3 输入
input函数
def input(*args, **kwargs):
2.4 运算符
2.4.1 算术运算符
运算符 | 说明 | 示例 |
---|---|---|
+ | 加 | |
- | 减 | |
* | 乘 | |
/ | 除 | 9 / 4 = 2.5 注意:除法运算的结果是浮点型;有浮点型数据参与的运算,结果也为浮点型。 |
// | 整除 | 9 // 4 = 2 |
% | 取余 | 9 % 4 = 1 |
** | 指数 | 2 ** 3 = 8 |
() | 小括号 | 用来提升运算优先级 ( 1 + 2 ) * 3 = 9 |
算数运算符的优先级
** 高于 * / // % 高于 + -
2.4.2 赋值运算符
运算符 | 说明 | 示例 |
---|---|---|
= | 赋值运算符 | 把 = 号右边的结果赋给左边的变量 |
-
单个变量赋值
a = 1
-
多个变量赋值
num1 = num2 = num3 = 1
num1, num2, f1, f2, str1, str2 = 1, 2, 1.1, 2.2, 'name', 'wk'
2.4.3 符合赋值运算符
-
+=
-
-=
-
*=
-
/=
-
//=
-
%=
-
**=
2.4.4 比较运算符
运算符 | 说明 | 示例 |
---|---|---|
== | 等于 | |
> | 大于 | |
< | 小于 | |
>= | 大于等于 | |
<= | 小于等于 | |
!= | 不等于 |
如果数据类型不相同(除了int, float, bool),比较大小不成立
注意:在比较运算符中 0等于False, 1等于True
字符串比较大小
1)字符之间比较大小,是按照字符的ASCII编码序号进行比较的
2)字符串比较大小,字符串从左到右的字符依次比较,如果一个字符大则大
2)数字 < 大写字母 < 小写字母 < 汉字
ASCII(American Standard Code for Information Interchange) 美国标准信息交换代码,主要用于显示现代英语和其它西欧语言,是单字节编码系统。总共128位(0 ~ 127)
2.4.5 逻辑运算符
运算符 | 说明 | 示例 |
---|---|---|
and | 与 | |
or | 或 | |
not | 非 |
2.4.6 三目运算符
条件成立时的结果 if 条件 else 条件不成立时的结果
'我是wk' if 1 > 0 else '我不是wk'
2.5 分支语句
- 单条件分支语句
if 条件判断:
业务代码
1)if使用缩来控制范围。if中的所有代码缩进务必对齐
2)当取消缩进后,就不在if的控制范围之内了
3)if中必须有代码,否则报错
注意:python中没有{}来控制范围
- 对立条件分支语句
if 条件判断:
条件成立时代码
else:
条件不成立时代码
- 多条件分支语句
条件从上到下依次判断,当一个条件成立时,将不会继续判断后面的条件
if 条件判断语句1:
条件成立时代码
elif 条件判断语句2:
条件成立时代码
else:
条件都不成立时代码
python中条件语句使用的比较运算符可以连续使用
if 18 <= age <= 40:
...
- 分支语句的嵌套
if 判断条件语句:
条件成立时代码
if 判断条件语句:
条件成立时代码
else:
条件不成立时代码
2.6 循环语句
2.6.1 for循环
for … in
for 临时变量 in 容器类型数据:
循环体
range()函数
格式:range(起始位置, 中止位置, 步长) 注意:起始位置默认0,不含中止位置,步长默认1
for … in … else …
for 临时变量 in 容器类型数据:
循环体
else:
当容器类型的元素遍历完成后执行的代码(有break不会执行到这,但continue会)
break
break用于中止循环
continue
continue用于跳出本次循环,进入下次循环
2.6.2 while循环
while …
while 判断条件语句:
条件成立时的语句1
条件成立时的语句2
break
同上
continue
同上
while … else …
while 判断条件:
条件成立时的语句1
条件成立时的语句2
else:
循环正常结束之后执行的代码(有break不会执行到这,但continue会)
2.7 容器类型
容器类型就是可以保存多个数据或变量的数据类型。容器类型包括:字符串、列表、元组、字典、集合。
2.7.1 字符串
字符串的定义
-
‘’ 一对单引号
str1 = '离离原上草,' \ '一岁一枯荣!'
注意:\ 标记了下一行和上一行是同一行内容
-
“” 一对双引号
-
‘’’ 三对单引号(实际上也是多行注释)
-
“”" 三对双引号(实际上也是多行注释)
字符串的下标
str = ‘abc’
-
正数下标
正数下标从左到右,从0开始
str[0]为a, str[1]为b, str[2]为c
-
负数下标
负数下标从右到左,从-1开始
str[-1]为c, str[-2]为b, str[-3]为a
字符串的切片
切片格式:[起始下标: 结束下标: 步长]
1)省略起始下标,默认从起始下标开始
2)省略结束下标,默认从结束下标结束
3)省略步长,默认为1
str1 = '012345678'
print(str1[0:2:1])
-
正数步长
从左到右
-
负数步长
从右到左
# 字符串反转 str2 = [::-1]
str[:]相当于复制了字符串
字符串方法
-
find(self, __sub, __start, __end)
查找从左到右一个出现字符或字符串的位置,查询不到返回-1
self
__sub: 需要查找的字符或字符串
__start: 起始下标
__end: 结束下标
-
rfind()
-
index(self, __sub, __start, __end)
查找从左到右一个出现字符或字符串的位置,查询不到报错
-
rindex()
-
count()
-
replace(self, __old, __new, __count)
默认替换所有旧的字符或字符串
self
__old: 旧的字符或字符串
__new: 新的字符或字符串
__count: 替换次数
-
split(self, sep, maxsplit)
字符串的拆分为多个字符串,存放在列表中
self:
sep: 字符串拆分的分隔符。如果不传,按照空格、制表符和换行符拆分。
maxsplit: 最大拆分次数。从左到右拆分。
-
join()
根据指定字符将列表中的字符串合并为一个字符串
str1 = ['hello', 'world'] str2 = '-' str2.join(str)
-
count(self, x, start, end)
查询目标字符中有多少个子字符串
-
len()
两个下划线len两个下划线()
查询字符串的长度
len(字符串)
-
strip()
去掉字符串左右两边的指定字符,不传参数表示去除空白数据(空格, \n, \t)
-
upper()
-
lower()
-
title()
将每个单词的首字符大写,其余小写。判断是否为同一个单子的依据仅有一个,非字母当作分隔符。
-
capitalize()
整个字符串首字母大写
-
startswith()
-
endswith()
-
ljust()
指定字符串左侧对齐,不足用指定字符填充
-
rjust()
指定字符串右侧对齐,不足用指定字符填充
-
center()
指定字符串剧中对齐,不足用指定字符填充
-
isalpha()
是否都是字母
-
isdigit()
是否都是数字
-
isalnum()
是否是字母和数字
-
isnumeric()
-
isspace()
是否都是空格
-
isidentifier()
是否为标识符
2.7.2 列表
格式:变量名 = [ 列表1, 列表2, 列表3, … ]
列表类型可以存储任意类型的数据。
列表同样用索引获取数据:正数索引从左到右;负数索引从右到左;
list1 = [ 'hello', 12, True, 2.3, [1, 2, 3] ]
列表的长度
len(list1)
遍历列表
for i in list1:
print(i)
i = 0
while i < len(list1):
print(list1[i])
i += 1
查找
-
index(self, __value, __start, __stop)
查询列表中指定的第一个元素的索引
-
count()
查询元素在列表中出现的次数
增加
-
append()
在列表末尾添加元素
-
extend()
在列表的末尾将容器类型的数据展开,追加到列表末尾
-
insert(self, __index, __object)
在指定的索引位置插入一个元素。其它元素向后移动一位,下标自动增长。
判断
-
in
判断元素是否在容器中
4 in list1
-
not in
与 in 相反
移除
-
pop(self, __index)
移除指定下标的元素;不传下标删除最后一个;
删除不存在的会报错;
-
remove()
根据元素的值删除,只能删除从左至右的第一个,无法删除全部;
删除不存在的会报错;
-
clear()
清空列表;
-
del
del不是列表的专有操作方式,所有的容器内部数据都可以使用del,前提是必须找到该元素;
del操作实际上是切断了引用关系;
del list1[1]
修改
list[下标] = 新值
反转
-
[::-1]
切片反转是生成新的列表;
-
reverse()
reverse()是修改了原列表;
排序
-
sort()
也是修改了列表的原数据;
sort(reverse = True)
降序排序
列表的推导式
有两种格式
-
变量 = [ 要插入列表中的数据 for 临时变量 in 容器 ]
''' 非推导式 ''' list1 = [] for i in range(10): list1.append(i) ''' 推导式 ''' list1 = [i for i in range(10)]
-
变量 = [要插入列表中的数据 for 临时变量 in 容器 if 条件]
2.7.3 元组
元组的操作方式和列表基本相同,但由于元组不可修改的特性,所以操作没有增、删、改,只能查询。
所谓的元组不能修改,其实是为了提示程序员不要修改元组类型的数据。
元组的定义
变量 = (元素1, 元素2,元素3,…)
# 定义方式1
tuple1 = (1, 2, 3, 4, 5)
# 定义方式2
tuple2 = tuple()
# 定义方式3(仅限元组的定义和返回)
tuple3 = 1,
注意:定义一个元素的元组,必须在元素末尾添加, tuple = (1, );不添加,号会被认为括号是提升算数优先级。
元组切片
元组可以切片 tuple1[:2],切片后产生新的元组。
元组查询
-
index()
-
count()
-
len()
或者len(元组)
元组变量
和列表相同
2.7.4 集合
集合是一组数据的集合,集合中的数据是无序的(顺序不可被控制),也是不能重复的。
无序带来的影响就是没有索引,所有使用索引的容器操作方式都没有。
写入到集合中的数据会自动去重,去重的规则是判断哈希值是否相同。注意: True等价于1等价于1.0;False等价于0等价于0.0。
集合的定义
变量 = {元素1, 元素2, 元素3, …}
# 定义方式1
set1 = {1, 2, 3, 4, 5}
# 定义方式2
set2 = set()
注意:定义空集合不能用 set1 = {}, 会被认为是字典
集合的操作
-
add()
-
update()
-
remove()
-
discard()
-
pop()
-
in
-
not in
2.7.5 字典
字典以键值对来存储数据,健不可以重复。
字典无法使用索引,因此也是无序的。
字典的定义
变量 = { 键1: 值1, 键2: 值2, 键3: 值3, … }
user = {'name': 'wk', 'age': '39', 'gender': '男'}
字典查询
-
变量[键]
user['name']
-
get(键, 默认值)
使用get()方法查询时,没有键会返回默认值,否则返回None
user.get('height')
-
keys()
查询字典中所有的健
# 获取所有的键 user.keys() # 将键转换成列表 list(user.keys())
-
values()
查询字典中所有的值
# 获取所有的值 user.values() # 将值转换成列表 list(user.values())
-
items()
查询字典中所有的键值对,以元组的方式返回每一个键值对
# 获取所有的键值对 user.items()
字典新增
-
变量[键] = 值
-
update()
当key不存在时会增加
user.update({ 'school': '哈弗' })
user.update(school='哈佛')
字典修改
字典的修改update同上。key存在则修改,不存在则增加。
字典删除
-
pop(key) 返回删除的值
根据key删除,删除不存在的key会报错
-
popitem()
每次删除最后一个键值对
-
clear()
清空字典
字典遍历
对key进行遍历
for key in user.keys():
print(key)
对value进行遍历
for value in user.values():
print(value)
对item进行遍历
# item为元组
for item in user.items():
print(item)
# 用key, value接收
for key, value in user.items():
print(key, value, sep=":")
2.7.6 容器公共运算符
-
可以将两个容器合为一个容器。
加法运算不会修改原有数据而是生成新的容器。
列表相加
list1 = [1, 2, 3] list2 = [4, 5, 6] list3 = list1 + list2 # [1, 2, 3, 4, 5, 6]
元组相加
tuple1 = [1, 2, 3] tuple2 = [4, 5, 6] tuple3 = tuple1 + tuple2 # [1, 2, 3, 4, 5, 6]
set 和 dict 不支持 + 运算
-
容器相乘就是将容器复制n份再相加。
乘法运算不会修改原有数据而是生成新的容器数据。
'-' * 3 # 即:'-' + '-' + '-' = '---'
list1 = [1, 2, 3] list1 * 2 # 即:[1, 2, 3] + [1, 2, 3] = [1, 2, 3, 1]
set 和 dict 不支持 * 运算
-
in
元素是否在容器内
注意:字典类型是根据键是否在容器内进行判断的
-
not in
元素是否不在容器内
-
del
del list[0] del dict['name']
注:无法使用del删除1)字符串 2)集合 3)元组中的数据;
2.7.7 容器公共函数
-
len()
获取容器的长度
-
min()
-
max()
-
sum()
-
any()
容器内部元素有任意一个不为空,则为True
-
all()
容器内部元素都不为空,则为True
2.8 函数
2.8.1 函数定义
函数的定义
def 函数名(参数1, 参数2, ...):
代码1
代码2
......
return 返回值
1)函数先定义后使用
2)重复定义函数,后定义的函数会覆盖先定义的函数
函数的说明文档
函数的说明文档就是当鼠标悬停在函数调用位置上,或按住ctrl键鼠标悬停
在函数体的第一行写多行注释,则为说明文档
def 函数名(参数1, 参数2, ...):
""" 说明文档 """
代码1
代码2
......
return 返回值
2.8.2 函数参数
- 实参
-
位置参数
按照参数的位置从左到右依次赋值
-
关键字参数
def key_param_func(a, b, c): """ 实参关键字参数 """ return
函数调用时不用关系形参的位置
key_param_func(c=3, b=2, a=1)
- 形参
-
位置参数
-
默认参数
给参数一个默认值;如果给参数赋值就使用所赋的值,否则使用默认值
确实参数不能出现在位置参数之前
def default_param_func(a, b=2): """ 形参默认参数 """ return
-
不定长参数
-
位置不定长参数
格式:*args
使用位置参数给args进行赋值,可以赋任意多个值,会将传入的值封装成元组
def func1(*args): """ 位置不定长参数 """ print(args) return
在不定长参数*args之后只能是默认参数
def func2(*args, b=2, c=3) print(args) return
一般不会在位置参数之前使用不定长参数,建议顺序:位置参数,位置不定长参数,默认参数
def func3(self, *args, c=3) print(args) return
-
关键字不定长参数
接收任意多个关键字参数,函数体内部接收到的是封装成字典形式的参数
格式:**kwargs
def func4(**kwargs) """ 形参-关键字不定长参数,参数被封装成字典 """ print(kwargs) # {name: 'wk', gendar: 'male'} return fun4(name='wk', gendar='male')
kwagrs可以和其它形参类型一起使用,但只能放在末尾
def func5(a, b, *args, c=10, **kwagrs): print(kwargs) return
-
2.8.3 函数返回值
return可以返回函数执行的结果;return也可以结束函数的执行。return后什么也不写默认返回None
-
返回单个值
-
返回多个值
返回多个值其实也是返回一个值,会被被封装成元组
def multi_rets(): """ 函数有多个返回值时封装成元组""" return 1, 2 # result值为元组(1, 2) result = multi_rets()
2.8.4 函数作用域
-
全局变量
在文件顶部书写,可以在函数内和函数外使用
-
局部变量
从函数体内部定义的位置开始,到函数体结束位置,在这个范围内可以使用局部变量,出了函数则变量销毁;
所以分支语句和循环语句中的变量,如果是在外部定义则是全局变量,在循环体内部定义则为局部变量;
num1 = 1 def change_value(): num1 = 100 print(f'函数内部num1={ num1 }') change_value() print(f'函数外部num1={num1}')
结果:
函数内部num1=100
函数外部num1=1
-
global关键字
在函数体内部使用全局变量,需要先声明该变量为全局变量,即:在其前添加global
num1 = 1 def change_value(): global num1 num1 = 100 print(f'函数内部num1={ num1 }') change_value() print(f'函数外部num1={num1}')
结果:
函数内部num1=100
函数外部num1=100
※ 注意:函数体内,如果局部变量和全局变量重名,其实是两个变量,只不过重名而已;要么使用局部变量,要么使用全局变量,不能同时使用;
2.8.5 函数执行流程
代码在执行中,不会检查函数体的语法,仅记录函数的名称。当执行到函数调用时,才会执行函数体中的代码
1)系统内置函数实在python启动的时候将核心库加载进来
2)在执行前函数被定义即可,定义的顺序不受影响
2.8.6 组包和拆包
组包
将多个数据自动组合为一个数据的过程
-
return组包
def func1(): return 1, 2, 3
-
变量组包
tuple = 1, 2, 3
拆包
将一个数据自动拆分为多个数据
-
变量拆包
# 元组变量拆包 num1, num2 = (1, 2) # 集合拆包 a, b = { 'tom', 'cat' } # 字典拆包 key1, key2 = { name: 'wk', 'gender': 'male' }
所有的容器都可以拆包
-
for循环拆包
for key, value in dict1.items(): print(key, value)
2.8.5 引用
引用地址
引用地址就是根据内存地址计算出来的唯一标识,可以认为引用地址就是内存地址。
使用关键字is判断引用地址是否相同;
使用函数id()可以输出变量的引用地址;
num1 = 1
num2 = 2
print(f'num1的id: {id(num1)}')
print(f'num2的id: {id(num2)}')
print(f'num1与num2的引用是否相同: { num1 is num2 }')
num1的id: 2227113191344
num2的id: 2227113191344
num1与num2的引用是否相同: True
数据值相同引用不一定相同
print(True == 1) # true
print(True is 1) # False
print(id(True)) # 140717647453032
print(id(1)) # 2989040992496
数据的值和类型相同引用不一定相同
list1 = [1, 2, 3]
list2 = [1, 2, 3]
print(list1 == list2) # True, 表示值相同
print(list1 is list2) # False,表示引用地址不同
结论:
字符串和元组,值相同,引用也相同
列表,集合,字典,值相同,引用不同
2.8.6 lambda表达式
lambda表达式又叫匿名函数,是函数的另一种定义方式。
匿名函数的最大作用是可以将函数以方便的形式传递到函数体内部。
格式:lambda 参数列表: 返回值
lambda num1, num2: num1 + num2
调用:
-
直接调用
res = (lambda num1, num2: num1 + num2)(3, 4)
-
间接调用
lm = lambda num1, num2: num1 + num2 lm(3, 4)
注意:使用lambda表达式创建的函数只能书写一个返回值的表达式
2.8.6 可变与不可变数据类型
-
可变数据类型
内存空间中的数据可以被修改的数据类型(能做到不修改引用地址的前提下修改数据的值)
list, set, dict
数据值相同,类型也相同,不一定引用地址相同,也就不一定是同一个数据
-
不可变数据类型
内存空间中的数据不可以被修改的数据类型(不能做到不修改引用地址的前提下修改数据的值)
str, int, float, bool
数据值相同,类型也相同,引用地址就相同也就是是同一个数据
2.8.7 闭包
在嵌套函数中,内部函数使用了外包函数的变量,外部函数返回了内部函数名,称为闭包
def outer():
num = 1
def inner():
print(num)
return inner
闭包的调用
-
方式一
ot = outer() # 获取 inner函数的地址 ot() # 调用inner函数
-
方式二
outer()()
2.8.8 装饰器
装饰器是在不修改原代码/函数的前提下,增强代码/函数的功能。实现其实是利用了闭包。
# 原函数
def have_lunch():
print('吃午饭')
# 定义装饰器
def outer(fn):
print('吃早饭')
def inner():
fn()
print('吃晚饭')
return inner
# 调用, 在outer()函数中对have_lunch()进行的增强又没修改其代码
outer(have_lunch)()
2.9 异常
程序运行过程中出现的错误。
2.9.1 异常捕获
捕获异常
try:
可能出现异常的代码
except:
出现异常执行的代码
try:
result = 1 / 0
except:
print('出错了')
捕获指定类型的异常
try:
可能出现异常的代码
except 异常类型1:
出现异常类型1执行的代码
except 异常类型2:
出现异常类型2执行的代码
常见异常
-
Exception
-
NameError
-
TypeError
-
KeyError
-
ValueError
-
IndexError
try:
print(a)
except NameError:
print('出现变量未定义异常')
except Exception:
print('Exception接收任意异常')
写法二
try:
print(a)
print(1 + 'a')
except (NameError, TypeError):
print('出现异常')
捕获异常描述信息
try:
可能出现异常的代码
except 异常类型 as 变量名:
print(变量名) # 此时会输出异常信息
try:
print(a)
except NameError as e:
print(e) # 此时会输出异常信息
except TypeError as e:
print(e) # 此时会输出异常信息
说明:多个类型的异常描述都用e变量接收不会出现冲突,因为一次只能捕获一个异常。
异常中的else
try:
可能出现异常的代码
except 异常类型 as 变量名:
print(变量名) # 此时会输出异常信息
else:
如果try中的代码没有出现异常时执行的代码
try:
print(1)
except Exception as e:
print(e)
else:
print(2)
1
2
异常中的finally
try:
可能出现异常的代码
except 异常类型 as 变量名:
print(变量名) # 此时会输出异常信息
finally:
不管是否出现异常始终会执行
异常传递
在异常存在嵌套的情况下,如果内层没有捕获到异常,可以传递到外层异常中进行捕获,这种现象叫异常传递
try:
try:
print(a)
except TypeError as e:
print(e)
except NameError as e:
print(e)
name ‘a’ is not defined
2.10 模块
模块其实就是一个python源文件,内部书写一些功能,导入模块即可使用其它人写好的功能。
1)模块可以提高代码的复用率
2)简单调用实现复杂功能
2.10.1 模块导入
模块的导入方式
-
全部导入
导入:import 模块名
调用:模块名.功能名
import random random.ranint(1, 10)
-
局部导入
导入:from 模块名 import 功能名
from random import randint
调用:功能名
-
局部匹配导入
导入:from 模块名 import *
调用:功能名
注意:虽然用了通配符*,但是导入范围还是可以手动控制
模块和功能起别名
导入模块或者功能,有些模块名过长,功能层级过多,可以起别名简化调用
如果出现同名功能,必须起别名(否则后导入覆盖先导入功能)
起别名后原名称不可用
模块起别名
import 模块名 as 新模块名
import numpy as py
功能起别名
from 模块名 import 功能名 as 新功能名
from 模块名 import 功能名1 as 新功能名1, 功能名2 as 新功能名2, 功能名3 as 新功能名3
2.10.2 自定义模块
自定义模块名称必须遵循标识符规范,否则无法导入
导入模块后可使用的数据
1)全局变量
2)函数
3)类
__all__的使用
在模块开始的位置定义__all__变量存储一个列表,列表中包含的功能名称,这些功能名称就可以使用 from 模块名 import * 的形式一次性导入
__all__ = ['func_a', 'func_b']
def func_a():
print('A')
def func_b():
print('B')
def func_c():
print('C')
1)如果模块开始不包含__all__变量,使用 from 模块名 import * 的形式可以一次性导入全部
2)如果模块中写了__all__=[],则导入任何功能不可用使用
3)__all__不影响 import 模块名 的方式
4)__all__不影响局部导入中,指定模块名的方式 import 模块名 from 模块名
模块中测试代码的书写
想要在模块中写的测试代码不执行,只需要将其写在如下if语句中。
每一个模块中变量__name__的默认值是______main______
if __name__ = '__main__':
测试代码
在模块文件中执行时 name = ‘main’,当模块被导入后,name = 包名.模块名,这就是为什么模块测试能够执行的原因
注意:导入模块的思路就是会将模块中的代码都执行一边,将函数和变量保存在内存中
2.11 包
包是相关模块的集合,即将相关的模块存在在一个目录中,并且有一个______init______.py文件,这个目录就称为包
包的创建
创建包:new -> Python Package
在目录下创建一个 init.py文件,目录就被python认为是一个包
包的使用
-
全部导入
导入:import 包名.模块名
调用:包名.模块名.功能名
-
局部导入1
导入:from 包名 import 模块名
调用:模块名.功能名
-
局部导入2
导入:from 包名.模块名 import 功能名
调用:功能名
-
局部导入3
导入:from 包名.模块名 import *
调用:功能名
3. 文件
3.1 文件读写
3.1.1 文件模式
读写模式
模式 | 说明 |
---|---|
r | 以只读方式打开文件(文件不存在报错)。文件的指针将会放在文件的开头。这是默认模式。 |
w | 打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。 |
a | 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
b | 以二进制方式打开文件 |
rb | 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。 |
wb | 以二进制格式打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。 |
ab | 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
r+ | 打开一个文件用于读、写。文件指针将会放在文件的开头,向后写入,覆盖原有字符。 |
w+ | 打开一个文件用于读、写。如果该文件已存在则先清空文件。如果该文件不存在,创建新文件。 |
a+ | 打开一个文件用于读、写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。 |
rb+ | 以二进制格式打开一个文件用于读、写。文件指针将会放在文件的开头。 |
wb+ | 以二进制格式打开一个文件用于读、写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。 |
ab+ | 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。 |
带 b 的都是二进制格式;
带 + 的都是可读可写模式;
带 r 打开文件时如果不存在则报错;
带 w 打开文件时如果不存在则创建;
以r, w模式打开文件指针都在文件开头,会用新内容代替就内容,即便没有写入操作;
以 a 模式打开文件指针都在文件末尾;
字符集
-
字节型文件
以字节形式存储的数据文件,例如:图片、音频、视频
# 字节码数据 byte1 = b'\xe7\x8e\x8b'
将字节型数据转换成字符型数据
str1 = byte1.decode(encoding="utf8")
-
字符型文件
使用字符集将字节型文件编码后的文件。如:txt, csv文件等
将字符串数据类型转换成字节数据类型
str1 = '王' # 一个汉字转换成utf8编码变成3个字节,说明一个汉字字符utf8编码占3个字节 byte1 = str1.encode(encoding='utf8') # b'\xe7\x8e\x8b' # 一个汉字转换成gbk编码变成2个字节,说明一个汉字字符gbk编码占2个字节 str1.encode(encoding='gbk') # b'\xcd\xf5'
编码集:
-
ascii 单字节编码
-
ansi 双字节编码,能够支持65000个字符
-
utf8 通过变长的字节序列来表示Unicode字符
在windows中默认是gbk编码,通常要明确指定encoding的值
3.1.2 读取文件
- 文件打开
open(文件路径, 读写模式, 编码集) 返回file对象
file_name = 'C:\\Users\\mux\\Desktop\\1.txt'
from_file = open(file_name, 'r', encoding='utf8')
- 文件读取
-
文件对象.read() 或 文件对象.read(n) n表示最大读取字符数
全部读取或按字符读取
-
文件对象.readline()
读取一行
-
文件对象.readlines()
读取全部,按行分割存储在列表中(返回值是list)
文件对象.readlines(n) n也是最大字符数
读取文本文件
# 读取文件
content = from_file.read(read_length)
# 关闭文件
from_file.close()
读取字节文件
# 打开文件(注意读取模式为"rb")
from_file = open(src_file, "rb")
# 读取文件, content的值为b'\xff\xd8...',
# b表示二进制含义,\x十六进制,后面跟了2个十六进制数据,
# 2的4次方(即4位二进制)等16。共8位即一个字节
content = from_file.read(read_length)
# 关闭文件
from_file.close()
- 文件关闭
文件对象.close()
如果不关闭文件,会持续占用内存;不关闭文件也有可能损害文件
3.1.3 写入文件
- 打开文件
以写模式打开文件
write_file = open('c:\\users\\desktop\\1.txt', 'w', encoding='utf8')
注意:文件是在打开时会被被清空
- 写入文件
write()
write_file.write('新的内容,老内容被覆盖 21:44!')
writelines()
lists = ['窗前明月光', '疑是地上霜']
write_file.writelines(lists)
注意:在windows下默认使用gbk编码集写入文件
- 关闭文件
write_file.close()
3.1.4 移动光标
文件对象.seek(偏移量, 起始位置)
偏移量:相对于起始位置向右移动的字符数
起始位置:0表示来到文件起始位置;1表示光标当前位置;2表示文件末尾
# 移动光标到文件开始位置
file.seek(0, 0) # 可以简写位file.seek(0)
3.2 文件操作
os模块(operation system)即操作系统模块。调用的是操作系统接口。
-
重命名
rename()
import os os.rename('C:\\Users\\mux\\Desktop\\1.png', 'C:\\Users\\mux\\Desktop\\11.png')
-
移动文件
remove()
import os # 删除文件(文件不存在则报错) os.remove('C:\\Users\\mux\\Desktop\\2.txt')
-
isfile()
判断是否文件
文件名
-
分离扩展名:os.path.splitext()
-
获取路径名:os.path.dirname()
-
获取文件名:os.path.basename()
-
运行shell命令: os.system()
3.3 文件夹操作
os模块(operation system)即操作系统模块。调用的是操作系统接口。
-
mkdir()
创建目录
import os os.mkdir()
-
rmdir()
删除目录
-
getcwd()
获取当前路径
import os cur_path = os.getcwd() print(f'当前路径:{cur_path}')
-
chdir()
改变目录
import os os.chdir("C:\\Windows")
-
listdir()
列车文件夹下所有文件,返回列表
-
isdir()
是否目录
-
exists()
是否存在
其它
day08-16
2024.11.30 Study Python Over