Python-基础
Jupyter NoteBook 深入理解 Python 基础
Python-基础
1 |
|
1. 格式化输出 format
1 |
person_name = '张三' |
2. %s
1 |
|
3. input
输入
1 |
# input |
4. 进制转换
1 |
// 二进制 => 十进制 |
5. 三目运算符
1 |
# 三目运算符 |
6. if
语句
1 |
# if |
7. for
循环
1 |
# 使用系统 range 指定范围 |
8. for else
结构
1 |
# pass 空语句 |
9. while
循环
1 |
n = 1 |
10. 字符串
-
常量
1
2
3
4
5
6
7
8
9
10
11
12
13s1 = 'abc'
s2 = "abc"
s3 = '''abc'''
print(id(s1),id(s2),id(s3))
s1: 2128137317424
s2: 2128137317424
s3: 2128137317424
# 三引号占用的内存空间与单双引号不同
print(s1==s2) # 比较的是内容 True
print(s1 is s2) # 比较的是地址 True -
变量
1
2
3
4s1 = input('请输入:')
s2 = input('请输入:')
print(s1==s2) # True
print(s1 is s2) # False ,常量是 True, input() 底层做了处理,所以最后地址是不一样的 -
切片使用
1
2
3
4
5
6
7
8filename = 'picture.png'
filename[5] # 从0 开始 取第 5 位
filename[0:5] # 取出 5 位
filename[::-1] # 倒叙输出 -
字符串的内置方法
1
2
3
4
5
6
7
8# 大小写相关
str = 'abc bb'
print(str.capitalize()) # 首字母大写 Abc bb
print(str.title()) # 单词的每个首字母大写 Abc Bb
print(str.upper()) # 所有字母大写 ABC BB
print(str.lower()) # 所有字母小写 abc bb -
随机数应用
(验证码) 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 验证码案例
code = ''
import random
s = 'QWERTYUIOPASDFGHJKLZXCBN'
for i in range(4):
ran = random.randint(1, len(s) - 1)
code += s[ran]
print(code)
user_input = input('请输入验证码: ')
if user_input.lower() == code.lower():
print('验证码输入正确')
else:
print('验证码输入错误') -
查找相关的
1
2
3
4
5
6
7
8
9# find() rfind() lfind() index rindex() replace()
str = 'abcd'
print(str.find('e')) # 找不见返回 -1 ,找见输出起始位置
print(str.rfind('e')) # 找不见返回 -1 ,找见输出起始位置
# index() 找不见报异常
# ValueError: substring not found
1
2
3
4
5# rfind()
x = path.rfind('/')
filename = path[x+1::]
print(filename)1
2
3
4
5
6
7
8
9
10
11# replace()
replace(old,new[,max])
# 将空格替换为 # 号
s1 = 'indec lucy luks gooes'
s2 = s1.replace(' ','#')
print(s2)
# 指定替换的做大次数
s2 = s1.replace(' ','#',2) -
编码相关
1
2
3
4
5
6
7
8
9
10
11
12
13# encode 编码
# decode 解码
# 解码编码
msg = '人生苦短,我学 Python'
# encode('指定编码') decode('')
result = msg.encode('utf-8')
print(result)
decode =result.decode('utf-8')
print(decode) -
endswith() startwith()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17应用: 文件上传 只能上传 (jpg,png,bmp,gif)
# 返回值都是布尔类型 True False
# endswith()
filename = 'python.png'
result = filename.endswith('png') # filename 是否以 png 结尾
print(result) # True
--------------------------------------------------------------------------------
# startwith()
s = 'hello'
result = s.startswith('he') # 判断是否以 he 开头
print(result) # True -
join
使用 1
2
3# join
new_str = '_'.join('abc') # 用符号连接字符串
print(new_str) # a_b_c -
去除左右空格
-
去除左边空格
1
2
3
4# 去除左空格
s = ' hello '
s = s.lstrip()
print(s+'1') # hello 1 -
去除右边空格
1
2
3
4# 去除右空格
s = ' hello '
s = s.rstrip()
print('a'+s+'1') # a hello1 -
去除左右两边的空格
1
2
3
4
5# 同时去除空格
s = ' hello '
s = s.strip()
print('a'+s+'1') # ahello1
-
-
分割字符串
1
2
3
4
5
6
7# split('指定字符切割','分割次数 int ')
s = 'hello world hello kitty'
result = s.split(' ')
print(result)
# 结果是 列表
# ['hello', 'world', 'hello', 'kitty'] -
求取定个数
(统计) 1
2s = 'aaaaaaaaa'
s.count('s')
11. 列表
-
遍历列表
1
2for i in range(len(movies)):
print(movies[i]) -
修改列表
1
2
3
4
5branch = ['a','b','c']
branch[0] = 0
print(branch) # [0, 'b', 'c'] -
列表元素删除
1
2
3
4
5
6
7del branch[0]
print(branch)
# 删除相关
remove()
pop()
clear() -
列表的切片操作
1
2branch[1::]
print(branch[1::]) -
列表的函数使用
-
append()
1
2
3# append() 末尾追加
-
extend()
1
2
3
4# extend()
+、 extends() 列表的合并 -
insert()
1
2
3指定位置插入
-
-
列表的排序
1
2
3
4
5
6
7
8
9a = [100,1,5,20,45,11]
# 默认升序
sorted(列表)
# print(sorted(a)) [1, 5, 11, 20, 45, 100]
# 翻转
sorted(a, reverse=True)
# print(sorted(a, reverse=True)) [100, 45, 20, 11, 5, 1] -
冒泡排序
1
-
选择排序
1
12 . 元组
1 |
|
1 |
import random |
13. 字典
1 |
# 空字典 dict1 = dict() |
-
增加
1
2
3
4dict[key] = value;
# 同名则为修改 -
删除
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16del 字典名
[key] 对应的函数:
字典名.remove('key') # 没有报错
字典名.pop('key')
字典名.clear()
字典名.popitem()
注意:
pop([key,default])
根据 key 删除字典中的键值对,返回值是 只要删除成功,怎返回键值对的值 value
pop 的默认值,往往是在删除的时候没有找到对应的 key ,则返回 default 默认值
popitem(): 随机删除字典中键值对(一般都是从末尾删除元素)
-
修改
1
# 同名则为修改
-
查询
1
dict[key]
-
字典的拼接
1
update()
-
形式转换
1
2
3
4
5
6
7
8fromkeys(seq)
将 seq 转成字典的形式, 如果没有指定默认的 value 则用 None
list1 = ['a','b','c']
new_dict = dict.fromkeys(list1);
14. 集合
-
关键字
1
2
3
4集合: set 关键字 无序不重复的元素
作用: 不重复的特点
-
声明集合
1
set() # 创建空集合,
只能使用 set() -
应用
1
2
3
4list1 = [1, 2, 3, 4, 1, 2, 3]
newList = set(list1)
print(newList) # {1, 2, 3, 4} -
增
1
2
3
4
5
6
7
8
9
10
11
12
13s1 = set()
# 增
# 增加一个
s1.add('add-01')
s1.add('add-02')
s1.add('add-03')
print(s1) # {'add-03', 'add-01', 'add-02'}
# 增加多个
update()
t1 = ('a','b')
s1.update(t1)
print(s1) # 输出无序 -
删
1
2
3
4
5
6
7remove() # 存在删除,
没有报错 keyValue
pop() # 随机删除,在集合中删除第一个
clear() # 清空
dicard() # 类似remove() 在移除没有元素不报错 -
改
-
查
-
可变和不可变
1
2
3
4
5
6
7
8
9
10
11
12
13不可变: 对象指向的内存中的值是不可以改变
不可变的类型: int str float 元组tuple
----------------------------------------------
可变的; 对象所指向的内存中的值是可以改变的
可变类型: 字典dict 列表 list
-
类型转换
1
str() int() list() dict() set() tuple()
-
str
可转类型 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21int list set tuple
---------------------------- str--> int --------------------
s = '1234' # 字符串类型
i = int(s) # 字符串转换为数字
print(type(i)) # <class 'int'>
----------------------------- str--> list --------------------
list1 = list(s)
print(list1) # ['1', '2', '3', '4']
----------------------------- str--> set --------------------
set1 = set(s)
print(set1) # {'3', '4', '1', '2'}
----------------------------- str--> tuple --------------------
tupl1 = tuple(s)
print(tupl1) # ('1', '2', '3', '4') -
list
可转类型 1
set() tuple() 可以转换成字典 [(key,value),()···]
-
dict
可转类型 1
list
-
tuple
可转类型 1
list
-
set
可转类型 1
list
-
15. 函数
-
函数简介
1
2
3
4
5作用: 将重复的代码, 封装到函数, 只要使用直接找函数 函数可以增强代码的模块化和提高代码的重复利用率
格式:
def 函数名:
pass -
拆包装包
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17装包: 把传递的参数, 包装成一个集合, 称之为 “装包”
拆包: 把集合参数,再次分解成单独的个体, 称之为"拆包"
# 封装一个求和函数
def add(*args):
sum = 0
if len(args) > 0:
for i in args:
sum += i
print(sum)
else:
print('没有元素可以计算')
add()
add(1,2,4,6,100)注意: 可变参数必须放在后面 -
关键字参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21# 关键字参数
def add(a,b=1):
print(a+b)
add(1,2) # 3 b=1 相当于默认值,后来的值会将其覆盖
# 可变 值必须是 key=value
def add(**args):
pass调用函数时有 ** 叫拆包
定义时有 ** 叫装包
应用:
def bb(a, b, *c, **d):
print(a, b, c, d)
bb(1, 2) # 1 2 () {}
bb(1, 2, 3, 4) # 1 2 (3, 4) {}
bb(1, 2, x=100, y=20) # 1 2 () {'x': 100, 'y': 20} -
函数的返回值
1
2
3return
有 return 需要用变量接受 -
global
问题 1
2
3
4
5
6
7
8
9
10
11函数内部声明的变量, 局部变量
声明在函数外侧的变量是全局变量
def fun():
global name # 不修改全局变量,只是获取打印, 但是如果要发生修改全局变量, 则要在函数内部声明, global 变量名
全局变量如果是不可变在函数中进行修改需要添加 global 关键字
如果全局变量是可变的,在函数中修改的时候就不需要添加 global -
嵌套函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23def func():
# 声明变量
n = 100 # 局部变量
list1 = [2, 3, 45, 5]
# 声明内部函数
def inner_func():
nonlocal n # 内部函数修改局部变量需要使用 nonlocal
# 对 list1 的元素进行 +5 操作
for index, i in enumerate(list1):
list1[index] = i + n
list1.sort()
print(list1) # [102, 103, 105, 145]
inner_func()
func()内部函数的特点:
1. 可以访问外部函数的变量
2. 内部函数可以修改外部函数的可变类型的变量 比如: list1
3. 内部函数修改全局的不可变变量时,需要在内部函数声明 global 变量名
内部函数修改外部函数的不可变的变量时,需要在内部函数中声明; nonlocal 变量名
4. locals() 查看本地变量有哪些,以字典的形式输出
globals() 可以查看全局变量有那些,以字典的形式输出 (会出系统的一些键值对)
16. 闭包
-
闭包的概念
1
在函数中提出的概念 -
条件
1
2
3
4
5
6
7
8
9
10
111. 外部函数中定义了内部函数
2. 外部函数是有返回值
3. 返回值是: 内部函数域名
4. 内部函数引用了外部函数的变量
语法格式:
def 外部函数():
pass
def 内部函数():
pass
return 内部函数名 -
闭包的应用
1
-
闭包的缺点
1
2
3闭包的缺点:
1. 作用域没有那么直观
2. 因为变量不会被垃圾回收所以有一定的内存占用问题 -
闭包的作用
1
2
3
4闭包的作用:
1. 可以使用同级的作用域
2. 读取其他元素的内部变量
3. 延长作用域 -
闭包的总结
1
2
3
4
5总结:
1. 闭包似优化了变量,原来需要类对象完成工作, 闭包也可以完成
2. 由于闭包引用;额外部函数的局部变量,则外部函数的局部变量没有及时释放, 消耗内存
3. 闭包的好处,使代码变得简洁, 便于阅读代码
4. 闭包是理解装饰器的基础
17. 装饰器 (重点)
-
装饰器
1
2
3特点:
1. 函数 A 是作为参数出现的(函数 B 就会接受函数 A 作为参数)
2. 要有闭包的特点1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 定义一个装饰器 (含有闭包特点)
def decorate(func):
a = 100
def wrapper():
print('----------------------> 内部函数 输出')
func()
print('----------------------- 111111111111112222222222222', a)
return wrapper
# 使用装饰器
def house():
print('我是毛坯房······················')
# 调用函数
house() -
带参数的装饰器
1
2
3
4*args,**kwargs 作为参数传递
如果装饰器是多层的,谁距离函数最近就优先使用那个装饰器
18. 匿名函数
1 |
def add(a,b): |

