Python基础语法
运行环境
pycharm+ python3.7
或者anacoda
终端调用python文件
python ./*.py
➜ p git:(master) ✗ python3 ./p.py
在p文件夹下,对p.py作出的处理
[0, 1, 2, 3, 4, 5, 6, 7, 8]
➜ p git:(master) ✗ python ./p.py
[0, 1, 2, 3, 4, 5, 6, 7, 8]
>>> li = [1,2,3,4,5,6,7,8,9]
>>> [x**2 for x in li if x>5]
[36, 49, 64, 81]
>>> dict([(x,x*10) for x in li])
{1: 10, 2: 20, 3: 30, 4: 40, 5: 50, 6: 60, 7: 70, 8: 80, 9: 90}
>>> [(x,x*10) for x in li]
[(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60), (7, 70), (8, 80), (9, 90)]
>>> dict([(1,2)])
{1: 2}
数列转换成字典形式
>>> [(x, y) for x in range(10) if x % 2 if x > 3 or y in range(10) if y > 7 if y != 8]
[(5, 9), (7, 9), (9, 9)]
>>> [ (x, y) for x in range(10) if x % 2 if x > 3 for y in range(10) if y > 7 if y != 8 ]
[(5, 9), (7, 9), (9, 9)]
pip list --format=columns pip列表——format=列
一、第一个程序
print(hello world!)
输出一句话 print(‘内容’)
二、注释
1. 概念
1.1 对代码做一些描述, 提高代码的可读性
1.2 注释不会被显示出来
2. 分类
2.1 单行注释
- 在注释的最前面加 # 号
- 建议 # 与 注释内容之间 至少保留一个空格
- 适合: 简短的描述, 注释
2.2 多行注释
- 一对 三引号 (单双引号均可)
- 适合: 较长的描述
'''
这是注释第一行
这是注释第二行
这是注释第三行
'''
3. 友情提醒
- 注释 并非越多越好. 若一目了然, 则不需要注释
- 对于功能性的 多行代码, 则在功能的最前面写明注释
- 多行注释 不能嵌套使用
三、打印输出
-
print(内容)
-
print(内容1,内容2,内容3, …)
-
print(内容1,内容2, …,end=”值”)
-
print(
内容1 \ 内容2 \ 内容3 \ ... **)**
相对而言,第四种写法使用频率较低
四、Python 排版缩进
1. Python 对代码的书写要求非常严格
2. 常规缩进
2.1 以 4个空格作为缩进. 默认要顶格
2.2 同级代码 需要保持缩进一致
3. 排版
- python中, 一行只有一条命令
- 多条命令需要换行
- 一条命令 最好不要超过 80个字符
4. 错误案例
print('诸葛亮') print('智商太低会传染')
5. 正确案例
print('诸葛亮')
print('智商太低会传染')
五、变量
1. 定义
用于存储数据. 类似于数学中的未知数
每定义一个变量, 都会分配一个内存
2. 格式
- 格式1: 变量名 = 值
- 格式2: 变量名1 = 变量名2 = 变量名3 = … = 值
a = b = c = 100
print(a, b, c)
print( id(a) )
print( id(b) )
print( id(c) )
发现: 一次性给 多个不同的变量 赋予同一个值, 内存也是一样的
坑点:在定义是, 没有给变量赋值, 则会报错, 被认为是 未定义变量
3. 命名规范
3.1 由数字, 字母 和 下划线组成
3.2 不能以 数字开头
3.3 严格区分大小写
3.4 不能使用 关键字(保留字)
查看 Python 关键字
import keyword
print( keyword.kwlist )
3.5 支持中文变量名,但是不推荐使用
4. 变量操作
4.1 修改变量
在已有的变量基础之上, 再次赋值, 就是修改
4.2 删除变量
通过 关键字 del来删除变量
del 变量名
del 变量名1, 变量名2, …
六、数据类型
1. 定义
变量的值能写成的样子
数据 一共有6种 标准类型
如果变量值 超出这6种以外, 都是不符合规范的
2. 数据类型
- Number — 数字
- String — 字符串
- List — 列表
- Tuple — 元组
- Set — 集合
- Dict — 字典
简单理解: 所有与数字相关的 都可以用 Number 类型 所有与字母, 数字, 标点, 文字等相关的都可以使用 String 类型 列表, 元组, 集合, 字典都是 复合类型, 可以容纳多个数据类型, 多个值, 该类型属于高级类型
3. 归类
- 可变类型: 定义后, 再次修改时, 是不会重新分配内存, 会在原来的基础上直接改
ist, Set, Dict 属于可变类型
- 不可变类型: 定义后, 该内存中的值就不能被修改. 如果强制修改的话, 那么会重新分配一个内存
Number, String, Tuple 属于不可变类型
练习
a = 10
b = a
b = 20
请问: 最后 a 和 b 的值分别是多少?
最后 a 和 b 的内存一样吗???
七、Number-整型 int
1. 值
值:正负整数
- 注意:
- 理论上 无限制
- 实际上 受限于内存
2. 类型检测
函数函数: type( 变量 )
返回值: 变量的数据类型
a = 10
print( type(a) )
a = 1.5
print( type(a) )
输出结果:
=> <class ‘int’> => <class ‘float’>
3. 进制
前缀 | 基数范围 | |
---|---|---|
二进制 | 0b | 0-1 |
八进制 | 0o | 0-7 |
十进制 | 无 | 0-9 |
十六进制 | 0x | 0-9 a-f |
任意进制 -> 十进制
公式: 基数 * 进制^次方
- 说明: 次方是从 个位开始以 0次方出现 十位 … 1次方 百位 … 2次方 …
1*2^3 + 1*2^2 + 1*2^1 + 0*2^0 =
a = 10 #十进制
a = 0b1110 #二进制
print(a)
1*8^1 + 2*8^0 = 10
a = 0o12 #八进制
print(a)
10*16^2 + 11*16^1 + 5*16^0
a = 0xab5 #十六进制
print(a)
十进制 -> 任意进制 十进制 除以 进制数, 结果倒取余
4. int 转换
将其他类型 转为 int类型 int()
a = 2.5
print( type(a) )
result = int( a ) # 将a 送进int(), 转为int, 结果送给result
print( result, type(result))
print( a, type(a))
输出结果:
=> <class ‘float’> => 2 <class ‘int’> => 2.5 <class ‘float’>
八、Number-浮点 float
1. 值
1) 整数 + 小数
2) 科学计数法
a = 2.5
print(a, type(a))
a = 2e5 # 2 * 10的5次方
print(a, type(a))
输出结果:
=> 2.5 <class ‘float’> => 200000.0 <class ‘float’>
2. 精度
1) 有效位数
- 从前向后, 第一个非0数字开头, 向后保留17位
a = 1.1234567890123456789
print(a)
a = 0.001234567890123456789
print(a)
输出结果:
=> 1.1234567890123457 => 0.0012345678901234567
2) 控制小数位
a = 1.234567
a = round(a, 3)
print(a)
输出结果:
=> 1.235
注意:
- python2中, 存在单精度和双精度
- python3中, 没有单精度, 只有双精度
3. float 转换
a = 2
print(a, type(a))
a = float(a)
print(a, type(a))
输出结果:
=> 2 <class ‘int’> => 2.0 <class ‘float’>
九、Number-复数 complex
1. 值
格式: 实数 + 虚数 j
a = 2 + 5j # 2是实数, 5是虚数
print(a, type(a))
输出结果:
=> (2+5j) <class ‘complex’>
2. 获取实数/虚数
- 实数: real
- 虚数: imag
a = 2 + 5j
print(a.real, type(a.real))
print(a.imag, type(a.imag))
输出结果:
=> 2.0 <class ‘float’> => 5.0 <class ‘float’>
3. 作用
- 数在实际生活中, 看不出有什么应用, 就像 圆周率, sin, cos
- 但是后期的 数据分析, 平面几何非常有用
4. complex转换
格式: complex(实数, 虚数) #虚数默认为0
a = 5.3
a = complex(a)
print(a, type(a))
输出结果:
=> (5.3+0j) <class ‘complex’> #虚数默认为0
a = 5
b = 2
result = complex(a, b)
print(result)
输出结果:
=> (5+2j)
十、Number-布尔
1. 值
值: True 和 False
注意: 首字母必须大写
a = True
print(a, type(a))
a = False
print(a, type(a))
输出结果:
=> True <class ‘bool’> => False <class ‘bool’>
2. 作用
- bool值代表两种 极端状态, 常用于比较, 判断等
- True: 1, 真, 对, 开, 是, 存在, 可以
- Flase: 0, 假, 错, 关, 否, 不存在, 不可以
print( 1 > 2 )
结果: => False
3. bool 转换
print( bool(10) )
print( bool(0) )
print( bool(0.0) )
print( bool(0+0j) )
print( bool(-5) )
输出结果:
=> True => False => False => False => True
11.bytes
python str与bytes之间的转换
# bytes object
b = b"example"
# str object
s = "example"
# str to bytes
bytes(s, encoding = "utf8")
# bytes to str
str(b, encoding = "utf-8")
# an alternative method
# str to bytes
str.encode(s)
# bytes to str
十一、String 字符型
1. 定义
- 可用于表达 数字, 字母, 标点, 汉字 等等内容
2. 格式
- 2.1 单引号
- 2.2 双引号
- 2.3 三引号
a1 = '小时候, 喜欢爬树么?'
a2 = "小时候, 进入女澡堂 洗澡么?"
a3 = '''小时候, 经常把小弟弟往插座里面插'''
a4 = """小时候, 想过你会坐着这里学Python"""
a5 = "I give you face, you don't have face"
print(a1, type(a1))
print(a2, type(a2))
print(a3, type(a3))
print(a4, type(a4))
print(a5, type(a5))
输出结果:
=> 小时候, 喜欢爬树么? <class ‘str’> => 小时候, 进入女澡堂 洗澡么? <class ‘str’> => 小时候, 经常把小弟弟往插座里面插 <class ‘str’> => 小时候, 想过你会坐着这里学Python <class ‘str’>
三引号被变量引用时, 就是 字符串 三引号若没有被引用时, 就是 注释 单引号中 不要嵌套单引号 双引号中 不要嵌套双引号 三引号中 不要嵌套三引号
小结: 引号支持互插, 不支持自插
3. 转义字符
转义符:\ 通过转义符能将普通字符转为特殊字符 将特殊字符转为普通字符
普通字符 -> 特殊字符
\n 换行
\t 制表符 tab
\r 回车
特殊字符 -> 普通字符
\'
\"
\\
...
a5 = 'I give you face, you don\'t have face'
print(a5)
输出结果:
=> I give you face, you don’t have face
4. 原始字符串
r’字符串内容’ R’字符串内容’
会将字符串内容原样输出
a = '上面的人喜欢做着\n下面的人喜欢躺着'
print(a)
a = r'上面的人喜欢做着\n下面的人喜欢躺着'
print(a)
a = R'上面的人喜欢做着\n下面的人喜欢躺着'
print(a)
输出结果:
=> 上面的人喜欢做着 => 下面的人喜欢躺着 => 上面的人喜欢做着\n下面的人喜欢躺着 => 上面的人喜欢做着\n下面的人喜欢躺着
5. 格式化字符串
%s 字符串
%d 整数 (十进制)
%f 小数
%e 科学计数法
%E 科学计数法
%o 八进制
%x 十六进制
%X 十六进制
- 格式化写法
- ‘字符串内容’ % 变量名
- ‘字符串内容’ % (变量名1, 变量名2, …)
name = '小明'
age = 18
print( '我们的大帅哥%s, 今年 %d 岁' % (name, age) )
- 非格式化写法
name = '小明'
age = 18
print( '我们的大帅哥',name,今年,age,岁' )
6. 字符串操作
6.1 拼接 +
a = '金庸小说: '
b = '飞雪连天射白鹿, 笑书神侠倚碧鸳'
c = a + b
print(c)
=> 金庸小说: 飞雪连天射白鹿, 笑书神侠倚碧鸳
6.2 复制 *
a = '母鸡'
b = a * 3
print(b)
=> 母鸡母鸡母鸡
6.3 索引 []
# 0 1 23 4 5 67 8 90 12 3 4 5
a = '营长说:敌人逼上来了,我们出击吧'
print( a[0] )
print( a[1] )
print( a[2] )
print( a[-1] )
print( a[-2] )
print( a[-3] )
=> 营 => 长 => 说 => 吧 => 击 => 出
6.4 取片 [::]
# 0 1 23 4 5 67 8 90 12 3 4 5
a = '营长说:敌人逼上来了,我们出击吧'
print( a[:]) # 开头 ~ 末尾
print( a[::]) # 开头 ~ 末尾
print( a[0:7]) # 索引0 ~ 索引7 (不包含索引7)
print( a[2:7]) # 索引2 ~ 索引7 (不包含索引7)
print( a[2:]) # 索引2 ~ 末尾
print( a[:2]) # 开头 ~ 索引2 (不包含索引2)
print( a[2:13:3]) # 索引2 ~ 索引13, 步长3 (不包含索引13)
print( a[2:13:4]) # 索引2 ~ 索引13, 步长4 (不包含索引13)
=> 营长说: 敌人逼上来了, 我们出击吧 => 营长说: 敌人逼上来了, 我们出击吧 => 营长说: 敌人 => 说: 敌人 => 说: 敌人逼上来了, 我们出击吧 => 营长 => 说敌上, => 说人了
7. String 转换
a = 100
a = str(a)
print(a, type(a))
a = True
a = str(a)
print(a, type(a))
=> 100 <class ‘str’> => True <class ‘str’>
十二、List 列表
1. 定义
由一堆数据组成的有序序列
2. 格式
列表名 = [值1, 值2, 值3, …]
a = [] # 空列表
print(a, type(a))
a = ['黄焖鸡', '兰州拉面', '沙县小吃', 10, 10.5, 1+2j, True]
print(a, type(a))
=> [] <class ‘list’> => [‘黄焖鸡’, ‘兰州拉面’, ‘沙县小吃’, 10, 10.5, (1+2j), True] <class ‘list’>
3. 列表操作
3.1 访问
# 0 1 2
a = ['黄焖鸡', '兰州拉面', '沙县小吃']
# -3 -2 -1
print( a[0] )
print( a[-1] )
# print( a[99] ) # 访问一个不存在的索引, 则会报错
=> 黄焖鸡 => 沙县小吃
3.2 插入
- 1) 列表名.append(值) 在最后追加一个数据
a = ['黄焖鸡', '兰州拉面', '沙县小吃']
a.append('麻辣烫')
print(a)
=> [‘黄焖鸡’, ‘麻辣香锅’, ‘兰州拉面’, ‘沙县小吃’, ‘麻辣烫’]
- 2) 列表名.insert(索引, 值) 在指定索引插入值, 原有索引会依次向后推1步
a = ['黄焖鸡', '兰州拉面', '沙县小吃']
a.insert(1, '麻辣香锅')
print(a)
print(a[1])
print(a[2])
a.insert(99, '重庆鸡公煲') # 插入的索引与原有索引的最大值 差距超过1, 则认为原有最大索引+1
print(a)
print(a[4])
print(a[99])
=> [‘黄焖鸡’, ‘麻辣香锅’, ‘兰州拉面’, ‘沙县小吃’] => 麻辣香锅 => 兰州拉面 => [‘黄焖鸡’, ‘麻辣香锅’, ‘兰州拉面’, ‘沙县小吃’, ‘重庆鸡公煲’] => 重庆鸡公煲 => 报错
3.3 修改
通过已有的索引 来重新赋值
a = ['黄焖鸡', '麻辣香锅', '兰州拉面', '沙县小吃', '麻辣烫', '重庆鸡公煲']
a[1] = '鸭血粉丝汤'
print(a)
=> [‘黄焖鸡’, ‘鸭血粉丝汤’, ‘兰州拉面’, ‘沙县小吃’, ‘麻辣烫’, ‘重庆鸡公煲’]
3.4 删除
- del 列表名[索引] 删除已有的索引值, 后面的索引依次向前推1步
- del 列表名 删除整个列表
a = ['黄焖鸡', '麻辣香锅', '兰州拉面', '沙县小吃', '麻辣烫', '重庆鸡公煲']
del a[1]
print(a)
print(a[1])
del a
# print(a)
=> [‘黄焖鸡’, ‘兰州拉面’, ‘沙县小吃’, ‘麻辣烫’, ‘重庆鸡公煲’] => 兰州拉面
3.5 合并
a = ['黄焖鸡', '兰州拉面']
b = ['沙县小吃', '麻辣烫']
print(a+b)
=> [‘黄焖鸡’, ‘兰州拉面’, ‘沙县小吃’, ‘麻辣烫’]
3.6 复制
a = ['黄焖鸡', '兰州拉面']
print( a*2 )
=> [‘黄焖鸡’, ‘兰州拉面’, ‘黄焖鸡’, ‘兰州拉面’]
3.7 取片, 分片
# 0 1 2 3 4 5 6
a = ['刘备', '关羽', '张飞', '赵云', '马超', '黄忠', '诸葛亮']
print(a[0:5]) # 索引0 ~ 索引5 (不包含索引5)
print(a[2:5]) # 索引2 ~ 索引5 (不包含索引5)
print(a[2: ]) # 索引2 ~ 末尾
print(a[ :2]) # 开头 ~ 索引2 (不包含索引2)
print(a[ : ]) # 开头 ~ 末尾
print(a[ : : ]) # 开头 ~ 末尾
print(a[0:5:2]) # 开头 ~ 末尾
=> [‘刘备’, ‘关羽’, ‘张飞’, ‘赵云’, ‘马超’] => [‘张飞’, ‘赵云’, ‘马超’] => [‘张飞’, ‘赵云’, ‘马超’, ‘黄忠’, ‘诸葛亮’] => [‘刘备’, ‘关羽’] => [‘刘备’, ‘关羽’, ‘张飞’, ‘赵云’, ‘马超’, ‘黄忠’, ‘诸葛亮’] => [‘刘备’, ‘关羽’, ‘张飞’, ‘赵云’, ‘马超’, ‘黄忠’, ‘诸葛亮’] => [‘刘备’, ‘张飞’, ‘马超’]
十三、Tuple 元组
1. 定义
由一堆数据组成的有序序列. 但不能修改数据, 是不可变类型之一
2. 格式
元组名 = (值1, 值2, 值3, …)
a = () # 空元组
a = ('男', '女')
print(a, type(a))
=> (‘男’, ‘女’) <class ‘tuple’>
- 注意 若()中只有一个值时, 会将() 理解成一个整体的意思 所以, 需要在值的后面, 补一个逗号
a = (10)
print(a, type(a))
a = (10, )
print(a, type(a))
=> 10 <class ‘int’> => (10,) <class ‘tuple’>
3. 元组操作
3.1 访问
- 通过 已有的索引 来访问元组
# 0 1 2 3
a = ('天蓬', '卷帘', '弼马温', '金蝉子')
print( a[0] )
print( a[-1] )
=> 天蓬 => 金蝉子
3.2 修改, 插入, 删除
- 由于元组 属于不可变类型之一, 所以无法通过索引来修改, 插入, 删除
3.3 合并 +
a = ('天蓬',)
b = ('卷帘',)
print(a+b)
=> (‘天蓬’, ‘卷帘’)
3.4 重复 *
a = ('天蓬',)
print( a*3 )
=> (‘天蓬’, ‘天蓬’, ‘天蓬’)
3.5 分片, 取片[::]
# 0 1 2 3
a = ('天蓬', '卷帘', '弼马温', '金蝉子')
print( a[::] )
print( a[1:3:1] )
=> (‘天蓬’, ‘卷帘’, ‘弼马温’, ‘金蝉子’) => (‘卷帘’, ‘弼马温’)
十四、Dict 字典
1. 定义
- 由一堆 键值对 组成的有序序列 键: 与索引类似, 支持数字, 字母等类型 索引都是数字, 且不可设置
- 键必须手动设置, 且唯一 (若发生等价键, 后面会覆盖前面的值)
- 键必须是不可变类型
- 值: 任意类型
可变类型: list set dict 不可变: number string tuple
2. 格式
- 字典名 = { 键:值, 键:值, …}
a = {} # 空字典
print(a, type(a))
a = {'name':'关羽', 'nickname':'武圣', 1:'关公', False:'温酒斩华雄'}
print(a, type(a))
=> {} <class ‘dict’> => {‘name’: ‘关羽’, ‘nickname’: ‘武圣’, 1: ‘关公’, False: ‘温酒斩华雄’} <class ‘dict’>
a = { 1: [1,2,3] }
a = { 1: {1:2, 3:4} }
print(a)
print(a[1])
print(a[1][3])
=> {1: {1: 2, 3: 4}} => {1: 2, 3: 4} => 4
3. 字典操作
3.1 访问
- 通过键来访问值
a = {'name':'关羽', 'nickname':'武圣', 1:'关公', False:'温酒斩华雄'}
print( a['name'] )
print( a['nickname'] )
print( a[1] )
print( a[False] )
# print( a['xxx'] ) # 访问不存在的 键, 则会报错
=> 关羽 => 武圣 => 关公 => 温酒斩华雄
3.2 修改
- 通过已存在的键来修改值
a = {'name':'关羽', 'nickname':'武圣', 1:'关公', False:'温酒斩华雄'}
a['name'] = '小明'
print(a)
=> {‘name’: ‘小明’, ‘nickname’: ‘武圣’, 1: ‘关公’, False: ‘温酒斩华雄’}
3.3 插入
- 通过不存在的键来插入值
a = {'name':'关羽', 'nickname':'武圣', 1:'关公', False:'温酒斩华雄'}
a['age'] = 18
print(a)
=> {‘name’: ‘小明’, ‘nickname’: ‘武圣’, 1: ‘关公’, False: ‘温酒斩华雄’, ‘age’: 18}
3.4 删除
- 通过 del 字典名[键]来删除值
a = {'name':'关羽', 'nickname':'武圣', 1:'关公'}
del a[1]
print(a)
=> {‘name’: ‘关羽’, ‘nickname’: ‘武圣’}
十五、集合 Set
1. 定义
由一堆 不会重复的数据 组成的无序序列 其实, 就是没有键的字典
- 值: 无序 具有唯一性 不可变类型
- 作用: 去重 关系测试
2. 格式
集合名 = {值1, 值2, 值3, … }
a = {} # 空字典, 而非空集合
print(a, type(a))
a = set() # 空集合
print(a, type(a))
a = {'杜子腾', '毕云涛', '史珍香'}
print(a)
=> {} <class ‘dict’> => set() <class ‘set’> => {‘史珍香’, ‘毕云涛’, ‘杜子腾’}
3. 去重
a = {10, 20, 30, 40, 20, 50, 20, 60}
print(a)
a = [10, 20, 30, 40, 20, 50, 20, 60]
a = set(a)
a = list(a)
print(a)
=> {40, 10, 50, 20, 60, 30} => [40, 10, 50, 20, 60, 30]
4.关系测试
a = {'1','2','3','4','5'}
b = {'4','5','6','7'}
- 交集 &
print( a & b )
=> {‘5’, ‘4’}
-
**并集 ** print( a | b )
=> {‘6’, ‘1’, ‘7’, ‘5’, ‘2’, ‘4’, ‘3’}
- 差集 -
print( a - b ) # a 相对于 b的差集
print( b - a ) # b 相对于 a的差集
=> {‘1’, ‘2’, ‘3’} => {‘7’, ‘6’}
- 对称差集 ^
print( a ^ b )
=> {‘6’, ‘7’, ‘1’, ‘2’, ‘3’}
5. 集合操作
5.1 添加
- 集合名.add(值)
a = {'杜子腾', '毕云涛', '史珍香'}
a.add('郝爽')
print( a )
=> {‘史珍香’, ‘毕云涛’, ‘郝爽’, ‘杜子腾’}
- 集合名.update(值)
a = {'杜子腾', '毕云涛', '史珍香'}
a.update( ('卜耀', '项耀') )
print(a)
=> {‘史珍香’, ‘毕云涛’, ‘卜耀’, ‘杜子腾’, ‘项耀’, ‘郝爽’}
- 利用 函数特性来实现的相关效果
a = set()
a.update('123456789')
print(a)
a = set('abcdefg')
print(a)
=> {‘4’, ‘3’, ‘5’, ‘6’, ‘7’, ‘2’, ‘8’, ‘9’, ‘1’} => {‘a’, ‘c’, ‘d’, ‘e’, ‘b’, ‘g’, ‘f’}
5.2 删除
- 集合名.remove(值) 值不存在则会报错
- 集合名.discard(值) 值不存在不会报错
a = {'杜子腾', '毕云涛', '史珍香'}
a.remove('史珍香')
print(a)
a.discard('杜子腾')
print(a)
=> {‘杜子腾’, ‘毕云涛’} => {‘毕云涛’}
5.3 访问,修改
- 没有索引,没有键, 无法单独获取集合值, 删除一个值
十六、类型转换
1. 基本类型
- Int, Float, Complex, Bool
- 分别是: int(), float(), complex(), bool()
2. 注意
- 1) Int() 支持float, bool, 纯数字字符串 (不能含有任意字母)
- 2) Float() 支持float, int, bool, 数字字符串 (包含字母e, 小数点)
- 3) Complex() 支持int, float, bool, 数字字符串 (包含字母e, 小数点)
- 4) Bool() 以下值 都可以转为false,其余都是true
整数0 小数0 复数0 空字符串 空容器 false 本身
3. str()
- 任何类型 都可以转换为string
4. List(), Tuple(), Set()
- 支持string, list, tuple, set, dict 转换
5. Dict()
-
只有 二维容器 才能转为 字典
- 一维列表
a = ['a',1, 'b',2, 'c',3]
- 二维列表
a = { ('a',1), ('b',2), ('c',3), }
二维容器: 容器中 嵌套别的容器
十七、内存管理
任何程序 或 软件在运行时, 都是临时存放在内存中的
1. 引用
python内部使用引用计数, 来保持内存中对象的追踪
a = 10
# 分析:
# 10 是对象
# a 是引用
#
# a引用了 对象10, 对象10 的引用计数为 1
b = 10
b引用了 对象10, 对象10 的引用计数为 2 (有a, 还有b)
2. 垃圾回收机制
- 每定义一个变量, 都会在内存划分空间, 在内存里面的值都统称为对象
- 那么内存由于有上限, 那么python 在使用完变量, 就会查看 引用计数
- 如果 引用计数 = 0, python 会立马释放内存 ( 垃圾回收 )
# 小结:
# 对象在以下情况引用计数 + 1
# 1) 对象被创建: a = 10
# 2) 对象被其他对象赋值: b = a
# 3) 被作为参数传递给函数: 函数名( a )
# 4) 作为容器对象的一个元素: x = [ 10, a, 03, ...]
#
#
# 对象在以下情况引用计数 - 1
# 1) 对象被销毁时: del a
# 2) 对象引用别的对象: a = 20
# 3) 引用离开了它的作用域时: 例如: 函数名(a) 在使用函数时, 计数+1, 一旦函数结束时, 计数-1
#
# 强调: 变量并不是直接存储, 而是引用了一个内存地址
# 强调: 变量并不是直接存储, 而是引用了一个内存地址
# 强调: 变量并不是直接存储, 而是引用了一个内存地址
3. 循环垃圾回收
- 当出现两个变量 互相引用, 但两个变量又没有别的引用, 也会被当做垃圾回收掉
# x = y
# y = x
4. 内存池
- 在python运行期间, 会大量执行 内存malloc(分配) 和 free(释放), 导致python运行效率降低
- 为了能加速高频率数字, 引用内存池机制, 用于管理 小块内存的分配和释放只有在超过 小块内存, 才会去 malloc
小块内存: 整数范围: -5 ~ 256
只要在 范围之内, 都是事先分配好的内存, 不会变. 只有超过这个范围, 才会去找python重新分配内存.
十八、运算符
一. 算术运算符
1. 基本运算
- + 加
- - 减
- * 乘
- / 除
2. 取模
- 通俗说法:求余数
- 运算符号:%
2.1 取模结果的正负
取模结果取决于第二位数的正负
2.2 取模结果的范围
公式: %(y-x+1) + x
3. 指数
print( 2 ** 3 ) # 2的3次方
=> 8
4. 整除
- 只留下整数, 去除小数
print( 10 // 4 )
=> 2
二. 赋值运算符
1. 等于号
1.1 单一赋值
a = 10
1.2 连续赋值
a = b = c = 20
1.3 多段赋值
a,b,c = 1,2,3
a,b = 5,10
a,b = b, a+b # a,b = 10, 15
# 先算 = 右边的, 再算 = 左边的
print(a, b)
=> 10 15
- 技巧: 交换变量
a = 5
b = 10
a,b = b,a
# 省略的临时内存
1.4 剩余赋值
a,b,*c = 1,2,3,4,5,6,67,7
print( a, b )
print( c ,type(c)) # *c 将剩下来的没人要的数据 全部接收, 以 list 形式接收
=> 1 2 => [3, 4, 5, 6, 67, 7] <class ‘list’>
2. 运算赋值
- +=
a += b # a = a + b
- -=
a -= b # a = a - b
- *=
a *= b # a = a * b
- /=
a /= b # a = a / b
- %=
a %= b # a = a % b
- //=
a //= b # a = a // b
- **=
a **= b # a = a 的 b次幂
三. 比较运算符
所有的比较结果为 bool
- > 和 >=
- < 和 <=
- == 判断两边的值是否相等
- != 判断两边的值是否不等
四. 逻辑运算符
1. 逻辑与
- 格式: x and y
- 规则: 若x 为真, 那么结果就是y 若x 为假, 那么结果就是x
2. 逻辑或
- 格式: x or y
- 规则: 若x 为真, 那么结果就是x 若x 为假, 那么结果就是y
3. 逻辑非
- 格式: not x
- 规则: 若x 为真, 那么结果就是 False 若x 为假, 那么结果就是 True
五. 身份运算符
1. is
- 格式: X is Y
- 规则: 判断 x 和 y 是否来自同一个内存
2. is not
- 格式: X is not Y
- 规则: 判断 x 和 y 是否来自不同的内存
六. 成员运算符
成员管理 支持string, list, tuple, set, dict
1. in
2. not in
a = ['古力娜扎', '迪丽热巴', '萨瓦迪卡', '马尔扎哈', '真皮沙发']
print( '马尔扎哈' in a )
print( '马尔扎哈' not in a )
=> True
=> False
七. 位运算符
位运算, 需要先转为二进制, 再运算.
1. 按位与
- 格式: x & y
- 规则: 两者为1即为1,否则为0
a = 5 # 0101
b = 12 # 1100
print( a & b )
=> 4
& 1 结果为1, 则为奇数 & 1 结果为0, 则为偶数
2. 按位或
-
格式: x y - 规则: 一个为1即为1,否则为0
a = 10 # 1010
b = 5 # 0101
print( a | b )
=> 15
奇数 1 为本身 偶数 1 则加1
3. 按位异或
- 格式 : x ^ y
- 规则 : 相异为1,相同为0
a = 10 # 1010
b = 8 # 1000
print( a ^ b )
=> 2
奇数 ^ 1, 结果-1 偶数 ^ 1, 结果+1
4. 按位取反
- 格式 : ~ x
- 规则 :
~x ===> -x-1
5. 左移
- 格式: x « num位
- 规则:二进制依次向左移动num位, 低位补0
x << n ==> x*2的n次方
6. 右移
- 格式: x » num位
- 规则: 二进制依次向右移动 num位, 高位补0, 低位丢弃
x >> n ==> x // 2的n次方
八. 运算符优先级
运算符 | 描述 |
---|---|
** | 指数 (最高优先级) |
~ + - | 按位翻转, 一元加号和减号(最后两个的方法名为 +@ 和 -@) |
* / % // | 乘,除,取模和取整除 |
+ - | 加法减法 |
» « | 右移,左移运算符 |
& | 位 ‘AND’ |
^ | | 位运算符 |
<= < > >= | 比较运算符 |
<> == != | 等于运算符 |
= %= /= //= -= += *= **= | 赋值运算符 |
is is not | 身份运算符 |
in not in | 成员运算符 |
and or not | 逻辑运算符 |
十九、流程控制
- 定义 计算机中在执行程序是, 是按照指定的顺序从上往下依次执行, 有时也会跳过部分代码, 有时不断重复某段代码
- 流程控制主要分为3种:
- 顺序结构 从上往下依次执行, 即为顺序结构. 大多数程序默认就是该结构
- 分支结构 当代码执行到 分叉口时, 要进行选择向左向右, 一旦其中一个方向, 那么另一个方向将不会执行
- 循环结构 当遇见 某一段功能代码需要重复运行, 才能完成时, 则需要循环结构 循环一般情况下, 总会停止循环, 或者突发情况停止循环, 需要借助 流程控制符
1. 分支结构 if
1.1 短向分支
-
格式:
if 条件: true环境
1.2 单向分支
-
格式:
if 条件: true环境 (代码块)
1.3 双向分支
-
格式:
if 条件: true环境 (代码块) else: false环境 (代码块)
1.4 多向分支
-
格式:
if 条件1: true环境1 (代码块) elif 条件2: true环境2 (代码块) elif 条件3: true环境3 (代码块) ...
1.5 巣状分支
-
格式:
if 条件1: if 条件2: true环境2 else: false环境2 else: if 条件3: true环境3 else: false环境3
2. 循环结构之while
- 作用: 将某一部分的代码功能, 重复的执行, 直到不满足条件时, 就会结束循环
- 组成: 初始值,循环条件,循环增量
2.1 循环1
-
格式:
while 条件: true环境 (代码块) 循环外的代码
2.2 循环2
-
格式:
while 条件: true环境
2.3 循环3
-
格式:
while 条件: true环境 (代码块) else: false环境 (代码块)
2.4 无限循环
只要条件永远成立, 就能成为无限循环, 又称死循环
3.循环结构之for
3.1 区间循环
-
格式:
for 变量 in 区间: 循环体 (代码块)
-
说明: 区间: range(start, stop, step)
- start: 从start开始, 默认值为0
- stop: 到stop结束, 不包含stop
- step: 步长, 默认值为1
3.2 else用法
-
格式:
for 变量 in 区间: 循环体 else: 进阶体
-
说明: 这里的else是指, 当循环做完了就会进入 进阶体 (只进入一次)
4. 异常
-
定义:
异常也是流程控制之一, 叫做异常结构
在程序执行过程中, 如果 py解释器遇到错误, 则会立马停止程序执行, 并在控制台输出错误. 此为”异常”
在输出错误时, 该行为”抛出异常”
-
常见报错:
错误 说明 AssertError 断言语句(assert)失败 AttributeError 尝试访问未知的对象属性 EOFError 用户输入文件末尾标志EOF(Ctrl+d) FloatingPointError 浮点计算错误 GeneratorExit generator.close()方法被调用的时候 ImportError 导入模块失败的时候 IndexError 索引超出序列的范围 KeyError 字典中查找一个不存在的关键字 KeyboardInterrupt 用户输入中断键(Ctrl+c) MemoryError 内存溢出(可通过删除对象释放内存) NameError 尝试访问一个不存在的变量 NotImplementedError 尚未实现的方法 OSError 操作系统产生的异常(例如打开一个不存在的文件) OverflowError 数值运算超出最大限制 ReferenceError 弱引用(weak reference)试图访问一个已经被垃圾回收机制回收了的对象 RecursionError 超出最大递归深度 RuntimeError 一般的运行时错误 StopIteration 迭代器没有更多的值 SyntaxError Python的语法错误 IndentationError 缩进错误 TabError Tab和空格混合使用 SystemError Python编译器系统错误 SystemExit Python编译器进程被关闭 TypeError 不同类型间的无效操作 UnboundLocalError 访问一个未初始化的本地变量(NameError的子类) UnicodeError Unicode相关的错误(ValueError的子类) UnicodeEncodeError Unicode编码时的错误(UnicodeError的子类) UnicodeDecodeError Unicode解码时的错误(UnicodeError的子类) UnicodeTranslateError Unicode转换时的错误(UnicodeError的子类) ValueError 传入无效的参数 ZeroDivisionError 除数为零
4.1 异常处理
-
格式Ⅰ
try: 正在执行的代码块 (执行时, 会不断的捕获异常) except: 处理异常
异常演示 # num = int(input('请输入一个数字: ')) # 提示 ValueError, 代表 数值有误 # 异常处理 # try: # num = int(input('请输入一个数字: ')) # print('您输入的数字为 %d' % num) # except: # print('您输入的不是数字, 请重新输入')
-
格式Ⅱ
# 不同的错误, 报不同提示 try: 尝试的代码块 except 错误类型1: 处理方式1 except 错误类型2: 处理方式2
# num = int(input('请输入能够被100除的数字:')) # res = 100 / num # print(' 100 / %d = %.2f ' % (num, res) ) # try: # num = int(input('请输入能够被100除的数字:')) # res = 100 / num # print(' 100 / %d = %.2f ' % (num, res) ) # except ValueError: # print('您输入的不是数字') # except ZeroDivisionError: # print('除数不能为0')
-
格式III
# 多个不同的错误, 报相同的信息 try: 代码块 except(错误类型1, 错误类型2, ...): 处理方法a except(错误类型3, 错误类型4, ...): 处理方法b
try: num = int(input('请输入能够被100除的数字:')) res = 100 / num print(' 100 / %d = %.2f ' % (num, res) ) list1 = [10,20,30,40] print(list1[99]) dict1 = {'name': '杨超越', 'sex': '女'} print(dict1['age']) except (ValueError, ZeroDivisionError): print('您输入的数字不正确') except (IndexError, KeyError): print('您的索引or键 不存在或超过范围')
-
格式Ⅳ
# 出现未知的错误, 可以进行统一处理 try: num = int(input('请输入能够被100除的数字:')) res = 100 / num print(' 100 / %d = %.2f ' % (num, res) ) except Exception as error: print('未知错误: %s ' % error )
-
格式
# try: # 代码块1 # # except 错误类型1: # 处理方法1 # # except 错误类型2: # 处理方法2: # # except (错误类型3, 错误类型4, ...) # 处理方法3 # # except (错误类型5, 错误类型6, ...) # 处理方法4 # # except Exception as 变量 # 处理方法5 # # else: # 没有异常时, 才会执行该代码块 # # finally: # 无论是否有异常, 都会执行该代码块
4.2 主动抛出异常
-
① 场景
之前用的py解释器自己发现了错误, 自动抛出了异常
实际开发中, 有些业务逻辑无法满足时, 但是没有触犯语法问题
python不会自动报错, 只能我们自己 主动抛出异常
-
② 语法
try: raise Exception(自定义异常信息) except Exception as 别名: 处理异常
5. 流程控制符
-
continue
立马结束当前一轮循环, 准备下一轮循环
-
break
立马结束循环, 准备执行 循环外的代码
-
pass
占位,为了防止python报错
-
exit()
程序一旦执行到 exit()时, 会立马终止程序
二十、函数
1. 定义一个函数
-
1.1 函数代码段以
def
关键字开头,后接函数表示符名称和圆括号() -
1.2 任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数
-
1.3 函数的第一行语句可以选择性的使用文档字符串用于存放函数说明
-
1.4 函数内容以冒号起始,并且缩进
-
1.5
return [表达式]
结束函数,选择性的返回一个值给调用方,不带表达式的return相当于返回None -
1.6 语法
def 函数名(参数列表): 函数体
2. 函数的调用
-
函数名(参数)
def a(): print(666) a()
3. 参数传递
-
3.1 传递不可变对象(传值)
def num(a): a += 10 return a b = 2 print(num(b)) print(b) => 12 => 2
-
3.2传可变对象(传址)
def list1(a): a[0] += 10 return a list2 = [1,2,3] print(list1(list2)) print(list2) => [11, 2, 3] => [11, 2, 3]
4. 参数
- 4.1 位置参数 两个参数的顺序必须一一对应,且少一个参数都不可以
- 4.2 关键字参数 关键字参数和函数调用关系紧密,函数调用使用关键字参数来确定传入的参数值。 使用关键字参数允许函数调用时参数的顺序与声明时不一致.
- 4.3 默认参数 调用函数时,如果没有传递参数,则会使用默认参数。
- 4.4 不定长参数 1) 加了星号 * 的参数会以元组(tuple)的形式导入,存放所有未命名的变量参数。 2) 加了两个星号 ** 的参数会以字典的形式导入。 3) 如果单独出现星号 * 后的参数必须用关键字传入。
5. return
rturn [表达式]
语句用于退出函数,选择性地向调用方返回一个表达式。
不带参数值的return语句返回None。
5. 变量作用域
5.1 全局/局部变量
- 全局变量 在函数外部定义的变量,即为全局变量
- 局部变量 只能在其被声明的函数内部访问在函数内部定义的变量,即为局部变量
5.2 作用域
作用域 | 名词 | 简写 |
---|---|---|
局部作用域 | local | L |
闭包函数外的函数中 | enclosing | E |
全局作用域 | global | G |
内建作用域 | built-in | B |
以L->E->G->B的规则查找,在局部找不到,会去局部外的局部找,再找不到就会去全局找,再则去内建作用域中找
5.3 改变作用域
- global 在作用域E不能直接修改全局变量,在修改变量之前,同过global声明一下即可改变
- nonlocal 在作用域L中不能直接修改修改作用域E中的变量
改变G中的变量 global 改变E中的变量 nonlocal 在 global nonlocal 声明变量之前,不能更改这个变量.
6. 闭包函数
6.1定义
闭包就是能够读取其他函数内部变量的函数
- 函数A里面定义一个新的函数B
- 在函数B中使用了函数A的变量
只有满足以上两个条件,那么函数B即为闭包函数
6.2 使用方式
- 直接调用 在函数A直接调用函数B
def A():
x = 10
def B():
y = 20
y = x + y # 在 B函数中使用函数 A 的变量 x 这时候 B 是闭包函数
print(y)
B() # 直接调用 如果不执行B() 那么 不会去输出y
A()
=> 30
- 返回函数名
def A():
x=10
def B():
y=20
y=x+y
print(y)
return B # 返回 B 函数
res = A() # 接收了 到了 return 的函数B
print(res)
res()
=> <function A.<locals>.B at 0x0033C420>
=> 30
6.3 作用
- 优点: 数据的持久化
- 缺点: 因为持久化,没有及时释放所以占内存
6.4 注意事项
闭包函数不能直接修改外部函数的局部变量
7. 匿名函数
7.1 定义
**没有名字的函数,可当做表达式使用**
7.2 格式
`lambda 形参:需要返回的结果`
冒号左边: **想要传递的参数**
冒号右边: **return想要的结果**
原理解析 相当于一个def
7.3 作用
- 匿名函数仅适合不想取函数名,功能简单
- 匿名函数可做表达式,并非语句,所以用在def不能用的地方
8. 高阶函数
8.1 定义
- 参数为函数
- 返回值为函数
满足以上任意一点, 即为高阶函数
8.2 作用
- 易于可读性
- 方便代码维护
- 隔离作用域
8.3 高阶函数
-
1)map(def, iterable1, iterable2, …) 功能:将可迭代对象中的每一个对象, 都是用一遍函数 参数: def: 内置函数或自定义函数 iterable: 可迭代对象 返回值: 对象
# 需求: # 将 1 ~ 10 每一个值都开平方 def power(x): return x ** 2 for i in map(power, range(1,11) ): print(i)
-
2)filter( def, iterable) 功能: 过滤 可迭代对象中的数据, 保留符合条件的数据 参数: def: 内置函数 or 自定义函数 iterable: 可迭代对象 返回值: 满足条件, 则返回对应的迭代数据, 不是返回bool
# 需求: # 以列表形式输出 1 ~ 10 之间的偶数 def iseven(x): return x % 2 == 0 a = list( filter(iseven, range(1,11)) ) print(a)
-
3)sorted(iterable, reverse=False, key=None ) 功能: 将可迭代对象进行排序, 生成排好的序列 参数: iterable: 可迭代对象 reverse: False 升序, 默认 True 降序 key: 排序依据, 默认none 返回值: 排好序后的 可迭代对象
# 需求1: # 按照 值的大小升序 a = set('123456789') b = sorted(a) print(a,b)
-
4)reduce(def, iterable) 功能: 对可迭代对象的每一个对象进行累加操作 参数: def: 内置 or 自定义函数 iterable: 可迭代对象
返回值: 累加之后的值from functools import reduce # 在使用reduce() 之前, 必须先导入该模块 a = [1,2,3,4,5] def add(x,y): return x+y b = reduce(add, a) print(b)
二十一、容器
1. 容器嵌套
1.1 列表嵌套
-
二维列表
a = [ [], [], [], [] ]
-
三维列表
a = [ [ [], [], [], [] ], [ [], [], [], [] ] ]
-
多维列表的操作
a = [ ['1', '2'], ['3', '4'], ['5', '6'], ['7', '8'] ] print( a[3] ) print( a[3][0] ) => ['7', '8'] => 7
说明: 若嵌套了一层, 可称之为 二维列表 若嵌套了二层, 可称之为 三维列表 依次类推
1.2 元组嵌套
a = (
['1', '2'],
['3', '4'],
['5', '6'],
['7', '8']
)
print( a[1][1] )
a[1][1] = '光头强'
print( a[1][1] )
=> 3
=> 光头强
1.3 字典嵌套
a = {
'name': ['小明', '小兰'],
'age': [18, 28],
'sex': ['女', '男'],
}
print( a['name'][1] )
=> 小兰
2. 容器遍历
2.1 list遍历
a = ['1', '2', '3', '4', '5']
i = 0
while i < 4:
print(i, a[i],end=" ")
i += 1
a = ['1', '2', '3', '4', '5']
# i 代表索引
for i in range(4):
print(i, a[i], end=" ")
# 灵活遍历 列表值
a = ['1', '2', '3', '4', '5']
print( len(a) ) # 获取当前列表a 有几个值 (长度)
length = len(a)
for i in range( length ):
print(i, a[i], end=" ")
a = ['1', '2', '3', '4', '5']
# i 代表值
# a.index(i) 获取值i 在a列表里面的索引
for i in a:
print(a.index(i), i, end=" ")
2.2 tuple遍历
a = ['1', '2', '3', '4', '5']
# i 代表索引
for i in range(5):
print(i, a[i], end=" ")
a = ['1', '2', '3', '4', '5']
for i in range( len(a) ):
print(i, a[i], end=" ")
a = ['1', '2', '3', '4', '5']
for i in a:
print(a.index(i), i, end=" ")
2.3 dict遍历
a = {'name':'关二哥', 'age':'56', 'sex':'男'}
for i in a:
print(i, end=" ") # i 代表 键
print(a[i], end=" ") # a[i] 代表 值
a = {'name':'关二哥', 'age':'56', 'sex':'男'}
# 专门获取键
for i in a.keys():
print(i, end=" ")
a = {'name':'关二哥', 'age':'56', 'sex':'男'}
# 专门获取值
for i in a.values():
print(i, end=" ")
a = {'name':'关二哥', 'age':'56', 'sex':'男'}
# 专门获取键和值
for i,j in a.items():
print('i= %s' % i, end=" ")
print('j= %s' % j)
2.4 set遍历
a = {'醋', '可乐', '生姜汁', '芥末汁', '苦瓜汁', '黑啤'}
for i in a:
print(i, end=" ")
2.5 多维容器遍历
a = [
['1','2','3'],
['4','5','6'],
['7','8','9'],
]
for i,j,k in a:
print(k, end=" ")
=> 3 6 9
a = {
'name': ['姬发', '妲己'],
'sex': ['男','女'],
'age': [18, 28]
}
for i,j in a.items():
print(i, end=" ")
print(j)
for i,j in a.items():
for x in j: # j 是每一个键后面对应的 列表
print(x)
二十二、推导式
一. 列表推导式
1. 基本推导式
- 格式:
[ 变量操作 for 变量 in 容器]
- 返回值: 新的容器
- 分析: 变量: 每次从容器 获取一个值 变量操作: 将得到的变量 进行操作, 操作的结果给 列表
2. 条件推导式
-
格式:
[ 变量操作 for 变量 in 容器 if 条件 ]
[ true环境 if 条件 else false环境 for 变量 in 容器 ]
3. 多循环推导式
-
格式:
[ 变量操作 for 变量1 in 容器1 for 变量2 in 容器2 ]
4. 多循环条件推导式
-
格式:
[ 变量操作 for 变量1 in 容器1 for 变量2 in 容器2 if 条件]
[ true环境 if 条件 else false环境 for 变量1 in 容器1 for 变量2 in 容器2 ]
二. 字典推导式
1. 基本推导式
-
格式:
{ 键:值 for 键,值 in 字典.items() }
2. 条件推导式
-
格式:
{ 键:值 for 键,值 in 字典.items() if 条件}
3. 多循环推导式
-
格式:
{ 键:值 for 键1,值1 in 字典1.items() for 键2,值2 in 字典2.items() }
4. 多循环条件推导式
-
格式:
{ 键:值 for 键1,值1 in 字典1.items() for 键2,值2 in 字典2.items() if 条件 }
三. 集合推导式
1. 基本推导式
-
格式:
{ 变量操作 for 变量 in 集合 }
2. 条件推导式
-
格式:
{ 变量操作 for 变量 in 集合 if 条件 }
3. 多循环推导式
-
格式:
{ 变量操作 for 变量1 in 集合1 if 条件 for 变量2 in 集合2 }
4. 多循环条件推导式
-
格式:
{ 变量操作 for 变量1 in 集合1 for 变量2 in 集合2 if 条件}
二十三、迭代器
1. 可迭代对象iterable
够被for循环遍历的容器 都是可迭代对象
能迭代的对象: list, tuple, dict, set, range, 生成器等
from collections import Iterable # 导入 Iterable模块
# isinstance() 来检测是否为 可迭代对象
print( isinstance([], Iterable) )
print( isinstance((), Iterable) )
print( isinstance({}, Iterable) )
print( isinstance(set(), Iterable) )
print( isinstance(range(10), Iterable) )
print( isinstance(10, Iterable) )
print( isinstance('abc', Iterable) )
2. 迭代器iterator
将可迭代对象一个一个的获取出来
-
创建迭代器 iter()
a=iter([1,2,3,4]) print(a)
-
迭代可迭代对象next()
print(next(a)) print(next(a)) print(next(a)) print(next(a))
-
小结:
迭代器是需要用时,才去拿一个,人称:懒加载 循环是一旦开始,就必须把对象中的数据全部拿出来
二十四、生成器
1. 生成器 generator
列表推导式,可以直接创建一个新的列表,一旦数据量过大,必然会受到内存的限制.此时只需要用到其中几个数据,就太浪费内存和性能 最佳方法:通过算法,一边循环,一边计算,要多少那多少,不要不生成 既满足推导式,又节省了空间(避免一次性生成整个列表)
生成器就是迭代器 迭代器不是生成器
2. 分类
2.1 生成器表达式
-
格式: 生成器对象 = (变量操作 for 变量 in 容器)
a = ( 2**i for i in range(10) ) print(a) => <generator object <genexpr> at 0x01D8EE30>
-
返回值: 生成器对象,并非元组
说明: 形式推导式,将推导式[]转成(),可以当做元组推导式,但python没有元组推导式
- 获取生成器中的值: 方法1:next(生成器) 方法2:生成器.next()
2.2 函数生成器
-
定义: 包含 关键字yield 的函数就是生成器
-
执行原理: 在生成器执行过程中, 遇到 yield就会立马中断并return yield所修饰的变量. 当再次调用生成器时, 会接着上一次的中断点后继续执行
def test(): i = 0 while i < 5: yield i # return i i += 1
3. 迭代生成器
生成器 也是 可迭代对象之一
4. 传参
每次yield立马返回变量 i , 下一次迭代 res = None了 能否在下一次迭代时, 传入参数, 以保证 res 不等于 None 在下一次迭代时, 通过 send() 方法传入参数
def test():
i = 0
while i < 5:
res = yield i # return i 一旦返回后 res = None 空
print(res)
i += 1
a = test()
print( next(a) )
print( next(a) )
print( a.send('hello'))
print( next(a) )
5. 迭代器和生成器的区别
生成器 肯定是 迭代器 迭代器 不一定是 生成器
- 迭代器: 仅仅为了将 可迭代对象中的值 一个一个获取出来
- 生成器: 通过 算法一个一个计算并创造出来, 且能终止函数, 将参数传入生成器, 最后接着中断点 继续向后执行
二十五、装饰器
python装饰器本质上就是一个函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外的功能,装饰器的返回值也是一个函数对象(函数的指针)。装饰器函数的外部函数传入我要装饰的函数名字,返回经过修饰后函数的名字;内层函数(闭包)负责修饰被修饰函数。
实质: 是一个函数
参数:是你要装饰的函数名(并非函数调用)
返回:是装饰完的函数名(也非函数调用)
作用:为已经存在的对象添加额外的功能
特点:不需要对对象做任何的代码上的变动
1. 函数装饰器
import time
def decorator(func):
def wrapper(*args, **kwargs):
start_time = time.time()
func()
end_time = time.time()
print(end_time - start_time)
return wrapper
@decorator
def func():
time.sleep(0.8)
func() # 函数调用
# 输出:0.800644397735595
在上面代码中 func是我要装饰器的函数,我想用装饰器显示func函数运行的时间。@decorator这个语法相当于 执行 func = decorator(func),为func函数装饰并返回。在来看一下我们的装饰器函数 - decorator,该函数的传入参数是func (被装饰函数),返回参数是内层函数。这里的内层函数-wrapper,其实就相当于闭包函数,它起到装饰给定函数的作用,wrapper参数为*args, kwargs。*args表示的参数以列表的形式传入;kwargs表示的参数以字典的形式传入:
从图中我们可以看到:凡是以key=value形式的参数均存在kwargs中,剩下的所有参数都以列表的形式存于args中。这里要注意的是:为了不破坏原函数的逻辑,我们要保证内层函数wrapper和被装饰函数func的传入参数和返回值类型必须保持一致。
2. 类方法的函数装饰器
类方法的函数装饰器和函数的函数装饰器类似。
import time
def decorator(func):
def wrapper(me_instance):
start_time = time.time()
func(me_instance)
end_time = time.time()
print(end_time - start_time)
return wrapper
class Method(object):
@decorator
def func(self):
time.sleep(0.8)
p1 = Method()
p1.func() # 函数调用
对于类方法来说,都会有一个默认的参数self,它实际表示的是类的一个实例,所以在装饰器的内部函数wrapper也要传入一个参数 - me_instance就表示将类的实例p1传给wrapper,其他的用法都和函数装饰器相同。
3. 类装饰器
class Decorator(object):
def __init__(self, f):
self.f = f
def __call__(self):
print("decorator start")
self.f()
print("decorator end")
@Decorator
def func():
print("func")
func()
# __call__()是一个特殊方法,它可将一个类实例变成一个可调用对象
要使用类装饰器必须实现类中的__call__()方法,就相当于将实例变成了一个方法。
4. 装饰器链
一个python函数也可以被多个装饰器修饰
多个装饰器的执行顺序:是从近到远依次执行。
二十六、模块
1. 定义
在实际开发中, 有一些功能会被多个不同的文件所使用. 为了避免多次复制, 可将这些功能写入模块, 这样哪个文件需要, 就引入该模块即可 每一个py文件都可以当做模块 (其他模块文件有: xxx.pyc xxx.pyo xxx.dll xxx.pyd xxx.so) 模块可以包含变量, 函数 和 可执行的语句 等代码
2.分类
2.1 开源模块
常见有趣的模块: 爬虫, 数据分析, 数据处理, 机器学习 等 开源模块地址: https://pypi.org/ 游戏模块地址: http://www.pygame.org/
2.2 内置模块
python自带的内置模块, 例如: string模块, math模块, random模块, time模块
2.3自定义模块
根据客户需求, 自己编辑py文件,形成一个模块, 供给其他人使用
3. 引入模块(整个模块)
- 格式:
import 模块1
import 模块2
import 模块1, 模块2, 模块3, ...
- 注意: 每一个import 都是独占一行
使用模块的工具: 模块名.变量名 这里的变量名 称之为 属性名 模块名.函数名() 这里的函数名 称之为 方法名
# 引入 内置模块string
import string
print(string.ascii_letters)
# 引入 自定义模块test
import test
print(test.name)
print(test.demo())
4. 局部引入
- 格式:
from 模块1 import 工具名
局部引入后, 就不需要再声明前缀(哪个模块), 可以直接使用
from test import demo
print( demo() )
5. 别名
- 格式:
import 模块1 as 别名
import test as T
print(T.name)
print(T.demo())
from test import demo as D
print( D() )
6.同名引入
由于 from … import 引入, 不需要前缀, 可能会导致引入不同模块的 相同工具名. 此种情况, 会发生后面的模块 会覆盖前面的模块
- 解决方案: 给相同的工具名 取不同的别名
from test import demo as D
from test2 import demo
print( demo() )
print( D() )
7.模块引入路径
7.1 引入
python会从以下几个目录 来查找模块:
- 当前目录
- 主程序目录\Dlls python解释器的安装目录
- 主程序目录\Lib
- 主程序目录
- 主程序目录\Lib\site-packages
import sys # 引入系统模块
print(sys.path)
7.2 file__属性
- 获取当前文件路径 or 引入模块的路径
print( __file__ )
7.3 __name__属性
获取当前文件的名字 or 引入模块的名字
print( __name__ )
若是当前文件, 则返回
__main__
, 同时证明当前文件就是 正在运行的主程序 若是引入的模块, 则返回 模块名, 同时证明当前文件是 别人引入的模块
二十七、面向对象 OOP
1. 概念
OOP 只是一种编程思想
- 类: 就是一个抽象, 虚拟的的事物
- 对象: 就是真实, 实际的对象
2. 类
-
定义
class 类名(): 属性(有什么) 方法(会什么)
- 类名:
- 大驼峰命名法
- 名词
- 严格区分大小写
- 属性名:
- 由数字,字母和下划线组成
- 不能以数字开头
- 方法名:
- 小写,下划线命名法
- 动词+名词
- 类名:
-
注意: 类一旦定义, 就会占据一个内存 类不实例化, 则不能正常使用
3. 对象
- 3.1 实例化对象 格式: 对象 = 类名()
- 3.2 通过对象使用属性 格式: 对象.属性名
- 3.3 通过对象使用方法 格式: 对象.方法名()
从同一个类实例化出来的对象, 内存各不一样, 对象互不影响
4. OOP特性
OOP 三大特性: 封装性, 继承性, 多态性
4.1 封装性
- ① 定义: 主要负责保护数据隐私 和 隔离复杂度
- ② 保护数据的隐私 只要数据不能被外界所获取, 就能起到保护的数据的作用
私有属性: __属性名
私有方法: __方法名()
- ③ 注意: 在python中,没有完全意义上的私有化,通过特殊方式,能在外界获取私有属性
class Demo():
__name = '二狗'
def __skill(self):
print('阴阳狗')
# 外界
dog = Demo()
# print( dog.__name ) #报错
print( dog._Demo__name ) # 特殊访问方式
在实际开发中,千万不要如此获取,否则就失去了私有的意义
4.2 继承性
子类继承父类的一些属性和方法
- 定义 主要负责类的继承, 扩展, 降低代码的冗余率(代码重复度)
- 格式
class 子类名(父类名):
代码块
- 特性
- 可以继承属性和方法 (不能继承私有属性和方法)
- 可以重写属性和方法
- 扩展父类
- 支持单继承, 连续继承, 多继承
4.2.1 单继承 一个子类只继承一个父类
4.2.2连续继承
4.2.3多继承
-
格式:
class 子类(父类1, 父类2, 父类3, ...)
-
继承冲突: 当继承发生冲突时,采用就近原则,先继承谁,就继承谁的属性和方法(在实际开发中, 尽量避免此种情况发生, 容易混淆)
-
继承顺序: 当多继承较多时, 可通过 mro 来查看继承顺序 使用格式:
类名.__mro__
-
发现:
继承中, 所有的类最终都会继承object
在祖辈类 object中, 提供实例化的方法
4.3 多态性
- 定义: 通过同一个类 , 传入不同的对象,从而实现不同的效果
- 有点: 提高代码的灵活度
5. 伪对象
-
定义:
伪对象可以在当前类内 操作使用属性和方法
-
self :
self代表类的实例,而非类
-
位置: 设在每个方法中参数的第一个位置
-
命名: 常用命名self, 可以修改命名
-
格式:
self.属性名 self.方法名()
-
创建属性 (共享)
在某方法内, 通过self.属性名 = 值
该属性已存在, 则为 修改属性
该属性不存在, 则为 创建属性
-
注意:
self 相当于当前独享
self的内存地址 与 对象内存地址相同
-
6. 构造方法
-
方法名:
__init__
-
触发条件: 在实例化时, 自动调用
-
主要作用: 初始化属性
-
给
__init__
传递参数:对象 = 类名(参数)
-
-
位置: 构造一般写在属性的最后面, 方法的最前面
7. 析构方法
-
方法名:
__del__
-
触发条件 : ① 在对象被销毁时, 会自动触发
③ 对象被覆盖时 ④ 对象被删除时② 当前文件全部执行完时
-
主要作用 : 在对象结束时, 做结尾操作
-
位置 : 析构一般写在方法的最后面
二十八、文件操作
在计算机中, 基本文件操作就三步:
- 打开文件
- 操作文件(读/写)
读: 将文件中的内容读取出来
写: 增删改文件内容
- 关闭文件
1. 打开文件
- open(文件路径, 打开模式, 本地编码)
- 返回值: 文件对象, 文件句柄
2. 写文件
-
w模式:
指针指向开头, 重写内容(删除原来的内容)
文件不存在, 则自动创建
-
文件句柄.write(内容)
-
返回值: 内容长度
4. 读文件
-
r模式
指针指向开头, 读取内容
文件不存在, 则报错
-
返回值: 读取的内容
5. 追加文件
-
文件句柄 = open(‘文件路径’, ‘a’)
-
a模式
指针指向末尾, 写入内容(不会删除原来的内容)
文件不存在, 则自动创建
-
文件句柄.write(内容)
6. 增强模式
-
+模式
同时具备读写能力, 配合 rwa 使用(r+,w+,a+)
-
以r模式打开, 做写操作, 违反权限
以w模式打开, 做读操作, 违反权限
-
以a+模式, 做读操作, 可以执行
以r+模式, 做写操作, 可以执行
注: 由于r+ 模式, 指针指向开头, 再次写入时, 会从开头依次写入, 会覆盖原有位置的内容
7. 关闭文件
- 文件句柄.close()
- 释放内存
8. 序列写入
- 文件句柄.writelines(序列)
- 将序列中的值一个一个写入文件
9. 读取一行内容
- 文件句柄.readline(位数)
- 返回值: 字符串
10. 读取所有内容
- 文件句柄.readlines()
- 返回值: 列表
11. 截取内容
- 文件句柄.truncate(字节)
- 作用: 保留截取的内容, 删除剩余的内容
- 返回值: 截取的字节
12. 缓冲区
-
文件句柄.flush()
-
原理:
wirte写操作 -> 内容 -> 缓冲区 -> flush -> 文件
-
自动刷新缓冲区:
1) 整个程序结束时, 自动刷新缓冲区
2) 文件关闭时, 自动刷新缓冲区
3) 当缓冲区写满时, 自动刷新缓冲区
13. with
自动关闭文件
-
格式:
with 打开文件 as 句柄: 文件操作(代码块) # 当代码块执行结束时, 句柄.close() 会自动执行
二十九、正则
findall()
import re
string="abcdefg acbdgef abcdgfe cadbgfe"
#带括号与不带括号的区别
#不带括号
regex=re.compile("((\w+)\s+\w+)")
print(regex.findall(string))
#输出:[('abcdefg acbdgef', 'abcdefg'), ('abcdgfe cadbgfe', 'abcdgfe')]
regex1=re.compile("(\w+)\s+\w+")
print(regex1.findall(string))
#输出:['abcdefg', 'abcdgfe']
regex2=re.compile("\w+\s+\w+")
print(regex2.findall(string))
#输出:['abcdefg acbdgef', 'abcdgfe cadbgfe']
findall()函数返回的总是正则表达式在字符串中所有匹配结果的列表list,此处主要讨论列表中“结果”的展现方式,即findall中返回列表中每个元素包含的信息。
- 1.当给出的正则表达式中带有多个括号时,列表的元素为多个字符串组成的tuple,tuple中字符串个数与括号对数相同,字符串内容与每个括号内的正则表达式相对应,并且排放顺序是按括号出现的顺序。
- 2.当给出的正则表达式中带有一个括号时,列表的元素为字符串,此字符串的内容与括号中的正则表达式相对应(不是整个正则表达式的匹配内容)。
- 3.当给出的正则表达式中不带括号时,列表的元素为字符串,此字符串为整个正则表达式匹配的内容。
三十、PyMySQL
1. PyMySQL安装
pip install pymysql
2. 连接数据库
通过如下代码测试数据库连接
import pymysql
# 打开数据库连接
db = pymysql.connect("localhost","root","123456","mydb" )
# 使用 cursor() 方法创建一个游标对象 cursor
cursor = db.cursor()
# 使用 execute() 方法执行 SQL 查询
cursor.execute("SELECT VERSION()")
# 使用 fetchone() 方法获取单条数据.
data = cursor.fetchone()
print ("Database version : %s " % data)
# 关闭数据库连接
db.close()
3. 执行数据添加
import pymysql
# 打开数据库连接
db = pymysql.connect("localhost","root","123456","mydemo" )
# 使用 cursor() 方法创建一个游标对象 cursor
cursor = db.cursor()
# SQL 插入语句
sql = "INSERT INTO stu(name,sex,age,classid) values('%s','%c','%d','%s')" % ('uu142','m',22,'lamp180')
try:
# 执行sql语句
cursor.execute(sql)
# 执行sql语句
db.commit()
print("ok: %d " % (cursor.rowcount))
except:
# 发生错误时回滚
db.rollback()
# 关闭数据库连接
db.close()
4. 执行删除操作
import pymysql
# 打开数据库连接
db = pymysql.connect("localhost","root","","mydemo" )
# 使用 cursor() 方法创建一个游标对象 cursor
cursor = db.cursor()
# SQL 删除语句
sql = "delete from stu where id = '%d'" % (13)
try:
# 执行SQL语句
cursor.execute(sql)
# 提交修改
db.commit()
except:
# 发生错误时回滚
db.rollback()
# 关闭数据库连接
db.close()
5. 执行数据修改/更新
import pymysql
# 打开数据库连接
db = pymysql.connect("localhost","testuser","test123","TESTDB" )
# 使用cursor()方法获取操作游标
cursor = db.cursor()
# SQL 更新语句
sql = "UPDATE EMPLOYEE SET AGE = AGE + 1
WHERE SEX = '%c'" % ('M')
try:
# 执行SQL语句
cursor.execute(sql)
# 提交到数据库执行
db.commit()
except:
# 发生错误时回滚
db.rollback()
# 关闭数据库连接
db.close()
6. 执行数据查询
Python查询Mysql使用 fetchone() 方法获取单条数据, 使用fetchall() 方法获取多条数据。
fetchone(): 该方法获取下一个查询结果集。结果集是一个对象
fetchall(): 接收全部的返回结果行.
rowcount: 这是一个只读属性,并返回执行execute()方法后影响的行数。
import pymysql
# 打开数据库连接
db = pymysql.connect("localhost","root","","mydemo" )
# 使用 cursor() 方法创建一个游标对象 cursor
cursor = db.cursor()
# SQL 查询语句
sql = "select * from stu limit %d" % (3)
#sql = "select * from stu"
try:
# 执行SQL语句
cursor.execute(sql)
# 获取所有记录列表
results = cursor.fetchall()
for row in results:
id = row[0]
name = row[1]
sex = row[2]
age = row[3]
classid = row[4]
# 打印结果
print ("id=%d,name=%s,sex=%s,age=%d,classid=%s" % (id,name,sex,age,classid))
except:
print ("Error: unable to fetch data")
# 关闭数据库连接
db.close()
7. 模板
# db.py 连接数据库、执行sql语句
import pymysql
class DB():
def __init__(self,database = 'py05',user='root',password='123456',port = 3306,host = 'localhost'):
self.db = pymysql.connect(host = host,port=port,user = user,database = database,password = password,charset ='utf8mb4')
self.cursor = self.db.cursor()
def update(self,sql, data):
try:
self.cursor.execute(sql, data)
self.db.commit()
except:
print("操作失败,请检查sql语句")
def query(self,sql):
try:
self.cursor.execute(sql)
data = self.cursor.fetchall()
return data
except:
print("查询失败,请检查sql语句")
def __del__(self):
self.cursor.close()
self.db.close()
常用模块
string 模块
print("~~~~~~~~~~~~~string~~~~~~~~~~~~")
import string # 获取的数据类型均为 string
a = string.ascii_letters # 获取所有的大小写字母
a = string.ascii_lowercase # 获取所有的小写字母
a = string.ascii_uppercase # 获取所有的大写字母
a = string.digits # 获取所有的十进制基数
a = string.hexdigits # 获取所有的十六进制基数
a = string.octdigits # 获取所有的八进制基数
a = string.punctuation # 获取所有的标点符号
a = string.whitespace # 获取所有的空白符号
print(a)
random 模块
print("~~~~~~~~~~~~~random~~~~~~~~~~~~")
import random
a = random.random() # (0,1)之间的随机数
a = random.randrange(1,10) # [1,10)之间的随机数
a = random.randrange(1,10,2) # [1,10)之间的随机数步长为2
a = random.randint(1,10) # [1,10]之间的随机整数
a = random.uniform(1,10) # [1,10]之间的随机小数
x = [1,2,3,4,'a','b','c','d']
a = random.choice(x) # 随机获取容器中的一个数据(不支持字典集合)
a = [1,2,3,4,'a','b','c','d']
random.shuffle(a) # 打乱列表
print(a)
math 模块
print("~~~~~~~~~~~~~math~~~~~~~~~~~~")
import math
a = math.ceil(3.2) # 进一取整
a = math.floor(3.2) # 舍一取整
a = math.pow(3,2) # 指数
a = math.sqrt(3) # 平方根
a = math.fabs(-5) # 绝对值
a = math.pi # 圆周率
a = math.e # 自然底数
print(math.fsum([1,2,3,4])) # 求和
print(a)
只支持整数
按位异或
>>> ~3
-4
按位取反
>>> a=324
>>> b=432423
>>> a^=b
>>> a
432227
>>> b ^= a
>>> b
324
>>> a^=b
>>> a
432423
time 模块
time 模块
print("~~~~~~~~~~~~~time~~~~~~~~~~~~")
import time
a = time.time() # 获取时间戳(1970~现在的秒数)
a = time.gmtime() # 世界时间元组(格林威治)
a = time.localtime() # 本地时间元组
a = time.ctime() # 格式化时间戳
a = time.asctime() # 格式化时间元组
a = time.asctime(time.gmtime())
a = time.strftime('%Y/%m/%d %H:%M:%S', time.localtime()) # 时间元组转自定义格式化时间
a = time.strptime('2018-10-11 15:32:46', '%Y-%m-%d %H:%M:%S') # 自定义时间字符串转时间元组
a = time.mktime((2018,11,11,11,11,11,0,0,0)) # 创建时间戳
time.sleep(2) # 延迟
a = time.perf_counter() # 系统运行的时间,包含延迟时间
a = time.process_time() #CPU的消耗时间,不包含延迟时间
print(a)
calendar 模块
print("~~~~~~~~~~~~~calendar~~~~~~~~~~~~")
import calendar
a = calendar.calendar(2019) # 某年的日历
a = calendar.month(2019,3) # 某月的日历
a = calendar.isleap(2019) # 是否闰年
print(a)
datetime 模块
print("~~~~~~~~~~~~~datetime~~~~~~~~~~~~")
import datetime
a = datetime.date(2019,3,19) # 设置时间对象
print(a.year)
print(a.month)
print(a.day)
print(a.weekday())
print(a.isoweekday())
a = datetime.datetime.now() #获取当前本地时间
a = datetime.datetime.fromtimestamp(1536554000) # 格式化时间戳
a = datetime.time(21,18,30,123456) # 设置时间对象
print(a.hour)
print(a.minute)
print(a.second)
print(a.microsecond)
print(a.tzinfo)
a = datetime.timedelta(1) # 用于时间加减
a = datetime.datetime.now() + datetime.timedelta(1) # 一天后
a = datetime.datetime.now() - datetime.timedelta(hours=3) # 3小时前
print(a)
os 模块
print("~~~~~~~~~~~~~os~~~~~~~~~~~~")
import os
a = os.name # name属性
a = os.sep # sep属性
a = os.getcwd() # 查看当前工作目录
# os.mkdir('a') # 在当前目录下创建新的目录
# os.mkdir('./b')
# os.mkdir('../c') # 上级目录
# os.mkdir('../../d') # 上上级目录
# os.makedirs('./x/y/z') # 创建多级目录
# os.rmdir('./a') # 删除目录
# os.chdir('./x/y') # 修改当前目录路径
# os.system('type null > a.txt') # 创建文件
# os.system('del a.txt') # 删除文件
# os.system('dir') # 查看当前目录的所有文件
# os.system('mkdir') # 创建目录
# os.system('rmdir') # 删除目录
# os.system('pint www.baidu.com') # 检测是否能链接
# os.remove('./dome/a.txt') # 删除文件
# a = os.listdir('./demo') # 获取指定目录下的所有文件和目录
a = os.path.exists('./demo/a.txt')
a = os.path.exists('./demo') # 判断文件或目录是否存在
a = os.path.isfile('./demo/a.txt') # 判断是否为文件
a = os.path.isdir('./demo') # 判断是否为目录
a = os.path.abspath('./demo') # 获取绝对路径
a = os.path.join('demo','a','a.txt')# 拼接路径
a = os.path.split('./demo/a.txt') # 拆成(目录,文件名)
a = os.path.splitext('./demo/a.txt')# 拆成(扩展名前面的部分,扩展名)
a = os.path.dirname('./demo/a.txt') # 获取目录
a = os.path.basename('./demo/a.txt')# 获取文件名
a = os.path.getsize('./demo/a.txt') # 获取文件大小(目录不行)
print(a)
shutil 模块
print("~~~~~~~~~~~~~shutil~~~~~~~~~~~~")
import shutil
# shutil.copyfile(来源地址,目标地址) # 拷贝文件内容(dst 不存在, 则自动创建, 已存在, 则删除原有内容)
# shutil.copyfile('./a.txt', './b.txt')
# shutil.copymade('./a.txt', './b.txt') # 拷贝权限
# shutil.copystat('./a.txt', './b.txt') # 拷贝状态 (权限+时间)
# shutil.copy('./a.txt', './b.txt') # 拷贝权限 + 内容(若 dst已存在, 则会报错)
# shutil.copy2('./a.txt', './b.txt') # 拷贝状态 + 内容
# shutil.copytree('./demo','./test') # 拷贝多级目录
# shutil.rmtree('./test') # 删除多级目录
# shutil.move('./test', './test2') # 剪切/重命名(同一目录下即为重命名,不同目录下即为剪切)
zipfile 模块
print("~~~~~~~~~~~~~zipfile~~~~~~~~~~~~")
import zipfile
# 压缩
# 1. 创建zip包
# 返回zip包对象
# demo = zipfile.ZipFile('./demo.zip', 'a', zipfile.ZIP_DEFLATED)
# 2. 添加文件 进zip包# demo.write('./demo')
# 3. 关闭zip包
# demo.close()
# ----------------------------------------
# 解压
# 1. 读取 zip 包
# demo = zipfile.ZipFile('./demo.zip', 'r')
# 2. 解压文件
# 单个解压
# demo.extract('f.txt', './test')
# 全部解压
# demo.extractall('./test')
# 3. 关闭zip包
# demo.close()
# ----------------------------------------
# ZipFile方法:
# ZipFile(filename, mode, 压缩方式)
# 参数:
# filename: 自定义zip包的路径
# mode:
# r: read 读取zip包的模式
# w: write 往zip包里面写入内容 (会删除原有的内容, 若包不存在, 则会自动创建)
# a: append 往zip包里面追加内容 (不会删除原来的内容, 若包不存在, 则会自动创建)
# 压缩方式:ZIP_STORED 仅仅是将文件填入仅zip包, 并非真正的压缩,默认
# ZIP_DEFLATED 将文件填入zip包, 通过zlib算法进行空间压缩
# ----------------------------------------
# 包.write( filename, 别名)
# 参数:
# filename : 将哪个文件写入包里面
# 别名: 将filename取个别名, 同时可以换路径
列表转字符串-换行去空格
content = '\n'.join([item.strip() for item in content_list if item.strip() != ''])
Python 3.8.0 重要新特性&优化
以下是 Python 3.8 相比 3.7 的新增特性。
- PEP 572,赋值表达式
- PEP 570,仅限位置形参
- PEP 587,Python 初始化配置(改进的嵌入)
- PEP 590,Vectorcall:用于 CPython 的快速调用协议
- PEP 578, Python Runtime Audit Hooks
- PEP 574,具有外部数据缓冲区的 pickle 协议 5
- 与打字相关:PEP 591(最终限定词),PEP 586(文学类型)和 PEP 589(TypedDict)
- 用于已编译字节码文件的并行文件系统缓存
- 调试构建使用与发布构建相同的 ABI
- f - 字符串支持 = 用于自动记录表达式和调试文档
- 在 Windows 上,默认 asyncio 事件循环现在是 ProactorEventLoop
- 在 macOS 上,spawn 启动方法默认使用 multiprocessing
- multiprocessing 现在可以使用共享内存段来避免进程之间的酸洗成本
- typed_ast 被合并回 CPython
- LOAD_GLOBAL 速度加快了 40%
- pickle 现在默认使用协议 4,提高了性能
赋值表达式 Python 3.8.0 有一个新的语法 :=,它将值赋给一个更大的表达式中的变量。它被亲切地称为 “海象运算符”(walrus operator),因为它长得像海象的眼睛和象牙。 海象 这个 “海象运算符” 在某些时候可以让你的代码更整洁,比如:
在这个示例中,赋值表达式可以避免调用 len () 两次:
if (n := len(a)) > 10:
print(f"List is too long ({n} elements, expected <= 10)")
类似的益处还可出现在正则表达式匹配中需要使用两次匹配对象的情况中,一次检测用于匹配是否发生,另一次用于提取子分组:
discount = 0.0
if (mo := re.search(r'(\d+)% discount', advertisement)):
discount = float(mo.group(1)) / 100.0
此运算符也适用于配合 while 循环计算一个值来检测循环是否终止,而同一个值又在循环体中再次被使用的情况:
#Loop over fixed length blocks
while (block := f.read(256)) != '':
process(block)
另一个值得介绍的用例出现于列表推导式中,在筛选条件中计算一个值,而同一个值又在表达式中需要被使用:
[clean_name.title() for name in names
if (clean_name := normalize('NFC', name)) in allowed_names]
请尽量将海象运算符的使用限制在清晰的场合中,以降低复杂性并提升可读性。
仅限位置形参
新增了一个函数形参语法 / 用来指明某些函数形参必须使用仅限位置而非关键字参数的形式。这种标记语法与通过 help () 所显示的使用 Larry Hastings 的 Argument Clinic 工具标记的 C 函数相同。
在下面的例子中,形参 a 和 b 为仅限位置形参,c 或 d 可以是位置形参或关键字形参,而 e 或 f 要求为关键字形参:
def f(a, b, /, c, d, *, e, f):
print(a, b, c, d, e, f)
以下均为合法的调用:
f(10, 20, 30, d=40, e=50, f=60)
但是,以下均为不合法的调用:
f(10, b=20, c=30, d=40, e=50, f=60) # b cannot be a keyword argument
f(10, 20, 30, 40, 50, f=60) # e must be a keyword argument
这种标记形式的一个用例是它允许纯 Python 函数完整模拟现有的用 C 代码编写的函数的行为。例如,内置的 pow () 函数不接受关键字参数:
def pow(x, y, z=None, /):
"Emulate the built in pow() function"
r = x ** y
return r if z is None else r%z
另一个用例是在不需要形参名称时排除关键字参数。例如,内置的 len () 函数的签名为 len (obj, /)。这可以排除如下这种笨拙的调用形式:
len(obj='hello') # The "obj" keyword argument impairs readability
另一个益处是将形参标记为仅限位置形参将允许在未来修改形参名而不会破坏客户的代码。例如,在 statistics 模块中,形参名 dist 在未来可能被修改。这使得以下函数描述成为可能:
def quantiles(dist, /, *, n=4, method='exclusive')
...
由于在 / 左侧的形参不会被公开为可用关键字,其他形参名仍可在 **kwargs 中使用:
>>> def f(a, b, /, **kwargs):
print(a, b, kwargs)...
>>> f(10, 20, a=1, b=2, c=3) # a and b are used in two ways
10 20 {'a': 1, 'b': 2, 'c': 3}
这极大地简化了需要接受任意关键字参数的函数和方法的实现。例如,下面是 collections 模块中的代码摘录:
class Counter(dict):
def __init__(self, iterable=None, /, **kwds):
` #Note “iterable” is a possible keyword argument`
3用于已编译字节码文件的并行文件系统缓存
新增的 PYTHONPYCACHEPREFIX 设置 (也可使用 -X pycache_prefix) 可将隐式的字节码缓存配置为使用单独的并行文件系统树,而不是默认的每个源代码目录下的 pycache 子目录。
缓存的位置会在 sys.pycache_prefix 中报告 (None 表示默认位置即 pycache 子目录)。
4.调试构建使用与发布构建相同的 ABI
发布构建和调试构建现在都是 ABI 兼容的:定义 Py_DEBUG 宏不会再启用 Py_TRACE_REFS宏,它引入了唯一的 ABI 不兼容性。Py_TRACE_REFS 宏添加了 sys.getobjects () 函数和 PYTHONDUMPREFS 环境变量,它可以使用新的 ./configure –with-trace-refs 构建选项来设置。
(由 Victor Stinner 在 bpo-36465 中贡献。)
f - 字符串支持 = 用于自动记录表达式和调试文档
增加 = 说明符用于 f-string。形式为 f’{expr=}’ 的 f - 字符串将扩展表示为表达式文本,加一个等于号,再加表达式的求值结果。例如:
>>> user = 'eric_idle'
>>> member_since = date(1975, 7, 31)
>>> f'{user=} {member_since=}'
"user='eric_idle' member_since=datetime.date(1975, 7, 31)"
通常的 f - 字符串格式说明符 允许更细致地控制所要显示的表达式结果:
>>> delta = date.today() - member_since
>>> f'{user=!s} {delta.days=:,d}'
'user=eric_idle delta.days=16,075'
= 说明符将输出整个表达式,以便详细演示计算过程:
>>> print(f'{theta=} {cos(radians(theta))=:.3f}')
theta=30 cos(radians(theta))=0.866
PEP 587: Python 初始化配置
PEP 587 增加了一个新的 C API 用来配置 Python 初始化,提供对整个配置过程的更细致控制以及更好的错误报告。
Vectorcall: 用于 CPython 的快速调用协议
添加 “vectorcall” 协议到 Python/C API。它的目标是对已被应用于许多类的现有优化进行正式化。任何实现可调用对象的扩展类型均可使用此协议。
此特性目前为暂定状态,计划在 Python 3.9 将其完全公开。
具有外部数据缓冲区的 pickle 协议 5 当使用 pickle 在 Python 进程间传输大量数据以充分发挥多核或多机处理的优势时,非常重要一点是通过减少内存拷贝来优化传输效率,并可能应用一些定制技巧例如针对特定数据的压缩。 pickle 协议 5 引入了对于外部缓冲区的支持,这样 PEP 3118 兼容的数据可以与主 pickle 流分开进行传输,这是由通信层来确定的。
连续三年夺冠,Python为什么这么受欢迎? Python 已经成为最受欢迎的编程语言。 在2019年度 IEEE Spectrum 编程语言排行榜中,Python 不负众望,稳居榜首,而且连续三年夺冠。
参考文献
Python 官网宣布,正式发布 Python 3.8.0!
https://mp.weixin.qq.com/s/DH85CRyAR9OS0MZFkTL6sQ
由 Antoine Pitrou 在 bpo-36785 中贡献
https://www.python.org/dev/peps/pep-0574
Python 3.8.0文档:
https://docs.python.org/zh-cn/3.8/whatsnew/3.8.html
python str与bytes之间的转换
https://blog.csdn.net/yatere/article/details/6606316