前言

从文章  python学习——【第十七弹】 开始,我们开始进入python巩固篇,利用所学基础知识来做一个简单的 学生信息管理系统,温故而知新。

上篇文章 python学习——【第十八弹】我们编写了学生信息管理系统的查询功能,这篇文章实现学生信息的删除功能

python学习——【第十九弹】_删除操作


需求分析

之前的学习我们了解了python中对文件的读写操作,那么我们可以利用”写“操作的追加覆盖性,实现用于存放的学生信息的文件 ”students.txt"的删除更新。

用户可以选择按照学生ID\姓名两种删除方式,删除指定学生;

如果没有查找到指定学生信息给予用户反馈,查到则告知用户学生信息已删除;

当用户执行完毕一次删除操作后,询问用户是否再次进行删除操作,如果是则继续执行,反之退出。


思路整理

获取用户的删除选择方式,用到input()函数;

判断学生信息是否删除需要用if..else...判断语句;

执行删除操作的 继续/退出需要用到 while循环语句;

将整个删除功能放到一个函数中,用户使用该该模块直接在主函数中调用即可。


学生信息删除函数delete()的编写

首先我们需要引入 os模块,利用os.path.exists()判断存储学生信息的文件是否存在

import os
filename='../students.txt'

然后开始delete()函数的编写,结合前面的思路,我们将大体框架写出来,这里我们以用户选择ID为例

import os
filename = '../students.txt'

def delete():
    while True:
        student_id = input('请输入学生ID:')
        if student_id !='':
            if os.path.exists('filename'):
# 使用with语句执行“读”操作,将所读取的学生信息放到一个列表 student_befor中
                pass
            else:
# 如果存放学生信息的文件不存在,就返回一个空列表  student_befor=[]
                pass
# 编写一个删除标记,如果学生信息删除就为True,反之为False,默认为False
            flag = False
            #开始执行“写”操作,目的是将students.txt中和用户输入的学生ID不相符的学生信息再写入 students.txt中,完成覆盖更新
            pass
            if flag:
                print('学生信息已删除')
            else:
                print('抱歉,没有查找到该学生信息')
#询问用户是否继续进行删除操作
        ans = input('请问你还需要继续删除吗?(y/n)')
        if ans == 'y':
            continue
        else:
            break

读取学生信息

if student_id!='':
    if os.path.exists(filename):
        with open(filename,'r',encoding='utf-8')as file:
            student_befor=file.readlines()
    else:
        student_befor=[]
print(student_befor)
print(type(student_befor))

我们看写此时student_befor列表中的信息存放情况

python学习——【第十九弹】_python_02

将字符串类型的学生信息转换成字典,以便进行键值匹配

if student_befor:
          d={} #定义一个空字典
          for item in student_befor: #遍历student_befor,遍历返回的结果是字符串
             	d=dict(eval(item))  #遍历得到的字符串转换成字典
                print('这是转化而来的字典:',d)

python学习——【第十九弹】_删除操作_03

根据用户输入的学生ID匹配相关信息

if d['id']!=student_id:#如果字典中的元素的键值可以不和用户输入的学生ID相同就写入students.txt文件中;此时students.txt文件中不含有用户输入的ID所对应的学生信息
                    w_file.write(str(d)+'\n')
        			print(d)#查看删除指定学生信息后的students.txt
                else:
                    print('已删除')

python学习——【第十九弹】_字符串_04

最终代码

import os
filename='../students.txt'
def delete():
    while True:
        student_id=input('请输入您要删除的学生的ID:')
        #如果输入学生的ID,并且存储学生信息的文件存在话,就读取文件中的学生信息,并以列表的形式返回。
        if student_id!='':
            if os.path.exists(filename):
                with open(filename,'r',encoding='utf-8')as file:
                    student_befor=file.readlines()
            else:
                student_befor=[]
            #标记是否完成删除操作
            flag=False #默认值False,没有删除
            #如果student_befor返回的是True,就代表列表中有内容;空列表布尔值是False
            if student_befor:
                with open(filename,'w',encoding='utf-8')as w_file:
                    d={} #定义一个空字典
                    for item in student_befor:
                        d=dict(eval(item)) #将字符串转换为字典
                        #如果需要删除的id字符串和已有的学生id不相等的话,就将该信息写入students.txt中
                        if d['id']!=student_id:
                            w_file.write(str(d)+'\n')
                        else:
                            flag=True  #表示已删除
                    if flag:
                        print(f'ID为{student_id}的学生信息已被删除')
                    else:
                        print(f'抱歉,没有找到ID为{student_id}的学生信息')
           #如果学生信息没有录入的话,就打印出'无学生信息',并退出删除操作
            else:
                print('无学生信息')
                break
            answer=input('是否要继续删除?y/n\n')
            if answer=='y':
                continue
            else:
                break