-
匿名函数作为参数
1
-
map()
1
2
3list1 = [1,4,7,6]
result = map(lambda x:x if x%2==0 eldr x+1,list1)
print(list(result)) -
reduce()
1
对列表中的元素进行加减乘除运算的函数 -
filter()
1
2
3
4# 过滤出 大于 10 的数子
list1 = [10, 20, 2, 3, 4, 6, 19]
result = filter(lambda x: x > 10, list1)
print(list(result)) -
递归函数
1
2
3普通函数: def func(): pass 匿名函数: lambda 参数: 返回结果
递归函数: 普通函数的一种表现形式
文件操作
-
文件操作
-
文件读取
1
2
3
4
5
6
7
8
9import os
# 以 txt 文件练习 其他读取 有 gbk 错误
# 读取路径 print(os.getcwd()) D:\python就业视频\python 基础
stream = open(r'D:\python就业视频\python 基础\hello.txt')
container = stream.read()
txt = stream.readable() # 判断文件是否可读 True
readLine = stream.readline() # 读取一行
lines = stream.readlines() # 读取多行
print(container, txt, readLine)
-
-
文件写入
1
2
3
4
5
6# mode = 'a'
stream = open(r'D:\python就业视频\python 基础\hello.txt', 'w')
print(stream.write('aaaaaaaaaaaaaaaa')) # 覆盖源文件
print(stream.writelines(str)) # 保留源文件 追加 -
文件复制
1
2
3
4
5with open(r'D:\python
就业视频\python 基础\hello.txt') as stream:
container = stream.read() # 读取文件
with open(r'D:\python就业视频\hello.txt', 'w') as writeFile:
writeFile.write(container)
print('文件写入') -
os
模块 1
# 路径读取
异常机制
-
异常
1
2
3
4
5
6
7
8
9try:
可能出现异常的代码
except 类型1:
如果有异常执行的代码
except 类型1:
如果有异常执行的代码
···
finally:
无论是否存在异常都会执行的代码 -
try-except-else
结构: 1
-
try-finally
结构: 1
-
抛出异常
( 126
)集 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16# 抛出异常
def refister():
username = input('请输入用户名: ')
if len(username) < 6:
raise Exception('我是抛出的异常···')
else:
print('输入的用户名是: ' + username)
# 接受异常
try:
refister()
except Exception as err:
print(err)
print('注册失败')
else:
print('注册成功')
列表推导式 (128 集
)
-
列表推导式
-
[表达式 for 变量 in 旧列表]
1
-
[表达式 for 变量 in 旧列表 if 条件]
1
2
3
4
5
list1 = [10, 2, 4, 6, 90, 30, 60]
# 取出 大于 10的数
newList = [i for i in list1 if i >= 10]
print(newList) -
if else
1
2
3
4
5
6
7
8
9dict1 = {'name': 'tom', 'salary': 5000}
dict2 = {'name': 'lucy', 'salary': 8000}
dict3 = {'name': 'jack', 'salary': 4500}
dict4 = {'name': 'lily', 'salary': 3000}
# if 薪资大于 5000 加 200,低于 5000 加 500
newList = [person['salary'] + 200 if person['salary'] > 5000 else person['salary'] + 500 for person in list1]
print(newList) # [5500, 8200, 5000, 3500]
-
-
字典推导式
1
2
3
4# 集合推导式
list1 = [1, 2, 1, 2, 3, 4, 5, 6, 4]
set1 = {x for x in list1}
print(set1) # {1, 2, 3, 4, 5, 6} -
集合推导式
1
2
3dict1 = {'a': 'A', 'b': 'B'}
newdict = {value: key for key, value in dict1.items()}
print(newdict) # {'A': 'a', 'B': 'b'}
生成器
1 |
|
1 |
|
面向对象
-
面向对象
1
-
类
1
2
3class 类名
[(父类)]:
属性: 特征
方法: 动作 -
构造器
1
-
对象方法
1
2
3
4
5
6
7
8
9
class Phone:
def call(self):
print('call············')
phone = Phone()
# 通过对象调用的方法
phone.call() -
类方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19特点:
1. 定义需要依赖装饰器 @classmethod
2. 类方法中参数不是一个对象,而是类
3. 类方法中只可以使用类属性
4. 类方法中是否使用普通方法? 不能
类方法的作用:
因为只能访问类属性和类方法,所以可以在对象创建之前, 如果需要完成一些动作 (功能)
class Dog:
def __index__(self,nikename):
self.nikename = nikename
def run(self):
print('{}在院子里跑来跑去'.format(self.nikename))
def eat(self):
print('吃饭饭····')
# self.run() # 类中方法的调用 需要通过 self.方法名 ()
def test(cls):
print('cls') -
静态方法
1
-
魔术方法
(参考资料:Python 常用魔术方法) -
魔术方法是什么
1
魔术方法就是一个类 / 对象中的方法,和普通方法唯一的不同时,普通方法需要调用!而魔术方法是在特定时刻自动触发。 -
__init__
1
2
3初始化魔术方法
触发时机:初始化对象时触发(不是实例化触发,但是和实例化在一个操作中) -
__str__
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18# 单纯打印对象名称,
出来的是一个地址, 地址对于开发者来说没有太大意义
# 如果想在打印对象名的时候能够给开发者更多一些信息量
Eg.
class Person:
def __init__(self, nickname, age):
self.nickname = nickname
self.age = age
def __str__(self):
return '姓名是: ' + self.nickname + ',年龄是: ' + str(self.age)
person = Person('Bin', 18)
print(person) # 姓名是: Bin,年龄是: 18 1
2
3
4
5
6_str__
触发时机: 使用 print(对象) 或者 str(对象) 的时候触发
参数: 一个self 接收对象
返回值: 必须是字符串类型
作用: print(对象时)进行操作,得到字符串,通常用于快捷操作
注意: 无 -
__new__
(向内存要空间–> 地址)1
2
3
4
5
6
7
8
9实例化魔术方法
触发时机: 在实例化对象时触发
参数: 至少一个 cls 接收当前类
返回值: 必须返回一个对象实例
作用: 实例化对象
注意: 实例化对象是 Object 类底层实现,其他类继承了 Object 的 __new__ 才能够实现实例化对象。
没事别碰这个魔术方法,先触发 __new__ 才会触发 __init__ -
__call_
1
2
3
4
5
6
7
8调用对象的魔术方法
触发时机: 将对象当作函数调用时触发 对象()
参数: 至少一个self 接收对象,其余根据调用时参数决定
返回值: 根据情况而定
作用: 可以将复杂的步骤进行合并操作,减少调用的步骤,方便使用
注意: 无
-
-
知识补充
1
2
3
41. 对象赋值
p = Person()
p1 = p
说明: p 和 p1 共同指向同一个地址1
2
32. 删除地址的引用
del p1 删除 p1 对地址的引用1
2
3
43. 查看对地址的引用次数
import sys
sys.getrefcount(对象名)1
2
34. 当一块空间没有了任何引用,
默认执行 __del__
ref = 0 -
总结魔术方法
1 |
|
-
私有化
1
2
3
4
5
6
7
8私有化
封装:
1. 私有化属性
2. 定义公有 set 和 get 方法
_ _属性: 就是将属性私有化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23class Person:
def __init__(self, name, age):
self.__name = name
self.__age = age
def setName(self, name):
if len(name) > 0 and len(name) <= 6:
self.__name = name
else:
print('名字必须是 6 位')
def getName(self, name):
return self.__name
def __str__(self):
return '姓名:{},年龄是:{}'.format(self.__name, self.__age)
person = Person('Bin', 18)
# 修改
person.setName('asasa')
print(person) -
@property
装饰器 1
···
-
关联关系
(以后补充) 1
····
-
继承
1
2
3
4
5
6
7
8class fu:
pass
class zi-1(fu):
pass
class zi-2(fu):
pass注意: 可以重写 __init__ 1
super().__init__() # 调用父类的 __init__
-
继承案例练习
1
2
3
4
5
6
7
8
9
10
11
12编写一个简单的工资管理程序, 系统可以管理以下四类人, 工人 (worker),销售员 (salesman), 经理 (manager) 销售经理 (salemanager) 所有的员工都具有工号, 姓名, 工资等属性, 有设置姓名, 获取姓名, 获取员工号, 计算工资等
1. 工人: 工人具有工作小时数和时薪的属性,工资计算方法为工作小时数 * 时薪
2. 销售员: 具有销售额和提成比例的属性,工资计算方法为销售额 * 提成比例
3. 经理: 具有固定月薪的属性,工资计算方法为固定月薪
4. 销售经理: 工资计算方法为销售额 * 提成比例 + 固定月薪
请根据以上要求设计合理的类,完成一下功能:
1. 添加所有类型的人员
2. 计算月薪
3. 显示所有人工工资情况
1
2
3
python 有多继承的特点
-
-
多态
1
-
单例模式
1
-
实现单例有几种模式
1
模块
-
模块的导入
1
2
3
4
5
6
7在 python 中, 模块是代码组织中的一种方式, 把功能相近的函数或者类放到一个文件中, 一个文件 (.py) 就是一个模块 (model) 模块名就是文件名去掉后缀 py,
好处:
- 提高代码的可复用,可维护性, 一个模块编写完毕后, 可以很方便的在其他项目中导入
- 解决了命名冲突,不同模块中相同的命名不会冲突 -
导入模块的方式
1
2
3
4
5
6
7
8
9
10
111. import 模块名
(文件名 去除后缀)
2. from name import fun_name,变量名, 类名
3. from 模块名 import * (该模块中的所有内容)
但是如果像限制获取的内容,可以在模块中使用 __all__ =[]
注意: 无论是 import 还是 from 的形式,都会将模块内容进行加载
如果不希望其进行调用,就会用到 __name__
在自己的模块里面 __name__ 叫: __main__
如果在其他模块中通过导入的方式调用的话叫: __name__ : 模块名
if __name__ == '__main__':
pass -
导包
1
from 包名.
模块名 import 类名,变量名, 函数名 -
sys
1
-
time
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31import time
----------------------------------- 重点 -----------------------------
# 时间戳
print(time.time())
# 延迟
time.sleep(3)
# 将元组的时间转成字符串
s = time.strftime('%Y-%m-%d')
print(s)
----------------------------------------------------------------------
t = time.time()
print(t) # 1609993679.9369621
# 将时间戳转换成字符串
print(time.ctime(t)) # Thu Jan 7 12:27:59 2021
# 将时间戳转换成元组
t = time.localtime(t)
print(t)
print(t.tm_yday)
print(t.tm_hour)
# 将元组的转换成时间戳
print(time.mktime(t)) -
random
-
小数
1
2
3
4import random
# 随机小数
r = random.random()
print(r) -
前 10 位随机数,奇数位
1
2
3前 10 位随机数 # 奇数 1--> 起始值 10--> 终点值 2--> 步进值
ran = random.randrange(1, 10, 2)
print(ran) -
前 10 位随机数整数
1
2
3# 随机整数
ran = random.randint(1, 10)
print(ran) -
随机选择
1
2
3
4# 随机选择
list1 = ['a', 'b', 'c', 'd']
ran = random.choice(list1)
print(ran) -
打乱顺序
1
2
3
4# 打乱顺序
pai = ['红梅 A','方片K','黑 2']
ran = random.shuffle(pai)
print(pai) # 输出原列表 -
小应用: 验证码功能
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22# 验证码案例
def fun():
code = ''
for i in range(4):
# 随机整数
ranNum = str(random.randint(0, 9))
# A-Z
ranUpperStr = chr(random.randint(65, 90))
# a-z
ranLowerStr = chr(random.randint(97, 122))
# 存放大小写组合
ranList = [ranNum, ranUpperStr, ranLowerStr]
# 随机选择
rChoice = random.choice(ranList)
# 拼接得到最终组合
code += rChoice
return code
# 函数调用
code = fun()
# 输出
print(code)
-
-
hashlib
加密模块 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20print('--------------------- content: 2021-01-11 ------------------------')
# 加密算法
print('--------------------- Md5 ------------------------')
pwd = '123456'
# md5 不可逆 --> 单向
md5 = hashlib.md5(pwd.encode('utf-8'))
# 16 进制加密
print(md5.hexdigest()) # e10adc3949ba59abbe56e057f20f883e
print('------------------------- sha1 ----------------------------------')
sha1 = hashlib.sha1(pwd.encode('utf-8'))
# sha1 加密
print(sha1.hexdigest()) # 7c4a8d09ca3762af61e59520943dc26494f8941b
print('------------------------- sha256 ----------------------------------')
sha256 = hashlib.sha256(pwd.encode('utf-8'))
# sha1 加密
print(sha256.hexdigest()) # 8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92-
小案例: 登录注册
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 登录注册
str = '123456'
# encode
str_en = hashlib.sha256(str.encode('utf-8'))
# 加密
str_pwd = str_en.hexdigest()
str_list = []
str_list.append(str_pwd)
# 用户输入密码加密之后进行对比
user_input = input('请输入密码: ')
user_sha256 = hashlib.sha256(user_input.encode('utf-8'))
sha256_pwd = user_sha256.hexdigest()
for i in str_list:
if sha256_pwd == i:
print('登录成功!',i)
else:
print('请重新输入···')
-
-
Unicode
之间的转换 1
2
3# chr ord
print(chr(65)) # Unicode --> str
print(ord('A')) # str --> Unicode -
第三方
pillow
1
pip install pillow
正则表达式
-
正则表达式的定义
1
2正则表达式是对字符串的一种逻辑公式, 就是用事先定义好的一些特殊字符, 以及这些特殊字符组成规则的字符串
正则表达式是对字符串和特殊字符操作的一种逻辑公式 -
正则表达式的作用和特点
1
2
3
4
5
6
7
8
9
10给定一个正则表达式和另一个字符串, 达到一定目的
1. 给定的字符串是否符合正则表达式的过滤逻辑(称作匹配)
2. 可以通过正则表达式,从字符串中获取我们想要的特定部分
正则表达式的特点是:
1. 灵活性,逻辑性和功能性非常强
2. 可以迅速的用极简单的方式达到字符串的复杂控制
-
方法
1
2
3
4
5
6
7
8
9# 使用正则 re 模块的方法: match 从头开始匹配,
如果不成功则就返回 None
# 使用正则 re 模块的方法: search 进行正则字符串匹配方法,匹配的是整个字符串 输出索引位置
# group()
# sub(’正则表达式 ‘,'新内容','替换')
# split() 切割-
re.match
与 re.search
的区别 1
2
3
4
5
re.match 只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回 None,
re.search 匹配整个字符串,直到找到一个匹配。 -
检索和替换
1
2
3
4
5
6
7
8
9
10
11re 模块提供了 re.sub 用于替换字符串中的匹配项
# 语法
re.sub(pattern, repl, string, count=0, flags=0)
pattern : 正则中的模式字符串。
repl : 替换的字符串,也可为一个函数。
string : 要被查找替换的原始字符串。
count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
flags : 编译时用的匹配模式,数字形式。 -
compile
函数 1
compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match() 和 search() 这两个函数使用。
-
findall
:1
2
3在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。
注意: match 和 search 是匹配一次 findall 匹配所有。 -
split
1
split 方法按照能够匹配的子串将字符串分割后返回列表
-
-
正则预定义
1
2
3
4
5
6
7
8
9
10
11\A: 表示从字符串的开始处匹配
\Z: 表示从字符串的结束处匹配,如果存在换行,只匹配到换行前的结束字符串。
\b: 匹配-一个单词边界,也就是指单词和空格间的位置。例如,’py\b' 可以匹配’ python” 中的’ py’,但不能匹配”oenpyx1"中的 'py'
\B: 匹配非单词边界。’ py\b’可以匹配”openpyx1"中的’ py',但不能匹配”python"中的’ py'
\d: 匹配任意数字,等价于[0-9] 。
\D: 匹配任意非数字字符,等价于[ \d]。
\s: 匹配任意空白字符,等价于[\t\n\r\f]
\S: 匹配任意非空白字符,等价于[^\s]。
\w: 匹配任意字母数字及下划线,等价于[a-zA-Z0-9_ ]
\W: 匹配任意非字母数字及下划线,等价于[^ \w]
\\: 匹配原义的反斜杠\ -
总结
1
2
3
4
5
6
7
8
9
10
11
12
13
14. 任意字符除
(\n)
^ 开头
$ 结尾
[] 范围
量词:
* >= 0
+ >= 1
? 0,1
{m} =m 位
{m,} >=m
{m,n} phone>=m phone<=n(范围内的大小)
-
起名
1
2
3
4
5起名方式: (?P 正则)
分组: ()
分组可以使用 group(n组) 获取 -
group
小应用 1
2
3
4path = '''<img data-original="http://browser9.qhimg.com/bdm/768_474_0/t010448c46c1ecf7cab.jpg" alt="卡通人物 动漫卡通" title="关键字:卡通人物 动漫卡通" data-realurl="http://browser9.qhimg.com/bdr/__85/t010448c46c1ecf7cab.jpg" src="http://browser9.qhimg.com/bdm/768_474_0/t010448c46c1ecf7cab.jpg" style="display: inline;">
'''
result = re.match(r'<img data-original="http://browser9.qhimg.com/bdm/768_474_0/t010448c46c1ecf7cab.jpg" alt="卡通人物 动漫卡通" title="关键字:卡通人物 动漫卡通" data-realurl="http://browser9.qhimg.com/bdr/__85/t010448c46c1ecf7cab.jpg" src="(.*?)"',path)
print(result.group(1)) # http://browser9.qhimg.com/bdm/768_474_0/t010448c46c1ecf7cab.jpg
进程(实现快速执行某任务, 不论顺序)
-
进程概念
1
2
3进程是操作系统分配资源的最小单元···
线程是操作系统调度的最小单元··· -
创建进程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31from multiprocessing import Process
import os
from time import sleep
def task1(timer, name):
while True:
sleep(timer)
print(os.getpid(), '--------------------> ', os.getppid())
print('{}'.format(name))
def task2(timer, name):
while True:
sleep(timer)
print(os.getpid(), '--------------------> ', os.getppid())
print('{}'.format(name))
if __name__ == '__main__':
print('主进程···········')
# 子进程
p1 = Process(target=task1, args=(1, 'p1'), name='任务一')
print(p1.name)
p1.start()
p2 = Process(target=task2, args=(2, 'p2'), name='任务二')
print(p2.name)
p2.start()1
2
3
4
5
6
7
8
9
10'''
总结:
process.start() 启动进程并执行任务
process.run() 只是执行了任务但没有启动进程
terminate() 终止
'''
主进程: # (解释器的 run )
子进程: -
终止进程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47# 全局变量
# 进程练习源码 2021-01-11
from multiprocessing import Process
import os
from time import sleep
def task1(timer, name):
while True:
sleep(timer)
print(os.getpid(), '--------------------> ', os.getppid())
print('{}'.format(name))
def task2(timer, name):
while True:
sleep(timer)
print(os.getpid(), '--------------------> ', os.getppid())
print('{}'.format(name))
# 全局变量
number = 1
if __name__ == '__main__':
print('主进程···········', os.getpid())
# 子进程
p1 = Process(target=task1, args=(1, 'p1'), name='任务一')
print(p1.name)
p1.start()
p2 = Process(target=task2, args=(2, 'p2'), name='任务二')
print(p2.name)
p2.start()
while True:
number += 1
sleep(0.2)
if number == 10:
# 终止进程
p1.terminate()
p2.terminate()
break
else:
print('number: ', number) -
全局变量
1
2
3
4
5多进程对于全局变量访问, 在每一个全局变量里面都放一个 m 变量
保证每个进程访问变量互不干扰 -
非阻塞式进程池
1
2
3
4
5
6
7
8
9'''
当需要创建的子进程数量不多时,可以直接利用 multiprocessing 中的 Process 动态生成多个进程
但如果是上百甚至上千个目标,手动的的去创建进程的工作量巨大, 此时就可以用到 multiprocessing 模块提供的 Pool 方法
初始化 Pool 时,可以指定一个最大进程数, 当有新的请求提交到 Pool 时, 如果池还没有满, 那么就会创建一个新的进程来执行该请求, 但
如果池中的进程数已经达到指定的最大值,那么该请就就会等待, 直到池中有进程结束, 才会创建新的进程来执行
非阻塞式: 全部添加到队列中,立刻返回, 并没有等待其他的进程完毕, 但是回调函数是等待任务完成后才调用
阻塞式: 区别在 apply() apply_async()
'''1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48# 进程池
from multiprocessing import Pool
import os
import time
import random
def task_fun(task_name):
print('任务开始啦·············', task_name, os.getpid())
# 获取时间戳
start = time.time()
# 使用 sleep
time.sleep(3)
end = time.time()
print('用时: {}'.format(start - end))
# 需要 return
return '用时: {}'.format(start - end)
def callback_fun(n):
# 必须添加参数
container_list.append(n)
container_list = []
if __name__ == '__main__':
# 创建进程池 开启 5 个子进程
pool = Pool(5)
'''
源码,Pool 中的参数:
def Pool(processes: Optional[int] = ..., # 最大进程数 整数类型
initializer: Optional[Callable[..., Any]] = ...,
initargs: Iterable[Any] = ...,
maxtasksperchild: Optional[int] = ...) -> pool.Pool: ...
'''
list = ['1a', '2a', '3a', '4a', '5a', '6a', '7a', '8a']
for task in list:
# 非阻塞式
pool.apply_async(task_fun, args=(task,), callback=callback_fun)
pool.close() # 添加任务结束
pool.join() # 堵住主进程 插队,不会执行后续 over,会等待 子进程执行完毕··········
# 主进程任务
for i in container_list:
print(i) -
阻塞式进程池
1
特点: 添加一个执行一个任务, 如果一个任务不结束另一个任务就进不来 -
进程间的通信
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40# 进程通信
# 通信是通过同一个 args=(参数1,···)
from multiprocessing import Process, Queue
from time import sleep
def download(q):
imglist = ['a.jpg', 'b.jpg', 'c.jpg', 'd.jpg', 'e.jpg']
for img in imglist:
print('正在下载: ', img)
sleep(0.5)
# 放入
q.put(img)
def getfile(q):
while True:
try:
# 获取
file = q.get(timeout=5)
print('{} 保存成功'.format(file))
except:
print('全部保存完毕·········')
break
if __name__ == '__main__':
# 通信桥梁
q = Queue(5)
down = Process(target=download, args=(q,))
gets = Process(target=getfile, args=(q,))
# 创建进程
down.start()
# down 阻塞
down.join()
gets.start()
gets.join()
线程
-
线程的概念
1
2
3
4
5
6
7
8
9
10
11
12
13'''
线程: 有时被称为轻量进程(Lightweight Process LWP),是程序执行流的最小单位。一个标准的线程由线程 ID,当前指令指针 (PC) 寄存器集合和堆栈组成, 另外, 线程是进程中的一个实体, 是被系统独立调度和分排的基本单位,线程自己不拥有系统资源, 只拥有一点儿在运行中必不可少的资源, 但它可与同属一个进程的其他线程共享进程所拥有的全部资源. 一个线程可以创建和撤销另一个线程, 同一个进程中的多个线程之间可以并发执行。由于线程之间的相互制约, 致使线程在运行中呈现出间断性。线程也有就绪,阻塞和运行三种基本状态。
就绪状态: 是指线程具备运行的所有条件m 逻辑上可以运行, 在等待处理机;
运行状态: 是指线程占有处理机正在运行
阻塞状态: 阻塞状态是指线程在等待一个事件(如某个信号量), 逻辑上不可执行。每一个程序都至少有一个线程,若程序只有一个线程, 那就是程序本身。
''' -
多线程
1
2
3
4
5
6
7
8
9
10
11
12
13'''
线程是程序中一个单一的顺序控制流程。
程序内有一个相对独立的、可调度的执行单元.是系统独立调度和分派 CPU 的基本单位指令运行时的程序的调度单位。在单个程序中同时运行
多个线程完成不同的工作称为多线程
多线程: 多线程(multithreading) 是指从软件或者硬件上实现多个线程并发执行的技术。具有多线程能力的计算机因有硬件支持而能够
在同一时间执行多于一个线程,进而提升整体处理性能. 具有这种能力的系统包括多对处理机, 多核心处理器以及芯片级多处理或同时多线处理器。
在一个程序中,这些独立运行的程序片段就做 "线程",利用它的编程的概念就叫做"多线程处理".
''' -
优点
- 使用线程可以把占据很长时间的程序中的任务放到后台去处理
- 用户界面可以更加吸引人,
这样比如用户点击了一个按钮去触发某些事件的处理, 可以弹出一个进度条
来显示用户处理的进度 - 程序的运行速度可能加快
- 在一些等待的任务实现上如用户输入,文件读写和网络收发数据等,
线程就比较有用了. 这种情况下我们可以释放一些
珍贵的资源如内存占用等等
-
线程的状态
1
新建 就绪 运行 阻塞 结束 -
全局解释器锁
1
2
3
4
5
6
7'''
Global Interpreter Lock,缩写 GIL 是计算机程序设计语言解释器用于同步线程的一种机制,它使得任何时刻仅有一个线程在执行。即
便在多核心处理器上,使用 GIL 的解释器也只允许同一时间执行一个线程。常见的使用 GIL 的解释器有CPython 与 Ruby MRI。
'''1
2
3线程用于: 耗时操作, 爬虫 IO 进程用于: 计算密集型 -
多线程同步
1
2
3
4
5
6
7
8
9
10数据共享:
如果多个线程共同对某个数据修改,则可能出现不可预料的结果,为了保证数据的正确性, 需要对多个线程进行同步
同步: 一个一个的完成,一个 1 做完另一个才能进来
效率会降低
使用 Thread 对象的 Lock 和 RLock 可以实现简单的线程同步,这个对象都有 acquire 方法 和 release 方法, 对于那些需要每次
只允许一个线程操作的数据,可以将其操作放在 acquire 和 release 方法之间
多线程的优势在于可以同时运行多个任务。但是当线程需要共享数据时,可能存在数据不同步的问题, 为了避免这种情况, 引入锁的概念 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import threading
from time import sleep
import random
# 锁对象
lock = threading.Lock()
# 可变类型
list1 = [0] * 10 # [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
# --------------------------------- S: 加锁任务 ----------------------------------------------
def task1():
# 获取线程锁,如果已经上锁, 则等待锁的释放
lock.acquire() # 阻塞
# 任务
for i in range(len(list1)):
list1[i] = 1
sleep(0.5)
lock.release() # 释放锁
def task2():
lock.acquire() # 阻塞
for i in range(len(list1)):
print('--------------> ', i)
sleep(0.5)
lock.release() # 释放锁
if __name__ == '__main__':
# 创建线程
th1 = threading.Thread(target=task1)
th2 = threading.Thread(target=task2)
# 开启线程
th2.start()
th1.start()
# 阻塞
th2.join()
th1.join()
print(list1)
# --------------------------------- E: 加锁任务 ---------------------------------------------- -
死锁
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54# 死锁
'''
开发过程中,在线程间共享多个资源的时候,如果两个线程分别占有一部分资源并且同时等待对方的资源,就会造成死锁.
尽管死锁很少发生,但一旦发生就会造成应用的停止响应, 程序不做任何事情
避免死锁
解决:
1. 重构代码
2. 使用 timeout 参数
'''
from threading import Thread, Lock
from time import sleep
# -------------------------------------------------------- S: 死锁 --------------------------------------
# 准备两把锁
lockA = Lock()
lockB = Lock()
# 自定义线程
class MyThreadA(Thread):
def run(self): # start()
# 源码: def acquire(self, blocking: bool = ..., timeout: float = ...) -> bool: ...
if lockA.acquire(): # 如果可以获取锁则返回 True (源码可知)
print(self.name + '拿到了A 锁')
sleep(0.1)
if lockB.acquire():
print(self.name + '又获取了B 锁, 原来还有 A 锁')
lockB.release() # 释放 B 锁
lockA.release() # 释放 A 锁
class MyThreadB(Thread):
def run(self): # start()
# 源码: def acquire(self, blocking: bool = ..., timeout: float = ...) -> bool: ...
if lockB.acquire(): # 如果可以获取锁则返回 True (源码可知)
print(self.name + '拿到了B 锁')
sleep(0.1)
if lockA.acquire():
print(self.name + '又获取了A 锁, 原来还有 B 锁')
lockA.release() # 释放 B 锁
lockB.release() # 释放 A 锁
if __name__ == '__main__':
th1 = MyThreadA()
th2 = MyThreadB()
th1.start()
th2.start()
# -------------------------------------------------------- E: 死锁 -------------------------------------- -
解决死锁
-
生产者与消费者
(线程之间的通信) 1
2
3
4
5
6
7
8
9
10
11
'''
生产者与消费者: 两个线程之间的通信
python 的 queue 模块中提供了同步的,包括 FIFO(先进先出) 队列 Queue
LIFO(后入先出) 队列 LifoQueue 和优先级队列 PriorityQueue。这些队列都实现了锁原语(可以理解为原子操作,即要么不做, 要么就全做), 能够在多线程中直接使用
可以使用队列来实现线程间的同步
'''1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46import queue
import threading
import random
from time import sleep
def produce(q):
i = 0
while i < 10:
num = random.randint(1, 100)
q.put('生产者产生的数据: %d' % num)
print('生产者产生的数据: %d' % num)
sleep(1)
i += 1
q.put(None)
# 完成任务
q.task_done() # task_done() 源码附有
def consume(q):
while True:
item = q.get()
if item is None:
break
print('消费者获取到: %s' % item)
sleep(4)
# 完成任务
q.task_done()
if __name__ == '__main__':
q = queue.Queue(10)
arr = []
# 创建生产者
th1 = threading.Thread(target=produce, args=(q,))
th1.start()
# 创建消费者
th2 = threading.Thread(target=consume, args=(q,))
th2.start()
th1.join()
th2.join()
print('END···············') -
数据共享总结
1
2
3
4
5
6进程共享数据与线程共享数据的区别:
进程是每个进程中都有一份
线程是共同一个数据 --> 数据安全问题
GIL --> 伪线程
-
协程
-
使用生成器创建协程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34# Coroutine 协程
'''
协程: 耗时操作
耗时操作: 网络请求 网络下载(爬虫), IO:文件的读写 阻塞
'''
from time import sleep
def task1():
for i in range(3):
print('A'+str(i))
yield
sleep(1)
def task2():
for i in range(3):
print('B' + str(i))
yield
sleep(2)
if __name__ == '__main__':
# 生成器
t1 = task1()
t2 = task2()
while True:
try:
next(t1)
next(t2)
except:
break -
第三方
greenlet
创建协程 1
2# greenlet
1
2
3
4
5# 进入 anaconda 安装的 Scripts
下
conda: conda install greenlet
windows: pip/pip3 install greenlet1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39from greenlet import greenlet
import time
def a():
for i in range(5):
print('A' + str(i))
gb.switch()
time.sleep(0.1)
def b():
for i in range(5):
print('B' + str(i))
gc.switch()
time.sleep(0.2)
def c():
for i in range(5):
print('C' + str(i))
ga.switch()
time.sleep(0.3)
if __name__ == '__main__':
ga = greenlet(a)
gb = greenlet(b)
gc = greenlet(c)
# 需要调一下
ga.switch()
'''
结果输出: A0 B0 C0 A1 B1 C1 A2 B2 C2 A3 B3 C3 A4 B4 C4
交替输出
'''
-
-
第三方
gevent
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
'''
conda解释器安装 gevent:
conda install gevent
成功后显示: All requested packages already installed.
全局解释器安装: pip/pip3 install gevent
'''
greenlet已经实现了协程,但是这个人工切换,是不是觉得太麻烦了,python 还有一个比 greenlet 更强大的并且能够自动切换任务的模块`gevent`, 其原理是当一个 greentlet 遇到 IO(指的是 input ouput 输入输出,比如网络、文件操作等)操作时,比如访问网络,就自动切换到其他的 greenlet, 等到 IO 完成,再适当的时候切换回来继续执行。
由于IO 操作非常耗时,经常使程序处于等待状态,有了 gevent 我们自动切换协程,就保证总有 greenlet 在运行,而不是等待 IO 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
from greenlet import greenlet
import gevent
import time
# 猴子补丁
from gevent import monkey
monkey.patch_all()
def a():
for i in range(5):
print('A' + str(i))
time.sleep(0.1)
def b():
for i in range(5):
print('B' + str(i))
time.sleep(0.2)
def c():
for i in range(5):
print('C' + str(i))
time.sleep(0.3)
if __name__ == '__main__':
g1 = gevent.spawn(a)
g2 = gevent.spawn(b)
g3 = gevent.spawn(c)
g1.join()
g2.join()
g3.join()
'''
没有猴子补丁的输出: A0 A1 A2 A3 A4 B0 B1 B2 B3 B4 C0 C1 C2 C3 C4
添加猴子补丁后输出: A0 B0 C0 A1 B1 A2 C1 A3 B2 A4 B3 C2 B4 C3 C4 # 实现协程
'''-
实现协程小应用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35# 协程案例
import urllib # 错误
import gevent
'''
erro: 由于暂时不了解爬虫,错误无法排除
date: 2021.01.13 13:40:31
python: 完结 python 基础学习
'''
# 猴子补丁
from gevent import monkey
monkey.patch_all()
def downUrl(url):
response = urllib.request.urlopen(url)
content = response.read()
print('下载了{} 的数据, 长度是:{}'.format(url, len(content)))
if __name__ == '__main__':
urls = ['http://www.163.com', 'http://www.qq.com', 'http://www.baidu.com']
g1 = gevent.spawn(downUrl, urls[0])
g2 = gevent.spawn(downUrl, urls[1])
g3 = gevent.spawn(downUrl, urls[2])
g1.join()
g2.join()
g3.join()
-
PyInstaller
-
安装
1
pip install pyinstaller
-
作用
将
python
文件编译为可执行文件独立运行 -
参数解析
参数 描述 -h
--clean
-D,--onedir
-F,--onefile
在 dist
文件夹中只生成独立的打包文件 -i <图标文件名.ico>
指定打包程序使用的图标 ico
文件 -
编译
1
pyinstaller -i xx.ico -F 将要编译的
python 源文件
PYMYSQL 模块
-
查询
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48# 输入相应参数
import pymysql
def main():
conn = pymysql.connect(host = 'localhost',
port = 3306,
user = 'root',
passwd = 'root',
db = 'student',
charset = 'utf8',
cursorclass = pymysql.cursors.DictCursor) # 修改类型 元组类型需要去除该参数
try:
# 获取游标对象
with conn.cursor() as cursor:
# 执行 sql 注意参数位置
cursor.execute('select eno,ename,sal from tb_emp')
# 元组类型结果集
# for row in cursor.fetchall():
# print('''
# ----------- 查询所有 -------
# eno: {}
# ename: {}
# sal: {}
# -------------------------
#
# '''.format(row[0], row[1], row[2]))
# 字典类型结果集 如果查询时带别名, 那么字典的键要更改为 别名
for row in cursor.fetchall():
# print(row)
print('''
-------------------------
eno: {}
ename: {}
sal: {}
--------------------------
'''.format(row['eno'], row['ename'], row['sal']))
except pymysql.MySQLError as erro:
print(erro)
finally:
# 关闭连接释放资源
conn.close()
if __name__ == '__main__':
main() -
添加
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35# pymysql 的使用
import pymysql
# 生成文件 pip freeze > requirements.txt
# 依赖项安装: pip install -r requirements.txt
def main():
conn = pymysql.connect(host = '127.0.0.1',
port = 3306,
user = 'root',
password = 'root',
db = 'student',
charset = 'utf8')
try:
# 获得游标对象
with conn.cursor() as cursor:
# execute 执行
result = cursor.execute('insert into tb_emp values(1001,"张三",4500)')
if result == 1:
print('添加成功')
# commit() 很重要 否则看不到响应结果
conn.commit()
else:
print('添加失败,操作已经回滚···')
except pymysql.MySQLError as error:
print(e)
conn.rollback()
finally:
conn.close()
if __name__ == '__main__':
a = main() -
删除
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35# 输入相应参数
import pymysql
def main():
conn = pymysql.connect(host = 'localhost',
port = 3306,
user = 'root',
passwd = 'root',
db = 'student',
charset = 'utf8')
eno = int(input('请输入要删除的员工编号: '))
try:
# 获取游标对象
with conn.cursor() as cursor:
# 执行 sql
result = cursor.execute('delete from tb_emp where eno=%s', (eno,))
if result == 1:
print('删除数据成功···')
conn.commit()
else:
print('删除数据失败,操作已经回滚····')
except pymysql.MySQLError as erro:
print(erro)
# 回滚
conn.rollback()
finally:
# 关闭连接释放资源
conn.close()
if __name__ == '__main__':
main() -
更新
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37# 输入相应参数
import pymysql
def main():
conn = pymysql.connect(host = 'localhost',
port = 3306,
user = 'root',
passwd = 'root',
db = 'student',
charset = 'utf8')
# 输入内容
oldeno = int(input('请输入原编号: '))
neweno = int(input('请输入新编号: '))
try:
# 获取游标对象
with conn.cursor() as cursor:
# 执行 sql 注意参数位置
result = cursor.execute('update tb_emp set eno = %s where eno = %s', (neweno, oldeno))
if result == 1:
print('更新数据成功···')
conn.commit()
else:
print('更新数据失败,操作已经回滚····')
except pymysql.MySQLError as erro:
print(erro)
# 回滚
conn.rollback()
finally:
# 关闭连接释放资源
conn.close()
if __name__ == '__main__':
main()