day17
笔记来源于:黑马程序员python教程,8天python从入门到精通,学python看这套就够了
目录
- day17
- 121、Python 操作 MySQL 基础使用
- pymysql
- 创建到 MySQL 的数据库链接
- 执行 SQL 语句
- 执行非查询性质的SQL语句
- 执行查询性质的SQL语句
- 122、Python 操作 MySQL 数据的插入
- 自动 commit
- 123、综合案例
- 案例需求
- DDL 定义
- 实现步骤
- Python 高阶技巧
- 1、闭包
- 基础概念
- 简单闭包
- 修改外部函数变量的值
- 使用闭包实现 ATM 小案例
- 2、装饰器
- 装饰器的一般写法(闭包写法)
- 装饰器的语法糖写法
- 3、单例模式
- 4、工厂模式
- 5、多线程并行执行概念
- 进程、线程
- 并行执行
- 6、多线程编程
121、Python 操作 MySQL 基础使用
pymysql
在Python中,使用第三方库:pymysql 来完成对MySQL数据库的操作。
安装:
1、pip install pymysql;
2、或者 PyCharm中安装包 PyMySQL(使用清华源:https://pypi.tuna.tsinghua.edu.cn/simple
)。
创建到 MySQL 的数据库链接
"""
演示 Python pymysql库的基础操作
"""
from pymysql import Connection
# 构建到 MySQL数据库的链接
conn = Connection(
host = "localhost", # 主机名(IP)
port = 3306, # 端口
user= 'root', # 账户
password= '666666' # 密码
)
# 打印 MySQL 数据库软件信息
# 验证是否连接上指定数据库
print(conn.get_server_info())
# 关闭链接
conn.close()
执行 SQL 语句
执行非查询性质的SQL语句
示例代码如下:
"""
演示 Python pymysql库的基础操作
"""
from pymysql import Connection
# 构建到 MySQL数据库的链接
conn = Connection(
host = "localhost", # 主机名(IP)
port = 3306, # 端口
user= 'root', # 账户
password= '666666' # 密码
)
# # 打印 MySQL 数据库软件信息
# # 验证是否连接上指定数据库
# print(conn.get_server_info())
# 执行非查询性质的 SQL
cursor = conn.cursor() # 获取到游标对象
# 选择数据库
conn.select_db("test")
# 执行 sql
cursor.execute("create table test_pymysql (id int);")
# 关闭链接
conn.close()
执行查询性质的SQL语句
"""
演示 Python pymysql库的基础操作
"""
from pymysql import Connection
# 构建到 MySQL数据库的链接
conn = Connection(
host = "localhost", # 主机名(IP)
port = 3306, # 端口
user= 'root', # 账户
password= '666666' # 密码
)
# print(conn.get_server_info())
# 执行非查询性质的 SQL
# 获取到游标对象
cursor = conn.cursor()
# # 选择数据库
# conn.select_db("test")
# # 执行 sql
# cursor.execute("create table test_pymysql (id int);")
# 选择数据库
conn.select_db("world")
# 使用游标对象,执行 sql 语句
cursor.execute("select * from student_1")
# 获取查询结果
results = cursor.fetchall()
for r in results:
print(r)
# 关闭链接
conn.close()
122、Python 操作 MySQL 数据的插入
直接使用:
cursor.execute("insert into student_2 values(10002, '林俊杰', 31, '男')")
经过执行是无法将数据插入到数据表 student 中的。
因为:pymysql在执行数据插入或其它产生数据更改的SQL语句时,默认是需要提交更改的,即,需要通过代码“确认”这种更改行为。通过链接对象.commit() 即可确认此行为。
示例代码:
"""
演示使用 pymysql 库进行数据插入的操作
"""
from pymysql import Connection
# 构建到 MySQL数据库的链接
conn = Connection(
host = "localhost", # 主机名(IP)
port = 3306, # 端口
user= 'root', # 账户
password= '666666', # 密码
)
# 执行非查询性质的 SQL
cursor = conn.cursor() # 获取到游标对象
# 选择数据库
conn.select_db("world")
# 执行 sql
cursor.execute("insert into student_2 values(10002, '林俊杰', 31, '男')")
# 通过 commit 确认
conn.commit()
# 关闭链接
conn.close()
自动 commit
如果不想手动commit确认,可以在构建链接对象的时候,设置自动commit的属性。
示例代码:
# 构建到 MySQL数据库的链接
conn = Connection(
host = "localhost", # 主机名(IP)
port = 3306, # 端口
user= 'root', # 账户
password= '666666', # 密码
autocommit=True # 自动提交(确认)
)
123、综合案例
案例需求
我们使用《面向对象》章节案例中的数据集,完成使用Python语言,读取数据,并将数据写入MySQL的功能。
DDL 定义
本次需求开发我们需要新建一个数据库来使用,数据库名称:py_sql
基于数据结构,可以得到建表语句:
create table orders(
order_date date,
order_id varchar(255),
money int,
province varchar(10)
);
实现步骤
示例代码:
DBeaver:
create database py_sql charset utf8;
use py_sql;
create table orders(
order_date date,
order_id varchar(255),
money int,
province varchar(10)
);
Python:
"""
SQL 综合案例,读取文件,写入 MySQL 数据库中
"""
from file_define import TextFileReader, JsonFileReader
from data_define import Record
from pymysql import Connection
text_file_reader = TextFileReader("E:/3code/PyCharm/pythonProject/mysql/03_综合案例/2011年1月销售数据.txt")
json_file_reader = JsonFileReader("E:/3code/PyCharm/pythonProject/mysql/03_综合案例/2011年2月销售数据JSON.txt")
jan_data: list[Record] = text_file_reader.read_data()
feb_data: list[Record] = json_file_reader.read_data()
# 将 2 个月份的数据合并为 1 个 list 来存储
all_data: list[Record] = jan_data + feb_data
print(all_data)
# 构建 MySQL 链接对象
conn = Connection(
host='localhost',
port=3306,
user='root',
password='666666',
autocommit=True
)
# 获得游标对象
cursor = conn.cursor()
# 选择数据库
conn.select_db("py_sql")
# 组织 SQL 语句
for record in all_data:
sql = (f"insert into orders(order_date, order_id, money, province) "
f"values('{record.date}', '{record.order_id}', '{record.money}', '{record.province}')")
# print(sql)
# 执行 SQL 语句
cursor.execute(sql)
# 关闭 MySQL 链接对象
Python 高阶技巧
1、闭包
基础概念
通过全局变量account_amount来记录余额
尽管功能实现是ok的,但是仍有问题:
- 代码在命名空间上(变量定义)不够干净、整洁
- 全局变量有被修改的风险
因此:
- 将变量定义在函数内部是行不通
- 我们需要使用闭包
在函数嵌套的前提下,内部函数使用了外部函数的变量,并且外部函数返回了内部函数,我们把这个使用外部函数变量的内部函数称为闭包。
简单闭包
示例代码:
# 简单闭包
def outer(logo):
def inner(msg):
print(f"<{logo}>{msg}<{logo}>")
return inner
fn1 = outer("黑马程序员")
fn1("welcome")
修改外部函数变量的值
示例代码:
# 使用 nonlocal 关键字修改外部函数的值
def outer(num1):
def inner(num2):
nonlocal num1
num1 += num2
print(num1)
return inner
fn = outer(10)
fn(10)
fn(20)
fn(20)
fn(20)
使用闭包实现 ATM 小案例
"""
演示 Python 的闭包特性
"""
# 使用闭包实现 ATM 小案例
def account_create(initial_account = 0):
def atm(num, deposit=True):
nonlocal initial_account
if deposit:
initial_account += num
print(f"存款, +{num}, 账户余额:{initial_account}")
else:
initial_account -= num
print(f"存款, -{num}, 账户余额:{initial_account}")
return atm
atm = account_create()
atm(100)
atm(200)
atm(100, deposit=False)
tips:
优点,使用闭包可以让我们得到:
- 无需定义全局变量即可实现通过函数,持续的访问、修改某个值
- 闭包使用的变量的所用于在函数内,难以被错误的调用修改
缺点:
- 由于内部函数持续引用外部函数的值,所以会导致这一部分内存空间不被释放,一直占用内存
2、装饰器
装饰器其实也是一种闭包, 其功能就是在不破坏目标函数原有的代码和功能的前提下,为目标函数增加新功能。
装饰器的一般写法(闭包写法)
示例代码:
# 装饰器的一般写法(闭包)
def outer(func):
def inner():
print("我睡觉了")
func()
print("我起床了")
return inner
def sleep():
import random
import time
print("睡眠中......")
time.sleep(random.randint(1, 5))
fn = outer(sleep)
fn()
定义一个闭包函数, 在闭包函数内部:
- 执行目标函数
- 并完成功能的添加
执行结果:
# 结果
我睡觉了
睡眠中......
我起床了
装饰器的语法糖写法
def outer(func):
def inner():
print("我睡觉了")
func()
print("我起床了")
return inner
@outer
def sleep():
import random
import time
print("睡眠中......")
time.sleep(random.randint(1, 5))
sleep()
使用@outer
定义在目标函数sleep之上
执行结果:
# 结果
我睡觉了
睡眠中......
我起床了
3、单例模式
某些场景下, 我们需要一个类无论获取多少次类对象,都仅仅提供一个具体的实例,用以节省创建类对象的开销和内存开销,比如某些工具类,仅需要1个实例,即可在各处使用。
这就是单例模式所要实现的效果。
单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。
在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。
- 定义:保证一个类只有一个实例,并提供一个访问它的全局访问点;
- 适用场景:当一个类只能有一个实例,而客户可以从一个众所周知的访问点访问它时。
单例的实现模式:
4、工厂模式
当需要大量创建一个类的实例的时候, 可以使用工厂模式。
即,从原生的使用类的构造去创建对象的形式迁移到,基于工厂提供的方法去创建对象的形式。
例如:由
转到
上述示例使用工厂类的get_person()方法去创建具体的类对象
优点:
- 大批量创建对象的时候有统一的入口,易于代码维护;
- 当发生修改,仅修改工厂类的创建方法即可;
- 符合现实世界的模式,即由工厂来制作产品(对象)。
示例代码:
"""
演示 设计模式之工厂模式
"""
class Person:
pass
class Worker(Person):
pass
class Student(Person):
pass
class Teacher(Person):
pass
class PersonFactory:
def get_person(self, p_type):
if p_type == 'w':
return Worker()
elif p_type == 's':
return Student()
else:
return Teacher()
pf = PersonFactory()
worker = pf.get_person('w')
stu = pf.get_person('s')
teacher = pf.get_person('t')
5、多线程并行执行概念
进程、线程
进程: 就是一个程序,运行在系统之上,那么便称之这个程序为一个运行进程,并分配进程ID方便系统管理。
线程:线程是归属于进程的,一个进程可以开启多个线程,执行不同的工作,是进程的实际工作最小单位。
进程就好比一家公司,是操作系统对程序进行运行管理的单位;
线程就好比公司的员工,进程可以有多个线程(员工),是进程实际的工作者。
操作系统中可以运行多个进程,即多任务运行;
一个进程内可以运行多个线程,即多线程运行。
tips:
进程之间是内存隔离的, 即不同的进程拥有各自的内存空间。 这就类似于不同的公司拥有不同的办公场所。
线程之间是内存共享的,线程是属于进程的,一个进程内的多个线程之间是共享这个进程所拥有的内存空间的。
这就好比,公司员工之间是共享公司的办公场所。
并行执行
并行执行的意思指的是同一时间做不同的工作。
进程之间就是并行执行的,操作系统可以同时运行好多程序,这些程序都是在并行执行。
除了进程外,线程其实也是可以并行执行的。
也就是比如一个Python程序,其实是完全可以做到:
- 一个线程在输出:你好
- 一个线程在输出:Hello
像这样一个程序在同一时间做两件乃至多件不同的事情, 我们就称之为:多线程并行执行
6、多线程编程
基本语法:
单线程:
示例代码:
"""
演示 多线程编程的使用
"""
import time
def sing():
while True:
print("我在唱歌,啦啦啦...")
time.sleep(1)
def dance():
while True:
print("我在跳舞,呱呱呱...")
time.sleep(1)
if __name__ == '__main__':
sing()
dance()
# 结果
我在唱歌,啦啦啦...
我在唱歌,啦啦啦...
我在唱歌,啦啦啦...
我在唱歌,啦啦啦...
我在唱歌,啦啦啦...
我在唱歌,啦啦啦...
我在唱歌,啦啦啦...
我在唱歌,啦啦啦...
我在唱歌,啦啦啦...
我在唱歌,啦啦啦...
我在唱歌,啦啦啦...
单方面循环 sing()
多线程:
"""
演示 多线程编程的使用
"""
import time
import threading
def sing():
while True:
print("我在唱歌,啦啦啦...")
time.sleep(1)
def dance():
while True:
print("我在跳舞,呱呱呱...")
time.sleep(1)
if __name__ == '__main__':
# 创建一个唱歌线程
sing_thread = threading.Thread(target=sing)
# 创建一个跳舞线程
dance_thread = threading.Thread(target=dance)
# 进程启动
sing_thread.start()
dance_thread.start()
# 结果
我在唱歌,啦啦啦...
我在跳舞,呱呱呱...
我在唱歌,啦啦啦...我在跳舞,呱呱呱...
我在唱歌,啦啦啦...我在跳舞,呱呱呱...
我在跳舞,呱呱呱...
我在唱歌,啦啦啦...
多线程传参:
需要传参的话可以通过:
- args参数通过元组(按参数顺序)的方式传参
- 或使用kwargs参数用字典的形式传参
示例代码:
"""
演示 多线程编程的使用
"""
import time
import threading
def sing(msg):
while True:
print(msg)
time.sleep(1)
def dance(msg):
while True:
print(msg)
time.sleep(1)
if __name__ == '__main__':
# 创建一个唱歌线程
sing_thread = threading.Thread(target=sing, args=("我要唱歌,哈哈哈",))
# 创建一个跳舞线程
dance_thread = threading.Thread(target=dance, kwargs={"msg":"我在跳舞,啦啦啦"})
# 进程启动
sing_thread.start()
dance_thread.start()
# 结果
我要唱歌,哈哈哈
我在跳舞,啦啦啦
我要唱歌,哈哈哈
我在跳舞,啦啦啦
我要唱歌,哈哈哈
我在跳舞,啦啦啦
我在跳舞,啦啦啦
我要唱歌,哈哈哈
我在跳舞,啦啦啦
我要唱歌,哈哈哈
我要唱歌,哈哈哈我在跳舞,啦啦啦
我在跳舞,啦啦啦
我要唱歌,哈哈哈
我在跳舞,啦啦啦我要唱歌,哈哈哈