python学习笔记,可能存在错误,大佬多指点
-
print()打印输出
多个参数输出用逗号隔开,end='' 不换行输出
# 输出文字
print('Python')
-
input() 键盘接收指令
# 键盘接收指令
tip = input('请输入文字')
-
注释
# 单行注释
"""多行注释-多行文本"""
'''多行注释'''
-
编码规范
- 尽量不要使用类似java中的结束符
- 每个import尽量只导入一个模块
- 文字太长可以使用 \ 来换行 推荐使用()来进行换行
- 语句换行 () 超出80字需换行 导入模块语句不可用,注释中的url过长不可用
-
保留字与标识符
保留字
and,as,assert,break,class,,continue,def,del,elif,else,except,finally,for,from,False,global,
if,import,in,is,lambda,nonlocal,not,None,or,pass,raise,return,try,True,while,with,yield
标识符
_标识符 保护变量
__标识符 类的私有成员
__标识符__ 专用标识 __init__() 构造函数
-
变量
python中不需要声明变量类型
# 字符串类型
str = 'Pyhton String'
# 整型
age = 18
# 浮点型
htight = 1.70
python中变量是动态类型,可以变化
nickname = '张三'
print(nickname) # 结果为张三
nickname = '李四'
print(nickname) # 结果为李四
python中允许多个变量指向同一个值,内存中只存在同一个值
no = num = 2048
print(no, num)
# 查看变量内存地址
print(id(no))
print(id(num))
常量,值不可变,python中常量没有关键字,命名为大写便是常量,但是赋值后还会被改变,所以不常用
# 常量
SFZ = 1122233
查看变量类型-使用type函数
str = '字符串'
print(type(str))
-
数据类型
数据类型:整数、浮点、字符串、布尔
1. 数字类型
整数、浮点、复数、十进制、八进制、二进制、十六进制
整数类型不需要管位数,当超出固定位数后,python会自动转为更高精度的类型
2. 字符串类型
python中字符串是不可变序列
常用转译字符
\ 续行符
\n 换行符
\0 空
\t 制表符
\" 双引号
\' 单引号
\\ 单反斜杠 转译反斜杠
\f 换页
\0dd 八进制数,dd代表字符,如\012 代表换行
\xhh 十六进制数,hh代表字符。如\x0a 代表换行
r 原始字符串-原样输出,不进行转译,例如字符串中的\会被认定为普通字符
"""xxx""" 三引号字符串可以保持原有格式进行输出
3. 布尔类型
True False
true false 不是布尔值
bool值转换数值 True = 1 False = 0
假值:False,None,0,0.0,虚数0,空序列(空字符串、空元组、空列表、空字典),对象的__bool__方法返回False,__len__方法返回0
真值:除上述假值外其他返回值都为真值
-
数据类型转换
int() 整型
float() 浮点型
str() 字符串
hex() 十六进制
cot() 八进制
-
运算符
算数运算符、赋值运算符、比较运算符、逻辑运算符、位运算符
1. 算数运算符
+ 、- 、* 、/ 、%
除法 / 结果为浮点数
除法 // 结果为整数
** 幂运算
2. 赋值运算符
+= 、 -= 、 *= 、 /= 、 %=
3. 比较-关系运算符
== 、 != 、> 、< 、 >= 、 <=
4. 逻辑运算符
and 逻辑与 一假则假
or 逻辑或 一真则真
not 逻辑非 真变假 假变真
5. 位运算符
& 位与 有0即为0
| 位或 有1即为1
~ 位取反 0变1 1变0
^ 位异或 全是0或全是1 才是0
<< 左移位 左边最高位丢弃,右边空位用0补充,等于乘以2的n次幂
>> 右移位 右边最高位丢弃,左边最高位如果是0,则填充0,如果是1,则填充1,等于除以2的n次幂
6. 运算符优先级
优先级高的运算先执行,优先级低的运算后执行,同一优先级的操作按从左到右的顺序执行
从上到下依次从高到低
1. 单目运算符 ~ + -
2. 算数运算符 * / % //
+ -
3. 位移运算符 &
^
|
4. 比较运算符 < <= > >= != ==
可以使用 () 改变优先级
-
索引-序列
在java中为数组
python中为列表、元组、字典、集合、字符串
序列:一块用于存放多个值的连续空间,并按一定顺序排列,可以通过索引取值
索引就是编号 0开始
切片、序列相加、乘法 对字典不支持
所以可以是负数,从后往前,从-1开始
1. 切片
语法:sname[start : end : step]
start: 起始位置、
end: 结束位置
step: 步长
start可以省略,冒号必须保留,end也可以省略,省略后默认值为1
切片不包含结束索引
sname = ['乔丹', '拉塞尔', '贾巴尔', '李宁', '科比', '詹姆斯', '张伯伦', '邓肯', '伯德', '阿尼尔']
# 指定开始及结束位置 输出结果['拉塞尔', '贾巴尔', '李宁', '科比']
print(sname[1:5])
# 指定从0开始到第五个 步长为2 输出结果['乔丹', '贾巴尔', '科比']
print(sname[0:5:2])
# 输出结果为0-4 5个 输出结果['乔丹', '拉塞尔', '贾巴尔', '李宁', '科比']
print(sname[:5])
# 输出结果为整个列表
print(sname[:])
# 输出结果为从第二个至结束
print(sname[2:])
2. 序列相加
使用+号,把两个相同类型的序列合并成为一个,如果有重复的不会被剔除
只能是相同类型相加。列表 + 列表 元组 + 元组 字符串 + 字符串
sname = ['乔丹', '拉塞尔', '贾巴尔', '李宁', '川建国']
cname = ['马斯克', '川建国', '贾巴尔', '李宁']
aname = sname + cname
print(aname)
3. 乘法
python中支持 序列 * 乘数 = 重复n次的序列
并非把元素内容相乘
phone = ['HuaWei Meta 60', 'Vivo x32', 'iphone16']
print(phone * 3)
4. 检查元素是否为序列成员
sname = ['乔丹', '拉塞尔', '贾巴尔', '李宁', '科比', '詹姆斯', '张伯伦', '邓肯', '伯德', '阿尼尔']
# 检查元素是否在列表中
print('乔丹' not in sname)
5. 计算序列的长度、最大值、最小值
常用方法
len() 列表长度
max() 最大值
min() 最小值
list() 将序列转换成列表
str() 序列转换成字符串
sum() 计算序列和
sorted() 元素排序
reversed() 反转序列元素
enumerate() 序列组合为索引序列
num = [10, 58, 65, 35, 33]
print('列表的长度', len(num))
str = '我是个字符串'
print(len(str))
-
列表
列表是内置的可变序列
1. 列表的创建和删除
赋值运算符直接创建, 使用 []
# 数值类型列表
num = [15, 22, 35, 105]
# 字符类型列表
verse = ['春眠不觉晓', 'python不得了', '夜来爬数据', '牢饭吃多少']
#
python = ['优雅', "简答", """明确"""]
# 多类型列表
untitle = ['pyhton', 28, '人生苦短', ['云计算', '视觉', '爬虫']]
创建空列表
# 创建空列表
unlist = []
创建数值列表
# 创建数值列表 从2生成到21 步长为2
num_list = list(range(2, 21, 2))
字符串转换成列表
str = 'hello world'
str_list = list(str)
print(str_list)
删除列表- del()
str = 'hello world'
str_list = list(str)
print(str_list)
# 删除列表
del(str_list)
2. 访问列表元素
通过索引或者切片访问
python = ['python', 'java', 28, ['爬虫', 18, '人工智能']]
# 使用print()
print(python)
# 通过索引
print(python[2])
# 通过切片
print(pyhton[:2])
3. 遍历列表
1. 使用for循环
2. 使用for循环和enumerate()
3. 使用for循环和range()
enumerate() 序列组合为索引序列
verse = ['春眠不觉晓', 'python不得了', '夜来爬数据', '牢饭吃多少']
# 使用for循环
for item in verse:
print(item)
# 使用for循环和enumerate()
for index, item in enumerate(verse):
print(index + 1, item)
# 使用for循环和range()
for i in range(0, len(verse)):
print(verse[i])
4. 添加、修改、删除列表元素
1. 添加元素
append() 添加新元素
insert(self, item) 指定位置插入元素 没有append执行效率高
extend() 一个列表的元素全部添加到另一个列表中
verse = ['春眠不觉晓', 'python不得了', '夜来爬数据', '牢饭吃多少']
# append 添加新元素
verse.append('哈哈')
# insert() 指定位置插入新元素
verse.insert(0, '第一个元素')
# extend() 一个列表中的元素全部添加到另一个列表中
old_list = ['乔丹', '贾巴尔', '奥拉朱旺', '巴克利', '姚明']
new_list = ['基德', '纳什', '希尔']
old_list.extend(new_list)
2. 修改元素
list[index] = 值
verse = ['春眠不觉晓', 'python不得了', '夜来爬数据', '牢饭吃多少']
# 修改元素
verse[-1] = '一行白鹭上青天'
3. 删除元素
del list[index]
remove()
verse = ['春眠不觉晓', 'python不得了', '夜来爬数据', '牢饭吃多少']
# del[index] 删除元素
del verse[-1]
# remove() TODO 如果没有该数据则会抛出异常
verse.remove('夜来爬数据')
5. 对列表进行统计计算
count() 获取指定元素痴线的次数
list.count(obj)
index() 获取指定元素首次出现的下标
list.index(obj)
sum() 统计数值列表的和
sum(list, start) start为可选参数,与list所有的值再次相加
nba = ['乔丹', '贾巴尔', '奥拉朱旺', '巴克利', '姚明', '乔丹']
# 获取指定元素出现的位置
num = nba.count('乔丹')
# 获取指定元素首次出现的下标
index = nba.index('贾巴尔')
num_list = [15, 20, 30, 50, 105]
# 统计数值列表的和
num_sum = sum(num_list)
# list所有的值相加后加100
num_sum_add = sum(num_list, 100)
6. 对列表进行排序
1. sort() 列表对象,排序后原列表中的元素顺序不变
list.sort(key=None, reverse=False)
key = str.lower 不区分大小写
reverse = False 升序 = True 降序
sort() 对中文排序效果不好 - 具体请自行尝试
2. sorted() 内置对象
sorted(list, key, reverse)
num_list = [15, 20, 35, 33, 55, 33]
# 升序 - 原列表顺序不变
num_list.sort()
name_list = ['cat', 'Tom', 'Angela', 'pet']
# 对英文进行排序 升序 不区分大小写
name_list(key=str.lower())
# lambda
name_list(key=lambda x: x.lower())
# sorted 排序
list_px = sorted(name_list, key=str.lower, reverse=True) # 降序
7. 列表推导式
列表推导式可以快速生成一个列表
import random
# 原始生成方式
list1 = []
for i in range(10):
list1.append(random.randint(10, 100))
# 使用列表推导式
list2 = [random.randint(10, 100) for i in range(10)]
# 生成1-10中偶数平方的列表 后面循环完成后前面才进行计算
list3 = [i*i for i in range(2, 10, 2)]
price = [1000, 500, 800, 888, 666]
# 生成满足条件的 添加判断
sales = [i for i in price if i > 800]
-
元组
元组 tuple (元素1, 元素2, ...)
元组类似列表,可以放置各种类型的数据
元素使不可变的
1. 创建和删除元组
可以通过赋值运算符创建元素
注意创建单个个数值元组时要加逗号 a = (15,)
# 元组的创建
number = (1, 2, 3, 4, 5, 6, 7, 8, 9)
mx = ('林俊杰', '房东的猫', '薛之谦')
# 混合类型元组
untitle = (15, '毛不易', 'pyhton', ['爬虫', '运动控制'])
# 以下并非元组
verse = ('我要学python')
# 创建单元素元组后面要加逗号
onese = ('我要学视觉',)
# 创建空元组
untuple = ()
# 创建数值元组
tuple1 = tuple(range(2, 21, 2))
删除元组使用del
tuple2 = tuple(range(2, 21, 2))
# 删除元组
del tuple2
2. 访问元组元素
1. print()
2. 索引
3. 切片
4. for遍历
untitle = (15, '人生苦短', 'python', ['java', 'web'], ('爬虫', '云计算'))
# print()
print(untitle)
# 索引
print(untitle[4])
# 切片 不包含结束索引
print(untitle[1:3])
# for循环遍历
for item in untitle:
print(item)
3. 修改元组元素
不可以直接修改-会报错
只能重新赋值
元组可以和元组进行组合,通过加号连接,不可连接其他类型
coffee_name = ('蓝山', '卡布奇诺', '曼特宁', '摩卡', '麝香猫', '哥伦比亚')
# 错误演示 直接修改
# coffee_name[4] = '拿铁'
# 重新赋值
coffee_name = ('蓝山', '卡布奇诺', '曼特宁', '摩卡', '拿铁', '哥伦比亚')
# 元组进行连接组合
new_coffee_name = ('麝香猫', '维也纳')
all_coffee_nane = coffee_name + new_coffee_name
# 错误演示
# print('合并后' + all_coffee_name)
4. 元组推导式
快速生成元组
生成器生成内容访问后立即销毁
import random
# 生成包含10个随机数的元组
ran_num = (random.randint(1, 100) for i in range(10))
# 销毁演示
for item in ran_num:
print(item, end = ' ')
# 此处访问结果为 () 空元组 上方for使用后立即销毁 所以此处为空元组
print(tuple(ran_num))
-
元组和列表的区别
元组和列表的区别
1. 元组和列表都属于序列,都可以按照一定顺序存放元素,类型不受限制
2. 列表元素可变,元组不可变,只能替换
3. 列表支持切片操作,元组只能切片访问
4. 列表访问速度慢,元祖访问速度快
5. 列表不能作为字典的键,元组可以作为字典的键
-
字符串
字符串定义的方式
1. 'xxx'
2. "xxx"
3. """xxx"""
1. 2. 必须在同一行,3. 可以换行
1. 拼接字符串
使用 + 拼接
h = 'hello'
w = 'world'
print(h + w)
str1 = '微信步数:'
num = 17777
print(str1 + str(num))
2. 计算字符串的长度
1. 英文字母 数字 小数点 下划线 空格 占一个字节
2. 中文汉字2~4个字节,UTF-8占3个字节,GBK编码中文占两个字节
len() 计算字符串长度
len(string) 中英文都按一个计算
encode() 设置编码格式 不填写默认utf-8
str = 'hello world'
# 获取字符串长度
print(len(str))
# 获取utf-8长度
print(len(str.encode()))
# 获取GBK长度
print(len(str.encode('GBK')))
3. 截取字符串
字符串也属于序列
1. 通过索引获取-下标
如果索引超长会报错 - IndexError
2. 使用切片方式进行截取
如果切片起始值大于数据长度则会返回空
str = '人生苦短,何必学python'
# 通过下标方式获取
print(str[1])
# 通过切片方式截取
print(str[1:3])
4. 分割字符串
split() 分割字符串
str.split(sep, maxsplit)
sep: 分隔符,空格、换行\n、制表符\t,都可以作为分隔符
maxsplit: 分隔次数
不指定任何参数则默认用空格分隔
join() 合并字符串
str. join(iterable)
iterable: 可迭代对象,字符,可以是列表,可以是元组
str_user = '@林俊杰 @房东的猫 @薛之谦'
# 不指定任何参数-默认用空格分隔
print(str.split())
# 指定分隔次数
print(str.split('', 3))
# 合并字符串
list_user = ['薛之谦', '林俊杰', '川建国']
str = '@'.join(list_user)
str_a = '@' + str
print(str_a)
5. 检索字符串
in : 判断字符是否存在
count() 检索出现次数
str.count(sub[,start[,end]])
find() 检索字符在字符串中首次出现的位置
str.find(sun[,start[,end]])
rfind() 从右往左查找
index() 检索是否存在字符串
str.index(sub[,start[,end]])
rindex() 从右往左查找
startswith() 检索是否以此字符串开头
str.startswith(sub[,start[,end]])
endswith() 检索是否以此字符串结尾
str_star = '@林俊杰 @房东的猫 @薛之谦 @毛不易'
# 检索出现次数
print(str_star.count('@', 5, 10))
# 检索首次出现位置 返回索引 没有找到返回-1
print(str_star.find('@'))
# 检索字符串是否存在
print('@' in str_star)
# rfind 从右往左查找
print(str_star.rfind('@'))
# 检索是否包含字符串 存在返回下标 不存在抛出异常
print(str_star.index('@'))
# rindex 从右往左查找
print(str_star.rindex('@'))
# startswith 检索是否以字符串开头
print(str_star.startswith('@'))
# endswith 检索是否已字符串结尾
print(str_star.endswith('@'))
6. 字母的大小写转换
lower() 转小写
upper() 转大写
str = 'WWW.mddn.net'
# 转小写
print(str.lower())
# 转大写
print(str.upper())
7. 去除空格和特殊字符
特殊字符: \t \r \n
strip() 去除字符串左右两端空格和特殊字符
str.strip([chars]) 参数不指定默认去除空格
lstrip() 去除左侧空格和特殊字符
rstrip() 去除右侧空格和特殊字符
str = ' https://www.mddn.net \t \n \r'
# 去除空格
print(str.strip())
str1 = '*https://www.mddn.net \t \n \r'
# 去除*
print(str1.strip('*'))
str2 = '*https://www.mddn.net \t \n \r*'
# 去除左侧*
print(str2.lstrip('*'))
# 去除右侧*
print(str2.rstrip('*'))
8. 格式化字符串
1. %
'%[-][+][0][m][.n]格式化字符串'%exp
[-] 左对齐 正数前面没符号,负数前面加负号
[+] 右对齐 正数前面加正号,负数前面加负号
[0] 右对齐 正数前面没符号,负数前面加负号,用0填充空白。和[m]一起使用
[m] 数值所占宽度 和[0] 一起使用 不够m所指定位数补0
[.n] 小数点后保留位数 n = xxx数字
以上为可选参数
必选参数:
s: 字符串
d: 十进制
f: 浮点数
exp: 要转换的项,多个需要使用元组
todo 两边百分号不可缺少
2. format()
str.format([args])
{[index][:[[fill]align][sign][#][width][.precision][type]]}
[index] 可选参数 在参数对象中索引的位置,从0开始,省略按照值的先后顺序自动分配
[fill] 指定空白处填充字符
align 对齐方式,
< 内容左对齐
> 内容右对齐
= 内容右对齐,符号放置最右侧,只对数字类型有效,如果值为向上尖括号,内容居中,需要和width一起使用
[sign] 指定有无符号数
+ 正数加正号,负数加符号
- 正数不变,负数加负号
值为空格 正数加空格,负数加负号
[#] 用于指定进制前缀
0b 二进制
00 八进制
0x 十进制
[windth] 指定宽度
[.precision] 指定保留的小数位数
[type] 要格式化的字类型
s 字符串
d 十进制数
f 浮点数
index 要么全部指定 要么全部不指定
import math
# %9d 表示9位10进制数 %s 表示字符串
temp = '编号:%9d \t公司名称:%s \t 官网:https://www.%s.com'
# 数据
item = (7, '百度', 'baidu')
# 替换数据
print(temp % item)
# format
temp2 = '编号:{0>9s} \t 公司名称:{:s} \t 官网:https://www.{:s}.com'
context = temp2.format('7', '百度', 'baidu')
print(context)
# 以货币形式展示
print('货币:¥{:,.2f}元'.format(1251+3950))
# 科学技术法
print('{0:.1f}用科学技术法表示:{0:E}'.format(12000.1))
# π取5位小数
print('π取五位小数:{:.5f}'.format(math.pi))
# 十六进制显示
print('{0:d}的十六进制是:{0:#x}'.format(100))
# 百分比显示
print('天才是由{:.0%}的灵感,加上{:.0%}的汗水'.format(0.01,0.99))
-
正则表达式
1. 正则表达式基础
一种用来匹配字符串的规则,包含行定位符,元字符,限定符,字符类,排除字符,选择字符,转译字符,分组
行定位符 定位开始和结束的 ^ 表示开始 $ 表示结束
元字符 表达特殊意义的专用字符
^ 开始
$ 结束
. 匹配出换行符以外的任意字节
\w 匹配字母、数字、下划线或汉字
\W 匹配字母、数字、下划线或汉字以外的字符
\s 匹配任意空白字符
\b 匹配单词的开始或结束
\d 匹配数字
限定符 限定数量
? 匹配前面的字符零次或一次
+ 匹配前面的字符一次或多次
* 匹配前面的字符零次或多次
{n} 匹配前面的字符n次
{n,} 匹配前面的字符最少n次
{n,m} 匹配前面的字符最少n次,最多m次
字符类 定义一个字符集合,匹配当中的字符 []表示
排除字符类 匹配不符合字符集中的字符 ^ 表示
选择字符 或 | 表示
转译字符 \ 表示
分组 ()表示
2. 匹配字符串
正则表达式需要引入的模块 re
1. match() 从字符串开始位置进行匹配,其实位置匹配成功返回m对象,否则返回None
re.match(pattern, string, [flags])
pattern 模式 - 正则表达式
string 要匹配的字符串
[flags] 标志位
re.i 不区分字母大小写
re.A 让\w不匹配汉字
2. search() 从整个字符串搜索第一个匹配的值
re.search(pattern, string, [flags])
3. findall() 搜索所有符合条件的字符串,返回列表
re.findall(pattern, string, [flags])
import re
pattern = r'md_\w'
str = 'MD_SHOP md_shop'
match = re.match(pattern, str, re.I)
print(match)
print('起始位置', match.start())
print('结束位置', match.end())
print('匹配数据', match.group())
# 验证输入手机号是否为中国移动
pattern1 = r'(13[4-9]\d{8})|(15[01289]\d{8})$'
phone = '13134222222'
match1 = re.match(pattern1, phone)
if match1 == None:
print('不是有效的手机号', phone)
else:
print('是有效的手机号码', phone)
# search() 从整个字符串搜索第一个匹配的值
pattern2 = r'md_\w' # 模式字符串
str2 = '项目MD_SHOP md_shop'
search2 = re.search(pattern, str, re.I)
print(search2)
# 验证是否出现危险字符
pattern3 = r'(黑客)|(抓包)|(监听)|(Trojan)'
about = '我是一名程序员,我喜欢看黑客方面的图书,想研究一下Trojan。'
search3 = re.search(pattern3, about)
if search3 == None:
print(about, '@ 安全')
else:
print(about, '@ 危险')
# findall
pattern = r'md_\w' # 模式字符串
str = '项目名称MD_SHOP md_shop'
finall = re.findall(pattern, str, re.I)
print(finall)
3. 替换字符串
sub()
re.sub(pattern, replacement, string ,count, flags = re.IGNORECASE)
pattern 匹配模式-正则表达式
replacemet 要替换的字符串
string 原始字符串
count 匹配后替换最大次数 默认0
flags 匹配方式
re.i 不区分字母大小写
re.A 让\w不匹配汉字
import re
# 替换危险字符
pattern3 = r'(黑客)|(抓包)|(监听)|(Trojan)'
about = '我是一名程序员,我喜欢看黑客方面的图书,想研究一下Trojan。'
sub = re.sub(pattern3, "xxx", about)
print('替换后:', sub)
4. 分割字符串
split() 返回列表
re.split(pattern, string, [maxsplit], flags)
pattern 匹配模式-正则表达式
string 要匹配的字符串
maxsplit 最大拆分次数,可选参数,不指定全部拆分
flags 匹配方式 re.i re.A
import re
pattern = r'[?|&]'
url = 'http://www.mddn.com/login.jsp?username="md"&password="mddn"'
result = re.split(pattern, url)
print(result)
-
流程控制语句
1. 流程控制语句
1. 选择语句 if elif else
2. 循环语句 while for
3. 跳转语句 break continiu
4. pass语句
2. 选择语句
if语句 python中没有switch语句
1. if语句
print('今有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二,问几何?\n')
num = int(input('请输入您认为满足条件的数'))
if num % 3 == 2 and num % 5 == 3 or num % 3 == 2:
print(num, "符合条件")
a = 10
b = 5
# 可以使用
if a > b : print(a)
3. if..esle
print('今有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二,问几何?\n')
num = int(input('请输入您认为满足条件的数:'))
if num % 3 == 2 and num % 5 == 3 or num % 3 == 2:
print(num, "符合条件")
else:
print(num, "不符合条件")
3. if..esif...else语句
num = int(input('请输入送花朵数'))
if num == 1:
print("送一朵花")
elif num == 3:
print("送三朵花")
elif num == 10:
print("送十朵")
else:
print("送其他朵")
4. if嵌套
print('为了安全不要喝酒')
proof = int(input('输入酒精含量'))
if proof < 20:
print('不够成酒驾')
else:
if 80 > proof >= 20:
print("酒驾")
else:
print("醉驾")
5. 使用and连接条件
print("考驾照啦")
age = int(input("请输入年龄:"))
if age >= 18 and age <= 70:
print('符合条件')
else:
print('不符合条件')
# 链式比较
if 18 <= age <= 70:
print('符合条件')
else:
print('不符合条件')
6. 使用or连接条件
sales = int(input('请输入商品日销量'))
# 销量好的和销量差的都需要重点关注
if sales > 100 or sales < 10:
print('重点关注')
7. 使用not 关键字
data = None
if data is not None:
print('有数据')
else:
print('无数据')
3. 循环语句
1. for循环
for 迭代变量 in 对象:
range() 生成一系列连续整数
range(start, end, step)
start: 起始值,非必填,默认0
end: 结束值,必填,填写后不包含该值,结束值-1,
step: 步长,非必填,默认1
xrange() python2中的函数,跟range()一样
# 计算1+2+3+....+100
result = 0
for i in range(101):
result += i
print('计算结果', result)
2. while循环
while 条件表达式:
a = 0
while a < 10:
a += 1
print('循环', a)
3. 嵌套循环
# 打印99乘法表
for i in range(1, 10): # 行数
for j in range(1, i+1): # 输出行数中的列
print(str(j) + "x" + str(i) + "=" +str(j*i) +'\t', end='')
print("")
4. break语句
break 跳出循环
# 三三剩二,五五剩三,七七剩二
for num in range(100):
print(num)
if num % 3 == 2 and num % 5 == 3 and num % 7 == 2:
print("这个数是", num)
break
5. continue语句
continue 跳出一次循环
# 假设拍桌子99次
total = 99
for num in range(1, 100):
if num % 7 == 0:
continue
else:
string = str(num)
if string.endswith('7'):
continue
total -= 1
print(total, '次')
-
字典
字典 dicttionary,java中的map
key value的形式,列表不能作为字典的key,元组可以
1. 创建字典
dict = {'key':'value','key':'value','key':'value'......}
zip(list1, list2) 将列表转换为字典,list1为key, list2为value, 返回zip对象
dict(zip) zip对象转换为字典对象
fromkeys() 创建值为空的字典
# 创建字典
word = {'che': '车', 'chen': '尘', 'cheng': '称', 'chi': '吃'}
print(word)
# 将列表转换为字典
key = ['che', 'chen', 'cheng', 'chi']
value = ['车', '尘', '称', '吃']
z = zip(key, value)
print(z)
# zip对象转换为字典对象
w = dict(zip(key, value))
print(w)
# 元组转换字典
name = ('绮梦', '冷一', '香凝', '黛蓝')
sign = ['水瓶座', '射手座', '双鱼座', '双子座']
c = {name: sign}
print(c)
# 创建空字典
dd = {}
print(dd)
dc = dict()
print(dc)
# 通过dict键值对创建字典
da = dict(绮梦='水瓶座', 冷一='射手座')
print(da)
# 通过dict->fromkeys() 创建值为空的字典
name_keys = ['绮梦', '冷一', '香凝', '黛蓝']
ks = dict.fromkeys(name_keys)
print(ks)
2. 删除字典
1. 删除字典
del 字典
2. 只删除字典元素 - 清空字典
字典.clear()
3. 访问字典
1. 通过下标 - 下标指的是key并非索引
2. 字典.get(key,[default]) 不指定返回None
name = ['绮梦', '冷一', '香凝', '黛蓝']
sign = ['水瓶座', '射手座', '双鱼座', '双子座']
d = dict(zip(name, sign))
# 通过下标
print(d['绮'])
# get()
print(d.get('冷一'))
# 指定默认值
print(d.get('冷', '查无此人'))
4. 遍历字典
items() 返回可比案例的元组列表
keys() 返回健列表
values() 返回值列表
sign = {'绮梦': '水瓶座', '冷一': '射手座', '香凝': '双鱼座', '黛蓝': '双子座'}
# 可遍历的元组列表
print(sign.items())
for key, value in sign.items():
print(key, value)
# 获取健列表
k = sign.keys()
print(k)
# 获取值列表
v = sign.values()
print(v)
5. 添加、修改、删除元素
dict[key] = value 添加修改元素
键必须唯一
del dict[key] 删除元素 如不存在会抛出异常
sign = {'绮梦': '水瓶座', '冷一': '射手座', '香凝': '双鱼座', '黛蓝': '双子座'}
# 添加
sign['碧琪'] = '处女座'
# 修改
sign['冷一'] = '巨蟹座'
# 删除
del sign['冷一']
6. 字典推导式
{键表达式:值表达式 for}
import random
# 字典推导式
random_dict = {i: random.randint(1, 100) for i in range(1, 5)}
print(random_dict)
name = ['绮梦', '冷一', '香凝', '黛蓝']
sign = ['水瓶座', '射手座', '双鱼座', '双子座']
names = {i: j for i, j in zip(name, sign)}
-
集合
集合 set
可变集合 set 用来保存不重复的元素,最好的应用是去重,集合也用{}来表示
特点是自动去除重复数据,无序,不能通过索引来获取
set() 空集合的创建
set(list) 将列表转换为集合
不可变集合 forzenset()
1. 集合的创建
# 定义一个集合
set1 = {"水瓶座", '射手座', '双鱼座', '双子座'}
print(set1)
# 创建空集合
set2 = set()
# 将列表和集合转换为set集合 set()方法
name = ['绮梦', '冷一', '香凝', '黛蓝', '绮梦']
print('列表', name)
set4 = set(name)
print('set集合', set4)
2. 集合的添加和删除
添加
setName.add(element)
element: 字符串,数字,bool, 不能使用列表元组等可迭代对象
删除
remove() 删除集合元素
pop() 随机删除一个元素
clear() 清空集合
del 删除集合
# 添加元素
mr = set(['java', 'python', 'javascript', 'eleui'])
mr.add('php')
print(mr)
# 删除元素
mr.remove('php')
print(mr)
# 随机移除一个元素
temp = mr.pop()
print('随机移除的元素', temp)
print(mr)
# 清空集合
mr.clear()
print(mr)
# 删除集合
del mr
3. 集合的交集、并集、差集运算
& 交集
| 并集
- 差集
^ 对称差集
pyname = set(['绮梦', '冷一', '香凝', '黛蓝']) # 选择pyhon
cname = set(['冷一', '灵玉', '子轩', '圣博']) # 选择c
print('选择python', pyname)
print('选择c', cname)
# 交集运算
print('交集运算', pyname & cname) # 既选择pyhton又选择c
print('并集运算', pyname | cname) # 输出选课的所有学生名字 去除重复的
print('差集运算', pyname - cname) # 选择python但没有选择c语言的学生
-
列表、元组、字典和集合的区别
列表 、元组tuple、字典dict和集合set的区别
定义符号
列表 [] 可变 可重复 有序
元组 () 不可变 可重复 有序
字典 {key:value} 可变 可重复 无序
集合 {} 可变 不可重复 无序
-
函数
1. 函数的创建和调用
def function([paramter_list]):
'''函数注释'''
空函数可用pass关键字
# 创建函数
def filter_char(str):
'''
过滤危险字符,并将过滤后的字符
str:要过滤的字符串
无返回值
'''
pattern = r'(黑客)|(抓包)|(监听)|(Trojan)' # 模式字符串
sub = re.sub(pattern, '***', str)
print(sub)
# 创建空函数
def empty():
pass
# 函数调用
about = '我是一名程序员,我喜欢看黑客方面的图书,想研究一下Trojan。'
filter_char(about)
2. 形参和实参
形式参数和实际参数
值传递: 不可变参数
引用传递: 可变参数
# 定义函数=有参
def demo(obj):
print('原值', obj)
obj += obj
# 值传递
mot = '唯有python'
print('函数调用前', mot)
demo(mot)
print('函数调用后', mot) # 值并未有任何改变
# 引用传递
list = ['绮梦', '冷一一', '香凝', '黛蓝']
print('函数调用前', list)
demo(list)
print('函数调用后', list)
3. 位置参数
必须按照定义时的个数和顺序进行参数传递,也成为必备参数
def bmi(person, height, weight):
'''
根据身高体重计算bmi指数
:param person: 姓名
:param height: 身高
:param weight: 体重
:return:
'''
print(person+'您的身高为:' + str(height) + '米' + '体重为' + str(weight))
bmi = weight / (height ** 2)
print(person, '您的bmi指数为:', bmi)
if bmi < 18.5:
print(person, '体重过轻')
elif 18.5 >= bmi < 24.9:
print(person, '正常范围')
elif 24.9 >= bmi < 29.9:
print(person, '体重过重')
elif 29.9 >= bmi:
print(person, '体重肥胖')
bmi('路人甲', 1.83, 60)
4. 关键字参数
使用形式参数的名字来确定要输入的参数值
def bmi(person, height, weight):
'''
根据身高体重计算bmi指数
:param person: 姓名
:param height: 身高
:param weight: 体重
:return:
'''
print(person+'您的身高为:' + str(height) + '米' + '体重为' + str(weight))
bmi = weight / (height ** 2)
print(person, '您的bmi指数为:', bmi)
if bmi < 18.5:
print(person, '体重过轻')
elif 18.5 >= bmi < 24.9:
print(person, '正常范围')
elif 24.9 >= bmi < 29.9:
print(person, '体重过重')
elif 29.9 >= bmi:
print(person, '体重肥胖')
bmi(person='路人乙', weight=60, height=1.5)
5. 为参数设置默认值
如果要为参数设置默认值,此参数必须要放到最后面
查看方法默认值
方法名.__defaults__
定义函数的参数时,为形式参数设置默认值不要指向不可变对象
def bmi(height, weight, person='路人已'):
'''
根据身高体重计算bmi指数
:param person: 姓名
:param height: 身高
:param weight: 体重
:return:
'''
print(person+'您的身高为:' + str(height) + '米' + '体重为' + str(weight))
bmi = weight / (height ** 2)
print(person, '您的bmi指数为:', bmi)
if bmi < 18.5:
print(person, '体重过轻')
elif 18.5 >= bmi < 24.9:
print(person, '正常范围')
elif 24.9 >= bmi < 29.9:
print(person, '体重过重')
elif 29.9 >= bmi:
print(person, '体重肥胖')
bmi(1.5, 60)
# 查看方法默认值
print('查看方法默认值', bmi.__defaults__)
6. 可变参数
个数不固定的参数 0-n个参数
*parameter 可以接收任意多个实际参数,并放到一个元组中
**paramter 接收任意多个类似关键字参数一样显式赋值的实际参数,并将其放到一个字典中
实际调用时,传递参数使用*param, * 为解包,调用时对于可迭代对象进行解包,使其中的元素能作为独立的 参数传递给参数
# *parameter
def coffee(*coffee_name): # 输出咖啡名称
print('\n我喜欢的咖啡有:')
for name in coffee_name:
print(name)
# 调用
coffee('摩卡', '拿铁', '卡布奇诺')
list1 = ['摩卡', '拿铁', '卡布奇诺']
# *list1 *为解包 调用时用于对可迭代对象进行解包 是其中的元素能作为独立的参数传递给函数
coffee(*list1)
# 可变参数
def bmi_a(*person):
'''
升级可变参数 姓名 身高m 体重kg
:param person:
:return: 可变参数 姓名 身高m 体重kg
'''
for list_person in person:
for item in list_person:
person = item[0]
height = item[1]
weight = item[2]
print(person + '您的身高为:' + str(height) + '米' + '体重为' + str(weight))
bmi = weight / (height ** 2)
print(person, '您的bmi指数为:', bmi)
if bmi < 18.5:
print(person, '体重过轻')
elif 18.5 >= bmi < 24.9:
print(person, '正常范围')
elif 24.9 >= bmi < 29.9:
print(person, '体重过重')
elif 29.9 >= bmi:
print(person, '体重肥胖')
list_w = [['绮梦', 1.70, 60], ['灵玉', 1.80, 65], ['张三', 1.40, 80]]
list_m = [['李四', 1.50, 60], ['王五', 1.10, 100]]
bmi_a(list_w, list_m)
# **parameter
def sign(**sign):
print()
for key, value in sign.items():
print(key + '的星座是 ' + value)
sign(绮梦='水瓶座', 冷一='射手座')
sign(香凝='双鱼座', 张三='巨蟹座', 王五='天蝎座')
sign_dict = {'绮梦': '水瓶座', '冷一': '射手座','香凝': '双鱼座', '张三': '巨蟹座', '王五': '天蝎座'}
sign(**sign_dict)
7. 返回值
retuen 返回值,一个或者多个,多个值就是一个元组
def fun_checkout(money):
'''
计算商品合计金额并进行折扣处理
:param money: 商品金额列表
:return: 商品合计金额和折后金额
'''
money_old = sum(money) # 合计金额
money_new = money_old
if 500 <= money_old < 1000: # 享受9折优惠
money_new = '{:2f}'.format(money_old * 0.9)
elif 1000 <= money_old <= 2000:
money_new = '{:2f}'.format(money_old * 0.8)
elif 2000 <= money_old <= 3000:
money_new = '{:2f}'.format(money_old * 0.7)
elif money_old <= 3000:
money_new = '{:2f}'.format(money_old * 0.7)
return money_old, money_new # 返回总金额和折扣后金额
print('\n开始计算.......、\n')
list_money = []
while True:
input_money = float(input('请输入商品金额,输入0代表结束'))
if int(input_money) == 0:
break
else:
list_money.append(input_money)
money = fun_checkout(list_money)
print('合计金额', money[0], '应付金额', money[1])
8. 变量作用域
global 修饰局部变量改变为全局变量
全局变量不能在函数体内改变全局变量的值,如果改变的话会被重新定义为局部变量,改变的是局部变量的值
# 局部变量
def fun_demo():
message = '局部变量'
print(message)
msg = '全局变量'
def fun_demo1():
global msg # 定义全局变量
msg = '函数体内改变'
print('全局变量-函数体内', msg)
fun_demo1()
print('全局变量-函数体外', msg)
9. 匿名函数
只能使用一次,使用lambda表达式
lambda
result = lambda [arg1 [, arg2, ..., argn]] : expression(表达式)
expression 中不能出现for while等
import math
# 正常方法
def circlearea(r): # 计算园的面积
return math.pi * (r**2)
r = 10
area = circlearea(r)
print('半径为', r, '的圆的面积为', area)
# lambda
r = 10 # 半径
result = lambda r : math.pi * (r**2)
print(result)
# 按照打折折扣排序
book_info = [('不一样的卡梅拉', 22.50, 120), ('零基础学安卓', 65.10, 89.80),
('摆渡人', 23.40, 36.00), ('福尔摩斯', 22.50, 128)] # 商品列表
print('爬取到的商品信息\n', book_info, '\n')
# 排序
book_info.sort(key=lambda x: (x[1], x[1]/x[2])) # 指定排序规则
print('排序后的商品信息\n', book_info, '\n')
-
常用内置函数
help() 查看函数模块的用途
id() 查看对象内存地址
oct() 十进制转八进制
round() 四舍五入
遵循靠近0的元组 0.5 0位舍入结果是0
python官方api文档
安装路径/doc/.chm
-
面向对象
对象和类
封装 继承 多态
1. 定义类
class ClassName():
'''类的帮助信息'''
class Geeses():
'''大雁类'''
pass
2. 创建类的实例
创建对象
ClassName(parameterList)
parameterList 可选参数,如果创建类时没有创建init()或者init()内只有self一个参数的话可以省略,否则就是init方法内的参数
class Geese:
'''大雁类'''
pass
# 创建类实例
wildGeese = Geese()
print(wildGeese)
3. init方法
init() 相当于java中的构造方法
初始化的作用
python和java不同,java中可以有多个构造方法,python中只能有一个
self参数必须作为第一个,有其他参数在后面进行添加,self指向实例本身的引用,通过他可以访问类中的对象和属性
class Geesewc:
'''大雁类'''
def __init__(self): # 定义构造方法
print('我是大雁类:')
class Geesee:
'''大雁类'''
# self参数必须作为第一个 有其他参数在后面进行添加 self指向实例本身的引用 通过他可以访问类中的对象和属性
def __init__(self, beak, wing, claw): # 定义构造方法
print('我是大雁类我有以下特征:')
print(beak)
print(wing)
print(claw)
# 无参
wildGeeseWc = Geesewc()
# 有参
beak1 = '喙的基部较高,长度和头的长度几乎相等'
wing1 = '翅膀长而尖'
claw1 = '爪子是浦状的'
wildGeese = Geesee(beak1, wing1, claw1)
4. 创建类的成员并访问
实例方法 - 方法
创建实例
def functionName(self, parameterList):
block
self 必须要的参数
访问
instanceName.functionName(paramList)
类的实例名称.实例方法名称
数据成员 - 属性
类属性,定义在类中,在方法体外的属性,在所有实例之间共享值
访问:类名.属性名
实例属性,定义在类中的方法,只作用与当前实例,只能通过类的对象进行访问
访问:类对象.属性名
class Geesef:
'''大雁类'''
def __init__(self, beak, wing, claw): # 定义构造方法
print('我是大雁类我有以下特征:')
print(beak)
print(wing)
print(claw)
# 创建类实例方法
def fly(self, state='本身就会飞'): # 飞行方法
print('飞行状态:', state)
beak1 = '喙的基部较高,长度和头的长度几乎相等'
wing1 = '翅膀长而尖'
claw1 = '爪子是浦状的'
wildGeese = Geesef(beak1, wing1, claw1)
wildGeese.fly('起飞')
wildGeese.fly()
class Geesed:
neck = '脖子较长' # 类属性 脖子
wing = '振翅频率高' # 翅膀
leg = '腿'
def __init__(self): # 定义构造方法
print('我是大雁类我有以下特征:')
print(Geesed.neck)
print(Geesed.wing)
print(Geesed.leg)
geed = Geesed()
class dayansl:
def __init__(self):
self.neck = '脖子较长' # 实例属性
self.wing = '振翅频率高'
self.leg = '腿'
print('我是大雁类我有以下特征:')
print(self.neck) # 访问实例属性
print(self.wing)
print(self.leg)
dayansl = dayansl()
# 访问实例独享
print(dayansl.neck)
# 修改
dayansl.leg = '我是腿'
print(dayansl.leg)
5. 访问限制
java中提供了修饰符,pyhton中没有
_foo: protected,保护,只允许类本身加子类访问
__foo: private,私有类型,只允许类本身访问,类的实例名._类名__xxx
__foo__: 系统定义
pyhton中对以下划线开头的属性进行了变形,形成了_类型_foo(只发生在类的定义时,方法执行时不会采用这个变形)
class Swan:
'''天鹅类'''
_neck_swan = '天鹅脖子很长' # 受保护类型的属性
__neck_sy = '私有天鹅' # 私有类型
def __init__(self):
print('init()', Swan._neck_swan) # 访问保护类型属性
print('init()', Swan.__neck_sy) # 访问私有类型
def my(self):
print('my()', Swan.__neck_sy)
swan = Swan()
print(swan._neck_swan) # 通过实例名访问保护类型属性
print(swan._Swan__neck_sy) # 访问私有类型
swan._Swan__neck_sy = '天鹅私有修改' # 修改私有类型
print(swan._Swan__neck_sy) # 访问私有类型
swan.my()
6. proterty装饰器
property 访问计算后所得的值
@property装饰器,把方法转换成属性,可以通过排方法名访问方法,不用添加括号,不不可以重新赋值
@property
def method(self):
block
class Rect:
def __init__(self,width, height):
self.width = width
self.height = height
@property
def area(self):
return self.width * self.height # 计算矩形面积
rect = Rect(10, 10)
print('面积为', rect.area)
还可用于创建不能修改,只读的属性
class TvShow:
def __init__(self, show):
self.__show=show
@property
def show(self):
return self.__show
tvshow = TvShow('正在播放渣浪2')
print('默认', tvshow.show) # 获取属性值
# 下列代码修改报错
# tvshow.show='红海行动'
class TvShows:
list_film = ['战狼2', '红海行动', '西游记女儿国', '熊出没']
def __init__(self, show):
self.__show=show
@property
def show(self):
return self.__show
@show.setter
def show(self,value):
if value in TvShows.list_film:
self.__show= '点播' + value
else:
self.__show='不存在'
tvshows = TvShows('战狼2')
print('正在播放' + tvshows.show)
print('您可以从', TvShows.list_film ,'中点播')
tvshows.show = '红海行动'
print('修改后' + tvshows.show)
-
继承
class ClassName(baseClassList):
baseClassList: 要继承的父类,默认继承object,当子类继承父类,子类就继承了父类的的实例方法和属性
class Fruit:
color = '绿色' # 类属性
def harvest(self, color):
print('水果是:', color) # 输出形式参数color
print('水果已经收获')
print('水果原来的颜色', Fruit.color) # 输出类属性
class Apple(Fruit): # 继承Fruit类
color = '红色'
def __init__(self):
print('我是苹果')
class Orange(Fruit): # 继承Fruit类
color = '橙色'
def __init__(self):
print('我是橘子')
# 苹果类
apple = Apple() # 创建苹果类实例
apple.harvest(apple.color) # 调用父类的harbest方法
# 橘子类
orange = Orange()
orange.harvest(Orange.color)
1. 方法重写
class Fruit: # 父类 - 基类
color = '绿色' # 类属性
def harvest(self, color):
print('水果是:', color) # 输出形式参数color
print('水果已经收获')
print('水果原来的颜色', Fruit.color) # 输出类属性
class Apple(Fruit): # 继承Fruit类
color = '红色'
def __init__(self):
print('我是苹果')
# 重写方法
def harvest(self, color):
print('苹果是:', color) # 输出形式参数color
print('苹果已经收获')
print('苹果原来的颜色', Fruit.color) # 输出类属性
class Orange(Fruit): # 继承Fruit类
color = '橙色'
def __init__(self):
print('我是橘子')
# 重写方法
def harvest(self, color):
print('橘子是:', color) # 输出形式参数color
print('橘子已经收获')
print('橘子原来的颜色', Fruit.color) # 输出类属性
# 苹果类
apple = Apple() # 创建苹果类实例
apple.harvest(apple.color) # 调用父类的harbest方法
# 橘子类
orange = Orange()
orange.harvest(Orange.color)
2. 子类调用父类init()
默认子类创建init()后不会自动调用父类的init(),子类不定义构造方法,就会默认调用父类的构造方法
super.__init__(self)
class Fruit: # 父类 - 基类
def __init__(self,color='绿色'):
Fruit.color=color
print('水果类init')
def harvest(self, color):
print('水果是:', color) # 输出形式参数color
print('水果已经收获')
print('水果原来的颜色', Fruit.color) # 输出类属性
class Apple(Fruit): # 继承Fruit类
color = '红色'
def __init__(self):
# 调用基类的构造函数
super().__init__()
print('我是苹果')
# 重写方法
def harvest(self, color):
print('苹果是:', color) # 输出形式参数color
print('苹果已经收获')
print('苹果原来的颜色', Fruit.color) # 输出类属性
class Sapodille(Fruit): # 继承Fruit类
def __init__(self, color):
# 调用基类的构造函数
print('我是人参果')
super().__init__(color)
# 重写方法
def harvest(self, color):
print('人参果是:', color) # 输出形式参数color
print('人参果已经收获')
print('人参果原来的颜色', Fruit.color) # 输出类属性
# 苹果类
apple = Apple() # 创建苹果类实例
apple.harvest(apple.color) # 调用父类的harbest方法
# 人参果
sapodille = Sapodille('白色')
sapodille.harvest('金黄色')
-
模块
把能够实现某一特定功能的代码放置在一个文件夹中作为一个模块
使用模块的好处
1. 避免函数名和变量名冲突
2. 更容易查找代码
3. 提交代码重永兴
4. 有选择的使用
标准模块-标准库
random、math、sys、tkinter、decimal、os、logging、urllib、json、calendar、re、shutil、datetime
1. 创建模块
# 模块-model包内 模块名BMI
def bmi(height, weight, person='路人已'):
'''
计算单人BMI
:param person: 姓名
:param height: 身高
:param weight: 体重
:return:
'''
print(person+'您的身高为:' + str(height) + '米' + '体重为' + str(weight))
bmi = weight / (height ** 2)
print(person, '您的bmi指数为:', bmi)
if bmi < 18.5:
print(person, '体重过轻')
elif 18.5 >= bmi < 24.9:
print(person, '正常范围')
elif 24.9 >= bmi < 29.9:
print(person, '体重过重')
elif 29.9 >= bmi:
print(person, '体重肥胖')
def bmi_a(*person): # 可变参数
'''
计算多个人
:param person:
:return: 可变参数 姓名 身高m 体重kg
'''
for list_person in person:
for item in list_person:
person = item[0]
height = item[1]
weight = item[2]
print(person + '您的身高为:' + str(height) + '米' + '体重为' + str(weight))
bmi = weight / (height ** 2)
print(person, '您的bmi指数为:', bmi)
if bmi < 18.5:
print(person, '体重过轻')
elif 18.5 >= bmi < 24.9:
print(person, '正常范围')
elif 24.9 >= bmi < 29.9:
print(person, '体重过重')
elif 29.9 >= bmi:
print(person, '体重肥胖')
2. import导入模块
import 模块名 as 别名
from 模块名 import 方法名1,方法名2
如导如的方法过多 方法名可以为*
dir() 可以查看内部定义了哪些函数
导入两个包含同名函数的模块可用使用as进行修改别名,否则直接调用会有意想不到的惊喜
下方调用模块代码请看1. 创建模块
import module.BMI as bmi
bmi.bmi(1.8, 70, '张三')
from module.BMI import *
# 查看内部定义函数
print(dir())
# 模块函数调用
bmi(1.87, 50)
bmi_a([('张三', 1.87, 60)])
3. 模块搜索目录
使用标准模块sys中的path变量来获取
1. 临时添加要查找的目录
sys.path.append('路径')
关闭后失效
2. 添加.path文件
在python安装目录下添加*.path
3. 在python path环境变量中添加
在系统变量中添加PYTHPATH路径为保存模块的路径
import sys
# 临时添加要查找的目录
sys.path.append("F:\\python-works\\python_basis\\day6\\module")
# 下面就可以直接导入了不需要加路径
import BMI
-
主程序
if __name__ == '__main__':
__name__ 模块名称变量
当程序在顶级模块运行时,他的值为__main__
if __name__ == '__main__':
pass
-
包
包内包含__init__.py
避免模块名重名引发的冲突
import 完整包名+模块名
form 完整包名 import 模块名
from 完整包名.模块名 import 定义名
-
标准模块
导入和使用标准模块
import random
# 生成随机验证码
if __name__ == '__main__':
checkcode = '' # 验证码
for i in range(4):
# 生成一个0^3中的一个数
index = random.randrange(0, 4)
if index != i and index + 1 != i:
# 生成 a-z 小写字母(97 - 122) ASCII
checkcode += chr(random.randint(97, 122))
elif index +1 == i:
# A-Z大写紫米
checkcode += chr(random.randint(65, 90))
else:
checkcode += str(random.randint(1, 9))
print(checkcode)
-
第三方模块
1. https://pypi.org
2. pip
pip <command> [moduleName]
command: install uninstall list
导入顺序
1. 标准模块
2. 第三方模块
3. 自定义模块
-
文件
File对象
1. 创建、打开、关闭文件
file = open(fileName[, mode[, buffering]])
fileName: 创建或者要打开的文件名
buffering: 0:不缓存 1:缓存 大于1:缓冲区大小
mode: 文件的打开模式
r = 只读
r+ = 读写 从头覆盖原内容
w = 只写 文件不存在创建
w+ = 打开文件后,先清空原内容,使其成为空文件,对这个空文件有读写权限
a = 追加 文件不存在创建
a+ = 读写,文件存在指针放末尾,否则新建读写
b = 二进制
rb = 二进制打开文件 只读
rb+ = 二进制打开,读写,文件的指针在文件的开头,常用非文本文件,图片声音等
wb = 二进制,只读,常用于图片声音等非文本
wb+ = 二进制,读写,绯闻班
ab = 二进制,追加,文件存在则指针放在文件末尾,否则创建新文件用于写入
ab+ = 二进制,追加,文件存在指针放末尾,否则新建文件读写
可以和+进行组合
关闭文件
file.close() 关闭文件
file.closed 查看文件是否被关闭 Flase没有关闭 True 关闭
# 创建和打开文件
file_img = open('file/123.jpg', 'rb') # 二进制打开图片
print(file_img)
# 关闭文件
if not file_img.closed:
print('文件未关闭', file_img.closed)
file_img.close()
print('文件已关闭', file_img.closed)
2. with 打开文件
使用with打开文件后会自动关闭
with expression as target:
expression: 表达式 指定要打开文件的open()
target: 指定变量 保存打开的结果
# 创建和打开文件 open
with open('file/status.txt', 'r', encoding='utf-8') as file:
pass
print('文件是否被关闭', file.closed)
3. 文件写入
write() 文件写入 返回写入量
file.write(string)
flush() 刷新缓冲区进行写入
file.flush()
writelines() 写入字符串列表 不会换行
file.writelines()
file = open('file/message.txt', 'w', encoding='utf-8')
print('\n即将显示\n')
file.write('蚂蚁呀嘿') # 写入时如没关闭文件会容易出现不显示的问题
# file.close()
file.flush() # 刷新缓冲区
file = open('file/message.txt', 'w', encoding='utf-8')
file.write('你使用了一张加速卡,小鸡撸起袖子开始双手吃饲料,进食速度大大加快\n')
print('写入了一条动态')
# file.writelines()
file.close()
str_list = ['姚明', '博尔特', '姆巴佩', '张一鸣']
with open('file/message.txt', 'w', encoding='utf-8') as file:
file.writelines([line + '\n' for line in str_list])
4. 读取文件
read() 读取指定字符串
file.read([size])
size: 读取的个数,不指定默认全部读取
读取文件前提:打开文件模式只能是r或者r+拥有读取权限的
没一个字母汉字数字等都占一个字符
seek() 将指针移动到指定位置
file.seek([size])
size:英文字母数字占一个字符,汉字根据编码不同所占数不同
汉字: gbk 2字符 utf8 3字符
TODO 英文半角符号就占用一个字符!!!!!!!!!!踩过坑
readLine() 读取一行
file.readline()
readLines() 读取全部行
file.readLines()
with open('file/message.txt', 'r+', encoding='utf-8') as file:
file.seek(30)
content = file.read(2)
print(content)
# 逐行读取
with open('file/tansuo.txt', 'r', encoding='utf-8') as f:
print('=' * 10)
num = 0
while True:
num += 1
line = f.readline()
if line == '':
break
print(num, line, end='\n')
print('over')
# 读取全部行
with open('file/tansuo.txt', 'r', encoding='utf-8') as f:
message = f.readlines()
print(message)
for line in message:
print(line)
print('over')
-
目录
os模块: 内置与操作系统功能和文件系统相关的模块,该模块中的雨具执行结果通常与操作系统有关,不同操作系统运行结果不同
1. os模块和os.path模块
os.path是os的子模块,只需要导入os模块即可
os.name 获取操作系统名称,返回 'nt' = windows 'posix' = linux or macos
os.linesep 获取当前系统换行符
os.sep 获取当前系统路径所使用分隔符
getcwd() 返回当前的工作目录
listdir(path) 返回指定路径下的文件和目录信息
mkdir(path,[,mode]) 创建目录
makedits(path/path..., [, mode]) 创建多级目录
rmdir(path) 删除目录
removedirs(path1,path2...) 删除多级目录
chdir(path) 把path设置为当前工作目录
walk(top, [topdown[, oneerror]]) 遍历目录树,返回一个元组,包含所有路径名,所有目录列表和文件列表三个元素
os.path 目录相关函数
abspath(path) 获取文件或目录绝对路径
exists(path) 判断目录是否存在,存在返回True,不存在返回False
join() 将目录与目录或者文件名拼接起来
splitext() 分割文件名和扩展名
basename(path) 从一个目录中提取文件名
dirname(path) 从一个路径中提取文件路径,不包含文件名
isdir() 判断是否是路径
import os
print(os.name) # 获取操作系统名称
print(os.linesep) # 获取当前系统换行符
print(os.sep) # 获取当前系统路径所使用分隔符
2. 路径
相对路径:相对于当前文件的路径
绝对路径:完整文件路径
getcwd() 获取当前目录
os.path.abspath(path) 获取绝对路径
path 相对路径
os.path.join(path1, path2...) 拼接路径
不会检查路径是否真实存在
如果出现多个绝对路径,以最后一个出现的为准
路径尽量使用 r'路径'
import os
print(os.getcwd()) # 获取当前目录
# 相对路径
with open(r'file/message.txt', 'r', encoding='utf-8') as f:
print(f.read())
print(os.path.abspath(r'file/message.txt'))
# 拼接路径 不会检查路径是否存在
path = os.path.join(r'F:\python-works\python_basis\day7', r"file\message.txt")
print(path)
if os.path.exists(path):
print('存在')
3. 判断目录是否存在
os.path.exists()
import os
# 判断目录是否存在
print(os.path.exists(r'file'))
# 判断文件是否存在
print(os.path.exists(r'file/123.jpg'))
4. 创建目录
mkdir() 创建目录
os.mkdir(path,mode=0o755)
path: 路径
mode: 默认值00777,在unix无效
makedirs() 创建多级目录
os.makedirs(path, mode=0o777)
import os
if not os.path.exists('file/demo'):
os.mkdir('file/demo')
else:
print('该目录存在')
# 使用递归函数创建多级目录
def mkdir(path): # 创建递归函数
if not os.path.isdir(path): # 判断是否是路径
mkdir(os.path.split(path)[0])
else:
return
os.mkdir(path)
mkdir(r'file/demo/re/demo/test')
# 创建多级目录
os.makedirs(r'file/demo/re/demo/test')
5. 删除目录
rmdir()
os.rmdir(path)
目录不为空不可删除
rmtree(path) 删除不为空的目录
import shutil
shutil.rmtree()
import os
import shutil
# F:\python-works\python_basis\day7\file\demo\re\demo
# 删除目录
if os.path.exists(r'file\demo\re\demo'):
# os.rmdir(r'file\demo\re\demo')
# 删除非空目录
shutil.rmtree(r'file\demo\re\demo')
print('删除成功')
else:
print('目录不存在')
6. 遍历目录
win、unix系统
walk()
os.walk(top[, topdown][, onerror][, followlinks])
top:必选参数要遍历内容的根目录
topdown: 可选参数,指定遍历顺序 True自上而下遍历-先根目录后子目录,False自下而上-先遍历子目录
onerror: 错误处理方式,默认忽略
followlinks: true 指定在支持的操作系统上访问由符号链接(软连接)指向的目录,软连接相当于win中的快捷方式
返回值:元组生成器对象(dirpath, dirnames, filenames)
dirpath: 当前遍历的路径-字符串
dirnames: 当前路径下包含的子目录 - 列表
filenames: 当前路径下所包含的文件 - 列表
import os
path = r'G:\照片'
print('【', path, '】', '目录下包含的文件和目录')
for root, dirs, files in os.walk(path, topdown=True):
for filename in dirs:
print(os.path.join(root, filename)) # 输出遍历到的目录
for filename in files:
print('\t', os.path.join(root, filename))
7. 删除文件
remove(path)
os.remove()
import os
if os.path.exists(r'file/demo/re/test.txt'):
os.remove(r'file/demo/re/test.txt')
print('删除完成')
else:
print('文件不存在')
8. 重命名文件和目录
rname()
os.rname(src, dst)
src: 要进行重名的目录或者文件路径
dst: 重命名之后的目录或者文件名
import os
scr = r'file/demo/re/message.txt'
dst = r'file/demo/re/m.txt'
if os.path.exists(scr):
os.rename(scr, dst)
print('修改完成')
else:
print('目录或文件不存在')
9. 获取文件基本信息
stat()
os.stat(path)
st_ctime 创建日期
st_mtime 修改日期
st_size 文件大小
st_mode 保护模式
st_ino 索引号
st_atime 最后一次访问时间
import os
import time
# 格式化时间
def formatTime(longtime):
'''格式化时间'''
return time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
# 格式化文件大小
def fotmatByte(number):
'''格式化文件大小'''
for (scale, label) in [(1024*1024*1024, 'GB'), (1024*1024, 'MB'), (1024, 'KB')]:
if number >= scale: # 大于等于1kb
return '%2f %s' % (number*1.0/scale, label)
elif number == 1: # 小于1kb
return '1字节'
else:
byte = '%2f' % (number or 0)
return (byte[:-3] if byte.endswith('.00') else byte) + '字节'
fileinfo = os.stat(r'file/123.jpg')
print('文件完整路径', os.path.abspath('file/123.jpg'))
print('索引号', fileinfo.st_ino)
print('设备名', fileinfo.st_dev)
print('文件大小', fileinfo.st_size)
print('文件大小', fotmatByte(fileinfo.st_size))
print('最后一次访问日期', formatTime(fileinfo.st_atime))
print('最后一次修改日期', fileinfo.st_mtime)
print('最后一次状态改变的时间', fileinfo.st_ctime)
-
数据库
1. 连接数据库对象
SQLite模块:sqlite3
MySQL模块:pymsql
连接对象
connect() 生成连接对象-connection对象
dsn: 数据源
user: 用户名
password: 密码
host: 主机名
database: 数据库名
charset: 编码格式
cursorclass: 游标类
connection对象常用方法
cursor() 获取游标对象,操作数据库,指定dml,调用存储过程等
commit() 提交事务
rollback() 回滚事务
close() 关闭数据库连接
2. 游标对象
Cursor对象
Connection.cursor()
Cursor对象常用方法
callproc(proname,[, paramters]) 调用存储过程
close() 关闭游标对象
excute(operation[, paramters]) 执行数据库操作,sql语句或者数据库命令
excutemany(operation, seq_of_params) 用于批量操作
fetchone() 获取查询结果集中的下一条记录
fetchmany(size) 获取指定数量的记录
fetchall() 获取结果集所记录
nextset() 跳转下一个可用的结果集
3. 创建数据库文件
SQLite 是文本数据库,内置sqlite3
import sqlite3
#创建连接对象
conn = sqlite3.connect('mddn.db')
# 创建游标
cursor = conn.cursor()
# 执行sql
cursor.execute('create table user (id int(10) primary key, name varchar(20))')
# 关闭游标
cursor.close()
# 关闭连接
conn.close()
4. 操作SQLite
import sqlite3
# 创建连接对象
conn = sqlite3.connect('mddn.db')
# 创建游标
cursor = conn.cursor()
# 执行sql
sql = 'insert into user (id,name) values (?, ?)'
# cursor.execute(sql,(2, 'xiaoming'))
# 新增多条语句
# data = [(3, 'lisi'), (4, 'wangwu'), (5, 'bobi')]
# cursor.executemany(sql, data)
# 查询数据
sql = 'select * from user where id > 3'
cursor.execute(sql)
# 获取单条
# res1 = cursor.fetchone()
# print(res1)
# 获取指定条数
# res1 = cursor.fetchmany(2)
# print(res1)
# 获取所有
# res1 = cursor.fetchall()
# print(res1)
# 修改用户信息 需要提交事务
# sql = 'update user set name = ? where id = ?'
# cursor.execute(sql, ('MR', 1))
# 删除用户信息 不需要提交事务
sql = 'delete from user where id = ?'
cursor.execute(sql, (1,))
# 关闭游标
cursor.close()
# 提交事务 - 查询语句不需要事务
conn.commit()
# 关闭连接
conn.close()
5. 连接mysql
# 导入PyMysql模块
import pymysql
# 调用connect() 创建连接对象
conn = pymysql.connect(host='127.0.0.1', user='root', password='123456', db='test', charset='utf8')
# 调用cursor() 创建cursor对象
cursor = conn.cursor()
# 执行sql语句
sql = 'select * from jimu_dict'
cursor.execute(sql)
data = cursor.fetchall()
print(data)
# 关闭连接
cursor.close()
# 关闭数据源
conn.close()
6. 创建数据库表
# 导入PyMysql模块
import pymysql
# 调用connect() 创建连接对象
conn = pymysql.connect(host='127.0.0.1', user='root', password='123456', db='test', charset='utf8')
# 调用cursor() 创建cursor对象
cursor = conn.cursor()
# 执行sql语句
cursor.execute('drop table if exists books') # 如果数据库表存在则删除
sql = """
create table books(xxx)
"""
sql = 'select * from jimu_dict'
cursor.execute(sql)
data = cursor.fetchall()
print(data)
# 关闭连接
cursor.close()
# 关闭数据源
conn.close()
7. 操作数据库表
sqlite占位符为?
pymysql占位符为%s
# 导入PyMysql模块
import pymysql
# 调用connect() 创建连接对象
conn = pymysql.connect(host='127.0.0.1', user='root', password='123456', db='test', charset='utf8')
# 调用cursor() 创建cursor对象
cursor = conn.cursor()
# res = cursor.fetchall()
# print(res)
try:
# 执行sql语句
sql = 'insert into books(name,category,price,publish_time) values(%s,%s,%s,%s)'
data = [('0基础', 'python', 79.80, '2018-11-11'), ('java基础', 'java', 22.80, '2018-12-12'),
('web基础', 'web', 99.80, '2024-11-11')]
cursor.executemany(sql, data)
conn.commit()
except:
conn.rollback()
# 关闭连接
cursor.close()
# 关闭数据源
conn.close()
-
进程
1. 使用multiprocessing模块进程
os.fork() 不支持win, 只支持linux
multiprocessing模块process类
Process([group[, target[, name[, args[, kwargs]]]]])
group: 参数未使用,始终为None
targer: 表示当前进程启动时执行的可调用对象
name: 当前进程实例的别名
args: 表示传递给target函数的参数元组
kwargs: 表示传递给target函数的参数字典
is_alive() 判断进程实例是否还在执行
join([timeout]) 是否等待进程实例执行结束,或等待多少秒
start() 启动进程实例
run() 如果没指定target参数,对这个对象调用start()时,就执行对象中的run()
timeinate() 不管任务是否完成,立即终止
属性
name: 当前进程实例别名,默认为Process-N N为从1开始递增的整数
pid: 当前进程实例的PID值
from multiprocessing import Process
import time
import os
def test(intervel):
time.sleep(intervel)
print("我是子进程")
def main():
print('主进程开始')
p = Process(target=test, args=(1,))
p.start()
print('主进程结束')
# 实例 使用Process子类创建2个进程,并记录子进程运行时间
def child_1(intervel):
print('子进程(%s)开始执行,他的父进程是(%s)' %(os.getpid(), os.getppid()))
t_start = time.time()
time.sleep(intervel)
t_end = time.time()
print("子进程(%s)执行时间为%0.2f秒" %(os.getpid(), t_end - t_start))
def child_2(intervel):
print('子进程(%s)开始执行,他的父进程是(%s)' %(os.getpid(), os.getppid()))
t_start = time.time()
time.sleep(intervel)
t_end = time.time()
print("子进程(%s)执行时间为%0.2f秒" %(os.getpid(), t_end - t_start))
def doubleMain():
print('主进程开始')
print('主进程PID:', os.getpid())
p1 = Process(target=child_1, args=(1,))
p2 = Process(target=child_2, name='mddn', args=(1,))
p1.start()
p2.start()
print('p1 is_alive=%s', p1.is_alive())
print('p2 is_alive=%s', p2.is_alive())
print('p1.name=`%s`' % p1.name)
print('p2.name=`%s`' % p2.name)
p1.join()
p2.join()
print('主进程结束')
if __name__ == '__main__':
# main()
doubleMain()
2. 使用Process子类创建进程
run() 是进程运行时执行的方法
start() 进程开始执行的方法
调用start() 默认执行run()
from multiprocessing import Process
import time
import os
class SubProcess(Process):
def __init__(self,interval,name=''):
# 调用父类初始化方法
# super(SubProcess,self).__init__()
# 调用父类初始化方法
Process.__init__(self)
self.interval = interval
if name :
self.name = name
def run(self):
print('子进程(%s)开始执行,他的父进程是(%s)' % (os.getpid(), os.getppid()))
t_start = time.time()
time.sleep(self.interval)
t_end = time.time()
print("子进程(%s)执行时间为%0.2f秒" % (os.getpid(), t_end - t_start))
def doubleMain():
print('主进程开始')
print('主进程PID:', os.getpid())
p1 = SubProcess(interval=1,name='mddn')
p2 = SubProcess(interval=2)
p1.start()
p2.start()
print('p1 is_alive=%s', p1.is_alive())
print('p2 is_alive=%s', p2.is_alive())
print('p1.name=`%s`' % p1.name)
print('p2.name=`%s`' % p2.name)
p1.join()
p2.join()
print('主进程结束')
if __name__ == '__main__':
doubleMain()
3. 使用进程池Pool创建进程
apply_async(func[, args[, kwds]]) 使用非阻塞方式调用func函数(并行执行,阻塞方式必须等待上一个进程退出才能执行下一个)
args: 传递给func的参数列表
kwds: 传递给func的关键字参数列表
apply(func[, args[, kwds]]) 使用组设方式调用func函数
close() 关闭Pool,使其不在接收新的任务
terminate() 不干任务是否完成,立即终止
join() 主进程阻塞,等待子进程的退出,必须在close()或者terminate()之后使用
from multiprocessing import Pool
import os
import time
def task(name):
print('子进程(%s)执行任务%s'%(os.getpid(), name))
time.sleep(1)
if __name__ == '__main__':
print('父进程(%s)'%os.getpid())
pool = Pool(3)
for i in range(10):
pool.apply_async(task,args=(i,))
pool.close()
pool.join()
print('所有子进程结束')
4. 队列
两个子进程之间无法直接通信,可以使用队列和管道进行通信
from multiprocessing import Process
import time
import os
f_num = 100
def plus():
print('子进程1开始')
global f_num
f_num += 50
print('f_num=%d'%f_num)
print('子进程1结束')
def minus():
print('子进程2开始')
global f_num
f_num -= 50
print('f_num=%d'%f_num)
print('子进程2结束')
if __name__ == '__main__':
print('主进程开始')
p1 = Process(target=plus)
p2 = Process(target=minus)
p1.start()
p2.start()
p1.join()
p2.join()
print('主程序结束')
5. 多进程队列的使用
队列先入先出
queue类: 处理队列
put(item, [block[, timeout]]) 将item消息写入队列
block: 默认为True,如果队列为空,block为false,则立即抛出异常,block如果为True,需要设置timeout超时时间,超时时间单位为秒
get(item, [block[, timeout]]) 获取队列中的一条消息,然后将其从队列中删除
get_nowait() 相当于get(False)
empty() 判断队列是否为空,空:true 非空:false
full() 查看队列是否已满
qsize() 返回当前队列包含的消息数量
from multiprocessing import Queue
if __name__ == '__main__':
q = Queue(3)
q.put('消息1')
q.put('消息2')
print('队列是否已满…%s' % q.full())
q.put('消息3')
print('队列是否已满…%s' % q.full())
try:
# q.put('消息4', True, 2)
q.put_nowait('消息4')
except:
print('消息已满, 现在的消息数量%s' % q.qsize())
if not q.empty():
print('从队列中取消息')
for i in range(q.qsize()):
print(q.get_nowait())
if not q.full():
q.put('消息5')
print(q.qsize())
6. 使用队列在进程间通信
from multiprocessing import Process, Queue
import time
def writr_task(q):
if not q.full():
for i in range(5):
message = '消息' + str(i)
q.put(message)
print('写入:%s' % message)
def read_task(q):
time.sleep(1)
while not q.empty():
print('读取:%s' % q.get(True, 2))
if __name__ == '__main__':
print('主进程开始')
q = Queue()
pw = Process(target=writr_task, args=(q,))
pr = Process(target=read_task, args=(q,))
pw.start()
pr.start()
pw.join()
pr.join()
print('主进程结束')
-
线程
操作系统能够进行运算调度的最小单位,它包含在进程之中,是进程实际运作单位
线程的特点
1. 进程是资源分配的最小单位,线程是最小的执行单位
2. 一个进程可以有多个线程
3. 现成共享进程资源
在多线程开发中,全局变量是多个线程都共享的数据,为防止数据混乱,通常使用互斥锁。
而局部变量等是各自线程的,是非共享的,不需要使用互斥锁
1. 使用threading模块创建线程
threading模块中的Thread类创建线程
Thread([group[, target[, name[,args[, kwargs]]]]])
group: 参数未使用,始终为None
target: 表示当前线程启动时执行的可调用对象
name: 线程实例的别名
args: 表示传递给target函数的参数元组
kwargs: 表示传递给target函数的参数字典
current_thread().name 获取当前线程的name值
import threading
import time
def thread():
for i in range(3):
time.sleep(1)
print('thread name is %s' % threading.current_thread().name)
if __name__ == '__main__':
print('主线程开始')
threads = [threading.Thread(target=thread) for i in range(4)]
for t in threads:
t.start()
for t in threads:
t.join()
print('主线程结束')
2. 使用thread子类创建线程
继承thread类
重写run()
如不赋值不需要创建init()
from threading import Thread
import time
class subThread(Thread):
def run(self):
for i in range(3):
time.sleep(1)
msg = '子线程' + self.name + '执行 i=' + str(i)
print(msg)
if __name__ == '__main__':
print('主线程开始')
t1 = subThread()
t2 = subThread()
t1.start()
t2.start()
t1.join()
t2.join()
print('主线程结束')
3. 互斥锁
互斥锁:防止多个线程同时读取某一内存中的区域
threading.Lock() 加锁
线程之间可以进行通信
from threading import Thread
import time
import os
f_num = 100
def plus():
print('子线程1开始')
global f_num
f_num += 50
print('f_num=%d'%f_num)
print('子线程1结束')
def minus():
print('子线程2开始')
global f_num
f_num -= 50
print('f_num=%d'%f_num)
print('子线程2结束')
if __name__ == '__main__':
print('主线程开始')
t1 = Thread(target=plus)
t2 = Thread(target=minus)
t1.start()
t2.start()
t1.join()
t2.join()
print('主线程序结束')
4. 使用互斥锁
threading.Lock() 创建锁
锁对象.acquire([blocking]) 锁定
blocking:bool值,成功锁定返回true,否则返回false
锁对象.release() 释放锁,未锁定调用抛出异常
注意死锁!!!!!
from threading import Lock, Thread
import time
n = 100
def task():
global n
mutex.acquire()
time.sleep(1)
n -= 1
print('够买成功剩余%d' % n)
mutex.release()
if __name__=='__main__':
mutex = Lock()
t_list = []
for i in range(10):
t = Thread(target=task)
t_list.append(t)
t.start()
for t in t_list:
t.join()
5. 使用队列在线程间通信
生产者 product 消费者 consumer 仓库 queue
from queue import Queue
from threading import Thread
import time
import random
class Producer(Thread):
def __init__(self, name, queue):
Thread.__init__(self,name=name)
self.data =queue
def run(self):
for i in range(5):
print('生产者%s将产品%d加入队列' % (threading.current_thread().name, i))
self.data.put(i)
time.sleep(random.random())
print('生产者%s完成' % threading.current_thread().name)
class Consumer(Thread):
def __init__(self, name, queue):
Thread.__init__(self, name=name)
self.data =queue
def run(self):
for i in range(5):
val = self.data.get()
print('消费者%s将产品%d取出' % (threading.current_thread().name, val))
time.sleep(random.random())
print('消费者%s完成' % threading.current_thread().name)
if __name__ == '__main__':
print('主线程开始')
queue = Queue()
producer = Producer('Producer', queue)
consumer = Consumer('Consumer', queue)
producer.start()
consumer.start()
producer.join()
consumer.join()
print('主线程结束')
-
进程和线程的区别
1. 进程是系统进行资源分配和调度的一个独立单位,线程是进程的一个实体,是cpu调度和分派的基本单位
2. 进程之间是相互独立的,多进程中,同一个变量,各自有一份拷贝存在于每个进程中,但互不影响,而同一个进程的多个线程是内存共享的,所有变量都由所有线程共享
3. 由于进程间是独立的,因此一个进程的崩溃不会影响到其他进程;而线程是包含在进程之内的,线程的崩溃就会引发进程的崩溃,继而导致同一个进程内的其他线程也崩溃