• Python程序练习4--模拟员工信息数据库操作


    1.功能简介

    此程序模拟员工信息数据库操作,按照语法输入指令即能实现员工信息的增、删、改、查功能。

     

    2.实现方法

    • 架构:

    本程序采用python语言编写,关键在于指令的解析和执行:其中指令解析主要运用了正则表达式来高效匹配有效信息;指令执行通过一个commd_exe主执行函数和增、删、改、查4个子执行函数来实现,操作方法主要是运用面向对象方法将员工信息对象化,从而使各项操作都能方便高效实现。程序主要函数如下: 
    (1)command_exe(command) 
    指令执行主函数,根据指令第一个字段识别何种操作,并分发给相应的处理函数执行。
    (2)add(command) 
    增加员工记录函数,指令中需包含新增员工除id号以外的其他所有信息,程序执行后信息写入员工信息表最后一行,id号根据原最后一条记录的id号自增1。 
    (3)delete(command) 
    删除员工记录函数,可根据where后的条件检索需删除的记录,并从信息表中删除。 
    (4)update(command) 
    修改和更新员工记录函数,根据where后的条件检索需更新的记录,根据set后的等式修改和更新指定的信息。 
    (5)search(command) 
    查询员工记录函数,根据where后的条件查询到相应的记录,根据select后的关键字来显示记录的指定信息,如果为*显示记录的所有信息。 
    (6)verify(staff_temp,condition) 
    员工信息验证函数,传入一个对象化的员工记录和指令中where后的条件字符串,判断记录是否符合条件,符合在返回True,否则返回False。指令包含where字段的删、改、查操作会调用此函数。 
    (7)logic_cal(staff_temp,logic_exp) 
    单个逻辑表达式的运算函数,传入一个对象化的员工记录和从where条件字符串中被and、or、not分割的单个表达式,实现=,>,<,>=,<=,like等确定的一个逻辑表达式的运算,返回结果为True或False。

    • 主要操作:

    数据记录包含6个关键字:id,name,age,phone,dept,enroll_date
    指令可用的逻辑运算符:<,>,=,<=,>=,like,and,or,not
    数据库操作: 
    1.增(add to xxxx values xxxx) 
    示例:add to staff_table values Alex Li,22,13651054608,IT,2013-04-01
    2.删(delete from xxxx where xxxx) 
    示例:delete from staff_table where age<=18 and enroll_date like "2017"
    3.改(update xxxx set xxxx where xxxx
    示例: 
    update staff_table set dept="Market",age=30 where dept="IT" and phone like "189"
    4.查(select xxxx from xxxx where xxxx
    示例1: 
    select * from staff_table where age>=25 and not phone like "136" or name like "李"
    示例2: 
    select name,age,dept from db.txt where id<9 and enroll_date like "-05-"
    示例3:select * from staff_table where * #显示所有记录 

    • 使用文件:

    staff_table 
    存放员工信息表,作为模拟的数据库文件,每条记录包含id,name,age,phone,dept,enroll_date六项信息,如"1,Alex Li,22,13651054608,IT,2013-04-0"

     

    3.流程图

    4.代码

      1 #!usr/bin/env python3
      2 #_*_coding:utf-8_*_
      3 
      4 'staff infomation management module'
      5 __author__='Byron Li'
      6 
      7 '''----------------------------------------------员工信息数据库操作指令语法---------------------------------------------
      8 数据记录包含6个关键字:id,name,age,phone,dept,enroll_date
      9 指令可用的逻辑运算符:<,>,=,<=,>=,like,and,or,not
     10 1.增(add to xxxx values xxxx)
     11   示例:add to staff_table values Alex Li,22,13651054608,IT,2013-04-01  
     12 2.删(delete from xxxx where xxxx)
     13   示例:delete from staff_table where age<=18 and enroll_date like "2017"
     14 3.改(update xxxx set xxxx where xxxx)
     15   示例:update staff_table set dept="Market",age=30 where dept="IT" and phone like "189"
     16 4.查(select xxxx from xxxx where xxxx)
     17   示例1:select * from staff_table where age>=25 and not phone like "136" or name like "李"
     18   示例2:select name,age,dept from  db.txt  where id<9  and  enroll_date like "-05-"
     19   示例3:select * from staff_table where *           #显示所有记录
     20 ---------------------------------------------------------------------------------------------------------------------'''
     21 import re
     22 import os
     23 class staff(object):               #员工类
     24     def __init__(self,*args):      #员工信息初始化:从字符串列表传参赋值
     25         self.id=args[0]
     26         self.name=args[1]
     27         self.age=args[2]
     28         self.phone=args[3]
     29         self.dept=args[4]
     30         self.enroll_date=args[5]
     31         self.allinfo=','.join(args)
     32     def update(self,**kwargs):       #员工信息更新:从字典传参赋值
     33         if 'id' in kwargs:
     34             self.id=kwargs['id']
     35         if 'name' in kwargs:
     36             self.name=kwargs['name']
     37         if 'age' in kwargs:
     38             self.age = kwargs['age']
     39         if 'phone' in kwargs:
     40             self.phone=kwargs['phone']
     41         if 'dept' in kwargs:
     42             self.dept=kwargs['dept']
     43         if 'enroll_date' in kwargs:
     44             self.enroll_date = kwargs['enroll_date']
     45         self.allinfo = ','.join(map(str,[self.id, self.name, self.age, self.phone, self.dept, self.enroll_date]))
     46     def print_info(self,info):     #员工信息打印显示:传入的参数为"*"或数据记录的若干个关键字
     47         if info=='*':
     48             print(self.allinfo)
     49         else:
     50             info=info.split(',')
     51             res=[]
     52             for i in info:
     53                 if hasattr(self,i.strip()):
     54                     res.append(str(getattr(self,i.strip())))
     55             print(','.join(res))
     56 
     57 def command_exe(command):   #指令执行主函数,根据指令第一个字段识别何种操作,并分发给相应的处理函数执行
     58     command=command.strip()
     59     return {
     60         'add':add,
     61         'delete':delete,
     62         'update':update,
     63         'select':search,
     64     }.get(command.split()[0],error)(command)
     65 
     66 def error(command):        #错误提示函数,指令不合语法调用该函数报错
     67     print('33[31;1m语法错误,请重新输入!33[0m
    ')
     68 
     69 def add(command):        #增加员工记录函数
     70     command_parse=re.search(r'adds*?tos(.*?)valuess(.*)',command)    #正则表达式指令解析
     71     if(command_parse):
     72         data_file=command_parse.group(1).strip()   #数据库文件
     73         info=command_parse.group(2).strip()        #需新增的员工信息,不含id
     74         id=1                                       #新增员工id,默认为1以防数据库为空表时新增记录id取1
     75         with open(data_file, 'r+', encoding='utf-8') as fr:
     76             line=fr.readline()
     77             while(line):
     78                 if line.strip()=='':
     79                     fr.seek(fr.tell()-len(line)-2)  #定位文件最后一行(只有空字符)的开头
     80                     break
     81                 staff_temp = staff(*line.strip().split(','))     #读取的信息转换为staff对象
     82                 id = int(staff_temp.id) + 1         #末行员工id加1为新员工id
     83                 line = fr.readline()
     84             info_new=''.join([str(id),',',info])  #id与其他信息合并成完整记录
     85             fr.write(info_new)
     86             fr.write('
    ')
     87             fr.flush()
     88             print("数据库本次33[31;1m新增1条33[0m员工信息:", info_new)  #新增记录打印
     89     else:
     90         error(command)
     91 
     92 def delete(command):    #删除员工记录函数
     93     command_parse=re.search(r'deletes*?froms(.*?)wheres(.*)',command)   #指令解析
     94     if(command_parse):
     95         data_file=command_parse.group(1).strip()  #数据库文件
     96         condition=command_parse.group(2).strip()  #检索条件
     97         data_file_bak = ''.join([data_file, '.bak'])
     98         count = 0           #删除记录计数
     99         staff_list = []     #删除记录的员工对象列表
    100         with open(data_file, 'r', encoding='utf-8') as fr, 
    101                 open(data_file_bak, 'w', encoding='utf-8') as fw:
    102             for line in fr:
    103                 staff_temp = staff(*line.strip().split(','))
    104                 if (verify(staff_temp, condition)):  #验证员工信息是否符合条件
    105                     count+=1
    106                     staff_list.append(staff_temp)
    107                     continue
    108                 fw.write(staff_temp.allinfo)
    109                 fw.write('
    ')
    110             fw.flush()
    111         os.remove(data_file)
    112         os.rename(data_file_bak, data_file)
    113         print("数据库本次共33[31;1m删除%d条33[0m员工信息,如下:"%count)
    114         for staff_temp in staff_list:
    115             staff_temp.print_info('*')   #删除记录打印
    116     else:
    117         error(command)
    118 
    119 def update(command):     #修改和更新员工记录函数
    120     command_parse=re.search(r'updates(.*?)sets(.*?)wheres(.*)',command)   #指令解析
    121     if(command_parse):
    122         data_file=command_parse.group(1).strip()     #数据库文件
    123         info=command_parse.group(2).strip()          #需更新的信息
    124         condition=command_parse.group(3).strip()     #检索条件
    125         data_file_bak=''.join([data_file,'.bak'])
    126 
    127         info = ''.join(['{', info.replace('=', ':'), '}'])   #将需更新的信息按字典格式修饰字符串
    128         info = eval(re.sub(r'(w+)s*:', r'"1":', info))    #将字符串进一步修饰最终转化成字典
    129         count = 0
    130         staff_list = []
    131         with open(data_file,'r',encoding='utf-8') as fr,
    132                 open(data_file_bak,'w',encoding='utf-8') as fw:
    133             for line in fr:
    134                 staff_temp=staff(*line.strip().split(','))
    135                 if(verify(staff_temp,condition)):    #验证员工信息是否符合条件
    136                     staff_temp.update(**info)        #调用员工对象成员函数更新信息
    137                     count += 1
    138                     staff_list.append(staff_temp)
    139                 fw.write(staff_temp.allinfo)
    140                 fw.write('
    ')
    141             fw.flush()
    142         os.remove(data_file)
    143         os.rename(data_file_bak,data_file)
    144         print("数据库本次共33[31;1m更新%d条33[0m员工信息,如下:"%count)
    145         for staff_temp in staff_list:
    146             staff_temp.print_info('*')  #更新记录打印
    147     else:
    148         error(command)
    149 
    150 def search(command):        #查询员工记录函数
    151     command_parse=re.search(r'selects(.*?)froms(.*?)wheres(.*)',command)   #指令解析
    152     if(command_parse):
    153         info=command_parse.group(1).strip()         #检索结束后需显示的信息,"*"为显示整体记录
    154         data_file=command_parse.group(2).strip()    #数据库文件
    155         condition=command_parse.group(3).strip()    #检索条件
    156         count = 0
    157         staff_list = []
    158         with open(data_file,'r',encoding='utf-8') as fr:
    159             for line in fr:
    160                 staff_temp=staff(*line.strip().split(','))
    161                 if(verify(staff_temp,condition)):   #验证员工信息是否符合条件
    162                     count += 1
    163                     staff_list.append(staff_temp)
    164         print("数据库本次共33[31;1m查询到%d条33[0m员工信息,如下:" % count)
    165         for staff_temp in staff_list:
    166             staff_temp.print_info(info)     #查询记录打印
    167     else:
    168         error(command)
    169 
    170 def verify(staff_temp,condition):             #员工信息验证函数,传入一个员工对象和条件字符串
    171     if condition.strip()=='*':return True   #如果条件为'*',即所有记录都满足条件
    172     condition_list=condition.split()           #检索条件字符串转列表
    173     if len(condition_list)==0:return False
    174     logic_str=['and','or','not']    #逻辑运算字符串 且、或、非
    175     logic_exp=[]                  #单个条件的逻辑表达式组成的列表,形如[‘age',' ','>','=',20] 或 [‘dept',' ','like',' ','HR']
    176     logic_list=[]                 #每个条件的表达式的计算结果再重组后的列表,形如 [‘True','and','False','or','not','False']
    177     for i in condition_list:
    178         if i in logic_str:
    179             if(len(logic_exp)!=0):
    180                 logic_list.append(str(logic_cal(staff_temp,logic_exp)))  #逻辑表达式计算并将返回的True或False转化成字符串添加到列表
    181             logic_list.append(i)
    182             logic_exp=[]
    183         else:
    184             logic_exp.append(i)
    185     logic_list.append(str(logic_cal(staff_temp, logic_exp)))
    186     return eval(' '.join(logic_list))    #列表转化成数学表达式完成所有条件的综合逻辑运算,结果为True或False
    187 
    188 def logic_cal(staff_temp,logic_exp):   #单个逻辑表达式的运算函数
    189     logic_exp = re.search('(.+?)([=<>]{1,2}|like)(.+)',''.join(logic_exp))  #表达式列表优化成三个元素,形如[‘age','>=',20] 或 [‘dept','like','HR']
    190     if(logic_exp):
    191         logic_exp=list(logic_exp.group(1,2,3))
    192         if(hasattr(staff_temp,logic_exp[0])):
    193             logic_exp[0] = getattr(staff_temp,logic_exp[0])
    194         else:
    195             return False
    196         if logic_exp[1]=='=':        #指令中的'='转化成程序中相等判别的"=="
    197             logic_exp[1]='=='
    198         if logic_exp[1]=='like':     #运算符为like的表达式运算
    199             return re.search(logic_exp[2].strip("'").strip('"'),logic_exp[0]) and True
    200         elif(logic_exp[0].isdigit() and logic_exp[2].isdigit()):   #两头为数字的运算,直接eval函数转数学表达式
    201             return eval(''.join(logic_exp))
    202         elif(logic_exp[1]=='=='):    #非数字的运算,即字符串运算,此时逻辑符只可能是‘=’,若用eval函数则字符串会转成无定义变量而无法计算,所以拿出来单独用"=="直接计算
    203             return logic_exp[0]==logic_exp[2].strip("'").strip('"')   #字符串相等判别,同时消除指令中字符串引号的影响,即输引号会比记录中的字符串多一层引号
    204         else:          #其他不合语法的条件格式输出直接返回False
    205             return False
    206     else:
    207         return False
    208 
    209 if __name__=='__main__':     #主函数,数据库指令输入和执行
    210     while(True):
    211         command=input("请按语法输入数据库操作指令:")    #指令输入
    212         if command=='exit':
    213             print("数据库操作结束,成功退出!".center(50, '*'))
    214             break
    215         command_exe(command)        #指令执行
    View Code
  • 相关阅读:
    安装CentOS7
    gitlab的CI/CD实现
    如何实现7*24小时灵活发布?阿里技术团队这么做
    架构整洁之道, 看这一篇就够了!
    什么是数据湖?有什么用?
    2020 云原生 7 大趋势预测
    饿了么交易系统 5 年演化史
    ajax 传参数 数组 会加上中括号
    文件下载
    数组常用方法
  • 原文地址:https://www.cnblogs.com/byron-li/p/7711623.html
Copyright © 2020-2023  润新知