按学生姓名修改的思路同上,这里就不做赘述了。

问题反馈

在完成“删除方式的选择”的功能时,出现了一些报错,这里记录一下报错原因,加以修改

UnboundLocalError

当我想让用户选择按照学生ID\姓名进行删除时,按照原有思路直接用 input()函数来收集用户的选择,然后进行键值匹配,发现运行后出现 UnboundLocalError 错误:

python学习——【第十九弹】_python_05

报错原因很明显,是由于变量的作用域导致的,原因如下

1. 如果在函数内部尝试给一个局部变量赋值,但该变量未被定义,则会发生UnboundLocalError。


2. 如果在函数内部尝试修改一个全局变量的值,但该变量未被声明为global,则会发生

UnboundLocalError。


3. 如果在函数内部尝试访问一个局部变量,但该变量还未被赋值,则会发生UnboundLocalError。


4. 如果在函数内部使用了与全局变量同名的变量,则会发生UnboundLocalError。


5. 如果在函数内部定义了一个和全局变量同名的变量,则必须使用global关键字声明该变量为全局变量,否则会发生UnboundLocalError。

我们看下代码:

python学习——【第十九弹】_UnboundLocalError_06

在 delete()函数中我们定义了两个变量 student_id  student_name,如果用户选择其中一种方式(学生ID或学生姓名)的话,那么另一个变量就相当于没有被声明,此时我们就需要在用户做出选择之前就在函数内部对这两个变量做出声明,即:

python学习——【第十九弹】_UnboundLocalError_07

如果将其放到函数外,函数内部需要使用global声明

python学习——【第十九弹】_删除操作_08

答非所问

先看运行结果,大家能看出哪有问题吗?没错,我明明输入的是n(结束删除操作),可是系统为什么还要我继续选择删除方式呢?经过断点调试,发现我红色框选中的if...else语句在执行中无论我输入什么都会自动忽略else的执行。

python学习——【第十九弹】_python_09

在网上查阅资料后发现,

python 中的or 语句的语法规则是:

在Python中,or是一个逻辑运算符,用于连接两个或多个条件表达式。当使用or连接的条件表达式中,只要有一个条件为真(True),整个表达式的结果就为真(True)。如果所有条件都为假(False),则整个表达式的结果为假(False)。

举个例子:

a = "hello world"
b = 1
c = False
d = 0

# 同时为真
print(a or b)  #hello world
# 先真后假
print(a or c)  #hello world
# 先假后真
print(c or a)  #hello world
#同时为假
print(c or d)  #0

而问题代码的执行并非所预期的效果,就是因为

输入 n时,对于if语句来说 or 前面的 Y 返回的是False,因此直接执行 or 后面 的 y ,此时返回的 y 为True,因此无论输入什么,都只会执行if语句块中的代码。

并且:or运算符可以连接任意数量的条件表达式,但建议不要连接过多的条件,以免影响代码的可读性。


解决方法如下:

1.   if choice in ["Y","y"]:
    	# do something
	else:
   		# do something else
        
2.  if choice == 'y' or choice == 'Y':
    	# do something
    else:
        #do something else

3.   #可以将用户输入转换为小写或大写字母并将其与小/大写的“y”进行比较,如下所示:
#把字符串所有字母都转换成小写形式,并返回转换后的字符串。
	if choice.lower() == 'y':
   		# do something
	else:
   		# do something else

    
    
4.  #把字符串所有字母都转换成大写形式,并返回转换后的字符串。
if choice.upper() == 'Y':
   		# do something
	else:
   		# do something else

python学习——【第十九弹】_UnboundLocalError_10


每篇一语

人可以休息,但不能止息。当你停下脚步的时候,别忘了别人还在奔跑。

如有不足,感谢指正!