文章目录
前言
简单总结异常,面向对象,数据库连接,进程和线程等学习
一、异常、面向对象
异常是程序错误后如何处理,直观理解即程序错误程序不会直接中断,而是以设置的代码执行程序,解决或者跳过可能出现的问题,增强程序的稳定性。通常在异常的库中,封装了各种异常类型,我们可以抛出这些异常到日志文件中,帮助定位程序错误,解决代码不完缮的问题。
1.异常的简单使用
i = 0
while True:
# 可能出现异常的代码块
try:
age = int(input("请输入年龄:"))
# 抛出异常
except ValueError:
print("请输入数字!")
# 无异常执行的代码块
else:
break
#有无异常都执行的代码块
finally:
i +=1
print(f"第{i}次输入")
其中,可能出现异常的代码段为输入,可能出现的异常为输入了非数字类型,导致不能进行int()强制转化,except用于抛出这种错误的可能,检测到了这种错误之后,进行print()打印,提醒用户规范输入。一直没有异常才进行else之后的代码。finally下的代码块,有无异常都执行。
2.面向对象
对象是一种抽象概念,其具有具体的属性和功能。例如把人抽象为一个对象,眼睛、鼻子、嘴巴等就是对象的属性,走路、吃饭等就是对象的功能,即方法。适用对象可以直接用对象名,通常采用实例化对象。即,对象是一个抽象的整理,实例即一个真实的个体。对象内的属性和方法是个体所共有的。在python中用类来描述对象这个概念。
"""
家具类
属性: 类型
面积
方法: init: 设置属性
str: 打印对象
房子类
属性: 地址
面积
剩余面积
方法: init: 设置属性
str: 打印对象
添加家具: 能添加就添加, 否则提示失败
"""
class Item(object):
def __init__(self, type='', area=0):
self.type = type
self.area = area
def __str__(self):
return f'家具是{self.type},面积为{self.area}'
class House(object):
def __init__(self, address='', area=90, item=[]):
self.address = address
self.area = area
self.item = item
self.free_area = area
def __str__(self):
list_item = [item.type for item in self.item]
item_str = '、'.join(list_item)
return f'房子地址是{self.address},房子面积为{self.area}平方米,剩余空间{self.free_area}平方米,添加的家具为{item_str}'
def add_item(self, item):
if self.free_area > item.area:
print("添加成功")
self.free_area = self.free_area - item.area
self.item.append(item)
else:
print("没空间了")
house = House('东北', 50)
item = Item('桌子', 10)
item2 = Item('椅子', 1)
house.add_item(item)
house.add_item(item2)
面向对象的特点有四个:抽象、继承、封装、多态。抽象即类的概念。继承则是子类继承父类的共有方法和属性,这些方法和属性子类可直接调用,但子类想扩展父类的功能,需要对父类进行重写。封装类中的一切都是封装起来的,便于代码的重用。多态,同名方法会根据实例化类对象自动选择对象的方法。
# 类: 由属性(变量) 方法(函数)
# 类名: 地瓜类 SweetPotato
# 属性:1. 状态 state 默认生的 --> 初始化方法中进行设置
# 2. 烧烤总时间 cooked_time 默认0 --> 初始化方法中进行设置
class SweetPotato(object):
# __init__:进行初始化的属性设置
def __init__(self, state='生的', cooked_time=0, condiments=''):
self.state = state
self.cooked_time = cooked_time
self.condiments = condiments
# 方法: 1.烧烤cook(self, time):
def cook(self, time):
# 累加时间
self.cooked_time += time
# 根据累加后的时间进行判断, 更改状态
if 0 <= self.cooked_time < 3:
self.state = "生的"
elif 3 <= self.cooked_time < 6:
self.state = "半生不熟"
elif 6 <= self.cooked_time < 8:
self.state = "熟了"
elif 8 <= self.cooked_time:
self.state = "烤糊了"
# 添加调料方法
def add_condiments(self, condiments):
self.condiments += condiments
# __str__:示地瓜的状态和烧烤的总时间
def __str__(self):
return f'{self.state},一共烤了{self.cooked_time}分钟,添加了{self.condiments}'
if __name__ == '__main__':
sp = SweetPotato()
sp.cook(3)
sp.cook(2)
sp.cook(1)
sp.add_condiments("椒盐,辣椒面")
print(sp)
3.类的基本使用
在类中,常用有:初始话方法、返回值方法、继承、静态方法、重写父类方法等。
class Star(object):
def __init__(self, name, films):
self.name = name
self.films = films
def __str__(self):
return f'{self.name}是要成为{self.films}的男人'
star = Star('路飞', '海贼王')
print(star)
类的继承、私有变量获取与修改
class People(object):
def __init__(self):
self.__name = "小明"
self.__age = "18"
# 2.提供__str__方法,返回姓名和年龄信息
def __str__(self):
return f"姓名{self.__name},年龄{self.__age}"
# 3.将类中的姓名和年龄私有化.
# 4.提供获取私有属性的方法.
def get_param(self, age):
# 6.设置年龄时限制范围(0 - 100).
if 0 < age < 100:
self.__set_param()
self.__age = age
print(f"{self.__name},{self.__age}")
else:
print("请输入1-100")
def __set_param(self):
self.__name = "小红"
people = People()
print(people)
people.get_param(20)
print(people)
类属性、类方法、静态方法
# 定义一个Animal类(动物类),拥有
# 公有类属性name"动物大家族",私有类属性leg"四条腿"
# 定义类Cat(),继承自Animal。
# 初始化名字为波斯猫
# 定义方法play,打印“xxx在玩耍” xxx表示名字
# 增加静态方法run,打印“动物们跑起来了”
# 增加类方法eat,打印“xxx在吃饭”
# 打印cat对象的name
class Animal(object):
name = "动物大家族"
__leg = "四条腿"
class Cat(Animal):
def __init__(self):
self.name = "波斯猫"
def paly(self):
print(f"{self.name}在玩耍。")
@staticmethod
def run():
print("动物们跑起来了")
@classmethod
def eat(cls):
print(f"{cls.name}在吃饭")
cat = Cat()
cat.paly()
cat.run()
print(cat.name)
Cat.eat()
print(Cat.name)
4.自定义异常
class ErrorAge(Exception):
def __init__(self):
super(ErrorAge, self).__init__()
self.min = 0
self.max = 100
def __str__(self):
return f"请输入{self.min}-{self.max}!"
try:
num = int(input())
if num < 0 or num > 100:
raise ErrorAge()
except (ErrorAge, ValueError) as e:
print("请输入1-100的数字!")
二、mysql数据库
1.引入库
这里使用的常规模块mysql
import mysql
2.读入数据
初始话连接信息,这是mysql.connector.connect的帮助文档,其会返回一个数据库连接对象,通常以关键字参数传参
def connect(*args, **kwargs):
"""Create or get a MySQL connection object
In its simpliest form, Connect() will open a connection to a
MySQL server and return a MySQLConnection object.
When any connection pooling arguments are given, for example pool_name
or pool_size, a pool is created or a previously one is used to return
a PooledMySQLConnection.
Returns MySQLConnection or PooledMySQLConnection.
"""
设定连接信息,定义连接方法,抛出连接异常,返回连接对象。
host = '127.0.0.1'
user = 'root'
port = 3306
password = 'password'
database = 'DATABASE'
table = 'table'
def connect_mysql(host, user, password, port, database):
try:
connection = mysql.connector.connect(host=host, user=user, password=password, port=port, database=database)
except Exception as e:
print(f"数据库连接失败!{e}")
sys.exit()
else:
return connection
连接成功后可通过连接对象创建游标,执行sql,获取执行结果,为[(1, ‘张三’, 18, ‘13523456789’)]列表嵌套元组
def select_user():
conn = connect_mysql(host, user, password, port, database)
SQL = "SELECT * FROM {0};".format(table)
curses = conn.cursor()
curses.execute(SQL)
data = curses.fetchall()
print(data)
curses.close()
conn.close()
return data
执行不同的sql用不同的cursor()对象,执行完毕获取数据,写入数据库conn.commit(),关闭游标对象,所有sql执行完毕,关闭数据库连接对象conn.close()。
注意,动态sql拼装利用format格式化
SQL = "SELECT * FROM {0};".format(table)
三、进程、线程
1.并发、并行
并发:CPU在一段时间内交替执行多个任务
并行:CPU在一段时间内只执行一个任务,利用多个CPU完成执行多个任务功能
2.进程、线程
进程是计算机任务的最小单位,每一个任务都是一个进程。线程是CPU调度的最小单位。每个进程最少有一个线程,线程依赖进程存在。
进程(并行)运行效率高,耗费资源大,不可共享全局变量,多进程任务执行稳定,可调用多核CPU。
线程(并发)相比进程运行效率低,执行稳定性相比进程低,可共享全局变量,只能调用单核CPU,执行无序。
资源竞争–>互斥锁,互斥锁可能产生死锁
# 什么是互斥锁? 说出互斥锁的应用场景及优缺点.
# 互斥锁:
"""为保证共享数据操作的完整性, threading模块给我们提供了一个Lock类, 我们把这个类创建的对象对
应于一个可称为"互斥锁" 的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象."""
# 互斥锁应用场景:
"""互斥锁可用于多线程中有可能产生共享数据(如全局变量)竞争的场景."""
# 优点:
"""避免资源竞争"""
# 缺点:
"""1.阻止了多线程并发执行,包含锁的某段代码实际上只能以单线程模式执行,效率就大大地下降了;
2.容易造成死锁"""
# 什么是死锁?怎样避免死锁?
"""死锁: 在两个或多个线程中,如果每个线程锁定了其他线程试图锁定的资源,此时会造成这些线程永久阻塞,
这个现象就叫死锁.
避免死锁: 在设计程序时, 尽量减少资源竞争, 无法避免资源竞争时, 各个线程及时释放锁定的资源."""
3.创建进程和线程、互斥锁
创建进程,参数target=“函数名”(必填),args=(5,)元组变量参数,kwargs={“name”:“张三”},字典变量参数,daemon = True,默认False,守护进程,开起则跟主进程一起结束。默认则主进程等待其结束再关闭所有进程。
# 引用
import multiprocessing
import threading
# 创建进程
process_name = multiprocessing.Process(target=process, name="进程1")
num_process = multiprocessing.Process(target=num_pro, name="进程2", args=(4,))
# 进程开始
process_name.start()
num_process.start()
# 阻塞进程,即进程执行结束才进程下个进程的执行
num_process.join()
# 创建线程
num_process = threading.Thread(target=print_num)
str_process = threading.Thread(target=print_str)
num_process.start()
str_process.start()
# 互斥锁
# 简历锁对象
lock1 = threading.Lock()
# 上锁
lock1.acquire()
# 解锁
lock1.release()
简单应用
# 1.开辟两个子进程
# 2.子进程1设置为死循环, 每隔1秒打印一次"进程信息"
# 3.子进程2接收一个整数类型参数, 进程2循环的次数即为传入的整形数字, 每个1秒循环一次
# 4.子进程2结束的时候, 子进程1也跟着结束
import multiprocessing
import time
def process():
while True:
print(os.getpid())
time.sleep(1)
def num_pro(num):
for i in range(num):
print(os.getpid())
time.sleep(1)
if __name__ == '__main__':
process_name = multiprocessing.Process(target=process, name="进程1")
num_process = multiprocessing.Process(target=num_pro, name="进程2", args=(4,))
process_name.daemon = True
process_name.start()
num_process.start()
num_process.join()
# 创建两个线程,其中一个输出1-52,另外一个输出A-Z。
# 输出格式要求:
"""
12A
34B
56C
...
5152Z
"""
import threading
lock1 = threading.Lock()
lock2 = threading.Lock()
def print_num():
for i in range(1, 52, 2):
lock2.acquire()
print(f"{i}{i + 1}", end='')
lock1.release()
def print_str():
for i in range(65, 91):
lock1.acquire()
print(chr(i))
lock2.release()
if __name__ == '__main__':
num_process = threading.Thread(target=print_num)
str_process = threading.Thread(target=print_str)
lock1.acquire()
num_process.start()
str_process.start()
总结
学生信息管理系统文件版,利用多线程解决tkinter打开文件卡顿,上篇已改。
学生信息管理系统数据库版:
# 引用mysql连接模块,数据库连接文件
import mysql_connection
from mysql_connection import conn, table, disconnect_mysql
# 自定义抛出电话长度异常
class PhoneNum(Exception):
def __init__(self):
# 调用父类异常
super(PhoneNum, self).__init__()
# 设定最大长度
self.num = 11
def __str__(self):
# 返回内容
return f"电话长度限制{self.num}位"
# 学生功能类
class Student(object):
# 初始化学生信息
def __init__(self, name="admin", age=18, tel='12345'):
self.name = name
self.age = age
self.tel = tel
# 静态方法,检测年龄是否合法
@staticmethod
def int_age_error():
# 循环失败的输入
while True:
try:
age = int(input("请输入年龄:"))
except ValueError:
print("请输入数字!")
else:
return age
# 静态方法,检测电弧是否合法
@staticmethod
def phone_num():
# 循环失败的输入
while True:
try:
user_tel = input("请输入电话:")
if len(user_tel) != 11:
raise PhoneNum()
else:
return user_tel
except PhoneNum as e:
print(f"请输入数字,{e}")
# 查询所有学生信息
def check_user(self):
# 获取数据库表数据
data = mysql_connection.select_user()
# 格式化打印
print("ID\t\t姓名\t\t年龄\t\t电话")
# 遍历表数据
for i, user_tuple in enumerate(data):
for j in range(len(user_tuple)):
# 打印表内容
print(user_tuple[j], end="\t\t")
print()
print()
# 查询指定学生信息
def find_user(self):
user_name = input("请输入姓名:")
# 验证电话长度
user_tel = self.phone_num()
# 拼装sql
SQL = "SELECT * FROM {0} WHERE name='{1}' AND tel='{2}';".format(table, user_name, user_tel)
try:
# 执行sql
curses = conn.cursor()
curses.execute(SQL)
# 获取数据
data = curses.fetchall()
# 关闭临时游标
curses.close()
except Exception as e:
print(e)
else:
# 判断是查询结果是否有数据
if len(data) > 0:
# 格式化输出
print("ID\t\t姓名\t\t年龄\t\t电话")
# 遍历数据
for i, user_tuple in enumerate(data):
for j in range(len(user_tuple)):
print(user_tuple[j], end="\t\t")
print()
else:
print("查无此人")
print()
# 添加学生信息
def add_user(self):
# 获取数据库表数据
data = mysql_connection.select_user()
# 验证电话长度
user_tel = self.phone_num()
# 遍历表数据,验证信息是否存在
for i, user_tuple in enumerate(data):
if user_tuple[len(user_tuple) - 1] == user_tel:
print("用户已存在")
break
else:
user_name = input("请输入姓名:")
# 验证年龄是否纯数字
user_age = self.int_age_error()
# 拼装sql
SQL1 = "INSERT INTO {0}(name,age,tel) VALUES('{1}',{2},'{3}');".format(table, user_name, user_age, user_tel)
try:
# 执行sql
curses1 = mysql_connection.conn.cursor()
curses1.execute(SQL1)
except Exception as e:
print(e)
else:
# 写入数据
conn.commit()
# 关闭临时游标
curses1.close()
print("添加成功!")
# self.check_user()
# 删除学生信息
def remove_user(self):
# 获取表数据
data = mysql_connection.select_user()
# 验证电话长度
user_tel = self.phone_num()
# 遍历数据信息
for i, user_tuple in enumerate(data):
if user_tuple[len(user_tuple) - 1] == user_tel:
user_name = input("请输入姓名:")
# 拼装sql
SQL1 = "DELETE FROM {0} WHERE name = '{1}' AND tel = '{2}';".format(table, user_name, user_tel)
try:
# 执行sql
curses1 = conn.cursor()
curses1.execute(SQL1)
except Exception as e:
print(e)
else:
# 写入数据
conn.commit()
# 关闭临时游标
curses1.close()
print("删除成功!")
break
else:
print("查无此人!")
# 修改学生信息
def change_user(self):
# 获取数据库表数据
data = mysql_connection.select_user()
user_tel = self.phone_num()
# 遍历表数据,匹配学生信息
for i, user_tuple in enumerate(data):
if user_tuple[len(user_tuple) - 1] == user_tel:
print("请输入要更改的信息:")
new_user_name = input("请输入姓名:")
# 调用静态方法,验证输入年龄是否合法
new_user_age = self.int_age_error()
new_user_tel = self.phone_num()
# 更新数据库内容
SQL1 = "UPDATE {0} SET name = '{1}',age = {2},tel = '{3}' WHERE tel = '{4}';".format(table,
new_user_name,
new_user_age,
new_user_tel,
user_tel)
try:
# 创建临时游标
curses1 = conn.cursor()
# 执行sql
curses1.execute(SQL1)
except Exception as e:
print(e)
else:
# 写入数据库
conn.commit()
# 关闭游标
curses1.close()
print("修改成功!")
break
else:
print("查无此人!")
# 关闭数据库连接
def save_data(self):
disconnect_mysql()
class Start(object):
# 静态方法展示菜单
@staticmethod
def show_menu():
print('=' * 20)
print("=1、查询所有用户信息!")
print("=2、查询指定用户信息!")
print("=3、添加用户信息!")
print("=4、删除用户信息!")
print("=5、修改用户信息!")
print("=6、退出系统!")
print('=' * 20)
def start(self, student):
while True:
# 展示菜单
self.show_menu()
# 抛出int()强制转化不合法异常
try:
command = int(input("请选择相应的功能:"))
except ValueError:
print("请输入数字!")
else:
if command == 1:
student.check_user()
elif command == 2:
student.find_user()
elif command == 3:
student.add_user()
elif command == 4:
student.remove_user()
elif command == 5:
student.change_user()
elif command == 6:
student.save_data()
break
else:
print("请重新输入1-6!")
if __name__ == '__main__':
# 定义学生对象
student = Student()
# 定义系统开始对象
star = Start()
# 将学生对象以参数传递开始方法中
star.start(student)
mysql_connection.py
import sys
import mysql.connector
# 初始化数据库连接
host = '127.0.0.1'
user = 'root'
port = 3306
password = 'password'
database = 'DATABASE'
table = 'table'
def connect_mysql(host, user, password, port, database):
try:
connection = mysql.connector.connect(host=host, user=user, password=password, port=port, database=database)
except Exception as e:
print(f"数据库连接失败!{e}")
sys.exit()
else:
return connection
def select_user():
SQL = "SELECT * FROM {0};".format(table)
curses = conn.cursor()
curses.execute(SQL)
data = curses.fetchall()
print(data)
curses.close()
return data
def disconnect_mysql():
conn.close()
if __name__ == '__main__':
conn = connect_mysql(host, user, password, port, database)
学生管理系统对象版(可修改为多线程,利用TK打开文件获取文件路径,上篇已有方法,此片未作更改):
# include utf-8
import os
# 自定义抛出电话长度异常
class PhoneNum(Exception):
def __init__(self):
# 调用父类异常
super(PhoneNum, self).__init__()
# 设定最大长度
self.num = 11
def __str__(self):
# 返回内容
return f"电话长度限制{self.num}位"
class Student(object):
def __init__(self, name='', age=0, tel=''):
self.name = name
self.age = age
self.tel = tel
def __str__(self):
return {"name": self.name, "age": self.age, "tel": self.tel}
def to_list(self):
return {"name": self.name, "age": self.age, "tel": self.tel}
class System(object):
# 初始化对象属性
def __init__(self, file_name='user.db'):
self.file_name = file_name
self.obj_user_list = []
# 加载数据
def load_data(self):
# 文件存在则将文件内容处理为对象列表
if os.path.exists(self.file_name):
with open(self.file_name, 'r', encoding='utf-8') as file:
# 处理文件内容为list类型
content = file.read()
# 判断文件是否为空
if content:
content = eval(content)
# 遍历列表将列表中的字典转化成Student类的对象
self.obj_user_list = [Student(user_dict["name"], user_dict["age"], user_dict["tel"]) for user_dict
in content]
else:
self.obj_user_list = [Student(user_dict["name"], user_dict["age"], user_dict["tel"]) for user_dict
in content]
# 静态方法,不使用self或者cls对象可以定义为静态
@staticmethod
def show_menu():
print('=' * 20)
print("=1、查询所有用户信息!")
print("=2、查询指定用户信息!")
print("=3、添加用户信息!")
print("=4、删除用户信息!")
print("=5、修改用户信息!")
print("=6、退出系统!")
print('=' * 20)
# 静态方法,检测年龄是否合法
@staticmethod
def int_age_error():
# 循环失败的输入
while True:
try:
age = int(input("请输入年龄:"))
except ValueError:
print("请输入数字!")
else:
return age
# 静态方法,检测电弧是否合法
@staticmethod
def phone_num():
# 循环失败的输入
while True:
try:
user_tel = input("请输入电话:")
if len(user_tel) != 11:
raise PhoneNum()
else:
return user_tel
except PhoneNum as e:
print(f"请输入数字,{e}")
# 系统开始
def start(self):
# 加载数据,只能加载一次
self.load_data()
while True:
self.show_menu()
# 抛出异常,可以将e加入日志文件
try:
command = int(input("请输入功能数字:"))
except Exception as e:
print("输入错误,请输入1-6!", e)
else:
if command == 1:
self.check_user()
elif command == 2:
self.find_user()
elif command == 3:
self.add_user()
elif command == 4:
self.remove_user()
elif command == 5:
self.change_user()
elif command == 6:
self.save_data()
break
else:
print("输入有误,请重新输入!")
# 查询所有学生信息
def check_user(self):
# 制表
print("序号\t\t姓名\t\t年龄\t\t电话")
for i, user_obj in enumerate(self.obj_user_list):
print(f"{i + 1}\t\t{user_obj.name}\t{user_obj.age}\t\t{user_obj.tel}")
# 查询指定学生信息
def find_user(self):
user_tel = self.phone_num()
for i, user_obj in enumerate(self.obj_user_list):
if user_obj.tel == user_tel:
print("序号\t\t姓名\t\t年龄\t\t电话")
print(f"{i + 1}\t\t{user_obj.name}\t\t{user_obj.age}\t\t{user_obj.tel}")
break
else:
print("查无此人!")
# 添加学生信息
def add_user(self):
while True:
user_tel = self.phone_num()
for user_obj in self.obj_user_list:
if user_obj.tel == user_tel:
print("用户已存在!请重新输入!")
break
else:
user_age = self.int_age_error()
user_name = input("请输入姓名:")
# 将学生信息转化为Student对象加入对象列表
self.obj_user_list.append(Student(user_name, user_age, user_tel))
print("添加成功!")
break
# 删除学生信息,删除其对象
def remove_user(self):
user_tel = self.phone_num()
for user_obj in self.obj_user_list:
if user_obj.tel == user_tel:
self.obj_user_list.remove(user_obj)
print("删除成功!")
break
else:
print("查无此人!")
# 修改学生信息,修改对象信息
def change_user(self):
user_tel = self.phone_num()
for i, user_obj in enumerate(self.obj_user_list):
if user_obj.tel == user_tel:
print("请输入要更改的信息:")
user_name = input("请输入姓名:")
# 调用静态方法,验证输入年龄是否合法
user_age = self.int_age_error()
user_tel = self.phone_num()
user_obj.name, user_obj.age, user_obj.tel = user_name, user_age, user_tel
print("修改成功!")
break
else:
print("查无此人!")
# 保存对象信息,将对象转化成列表,转化成string写入文件
def save_data(self):
with open(self.file_name, 'w', encoding="utf-8") as file:
temp_list = [user_obj.to_list() for user_obj in self.obj_user_list]
file.write(str(temp_list))
print("保存成功,欢迎下次使用!")
if __name__ == '__main__':
sys = System()
sys.start()
写在最后
至此,python基础的web内容学习告一段落,毕竟python写后台的话:那不就是脱裤子放屁,多此一举吗。
所以,后面开始数据分析和Java的学习,基础内容还需多多练习,欢迎一起学习、讨论。说实话,进程、线程那一块还是有些懵逼,大致理解了,但体现不在已有的知识面上,还需努力。
光阴似水,人生逆旅矣。