基於Python的課堂點名器V3

前言

在課堂點名器V2的基礎上,我們又有了更高的要求。

需求分析

課堂點名器V3的大致需求如下:
在這裏插入圖片描述下面就說說自己看到這個大致需求後,腦子裏的初步想法。

因爲思路很難一下理清,我先闡述自己得出的結論

我們的目的:輸入是學生名單的csv文件,輸出的是四大名單並且要保存在四個csv文件中。
判別方法:有兩次點名,課前點一次(後面叫第一次點名)和課後點名(第二次點名);四個輸出的數據判定如下:

  • 遲到判定:第一次點名不在就是遲到
  • 請假判定:第一次點名輸出已請假
  • 早退判定:第一次點名在,但是第二次點名不在
  • 曠課判定:第一次和第二次點名都不在

然後,第一次點名得出遲到名單和請假名單,第二次點名得出早退名單,然後曠課名單經過遲到名單和早退名單的交運算得出。

或許有人會說,這個結果和需求有些不同。確實有些不同,但是程序在不考慮換顯示界面的話(GUI等界面),無法在調試窗口那裏實時顯示出四種名單(個人認爲),肯定是兩次點名結束才顯示出來最後的名單,那麼,我們只要確保最終的名單是符合需求的就行了,判斷過程可以怎麼方便怎麼來。

下面我就放一些自己思考過程中的想法
在這裏插入圖片描述在這裏插入圖片描述

在這裏插入圖片描述當然,上面這三張已經是自己第二次思考過程了。下面再給些自己第一次思考的過程(你們可能看不懂)
在這裏插入圖片描述(下面這張是我一開始打算用tkinter來寫GUI的點名器所想的東西)
在這裏插入圖片描述
雖然都是很累贅的東西,但畢竟是自己所想,也給出來看看,自己第一次自己獨立搞一個大程序,想法方面還是很稚嫩,萬一有個大佬看我這樣,來指導我呢 ~ ~

全部代碼(講解就放註釋裏面了)

# 點名器V3
import csv
import random

# 規定的一些常量
student_late = []   # 存儲遲到名單
students_late = []   # 遲到錄入名單 這種形式[[姓名, 學號], [], [], ....]
# student_absence = []   # 存儲曠課名單(不需要,因爲absence這個表是通過late和early交運算得到的)
students_absence = []    # 曠課錄入名單 這種形式[[姓名, 學號], [], [], ....]
student_sick = []   # 存儲請假名單
students_sick = []   # 請假錄入名單 這種形式[[姓名, 學號], [], [], ....]
student_early = []   # 存儲早退名單
students_early = []   # 早退錄入名單 這種形式[[姓名, 學號], [], [], ....]


###
# 功能:讀入csv文件學生名單
# 輸入:文件名(string)
# 返回值:學生全部信息(dict),學生名單(list)
###
def file_in(file_name):
    students_info = {}
    students_name = []
    # open()函數讀入文件
    with open(file_name, newline='') as info:
        reader = csv.reader(info)
        for row in reader:
            students_info[row[0]] = row[1]
            students_name.append(row[0])
    return students_info, students_name


###
# 功能:產生隨機學生名單
# 輸入:學生名單(list)
# 返回值:打亂的學生名單(list)
###
def new_list(students_name):
    student_upset_name = random.sample(students_name, len(students_name))
    return student_upset_name


###
# 功能:完成點名器的初始化,整合了new_list()和file_in()兩個函數
# 輸入:學生名單(list)
# 返回值:學生信息(dict)和打亂的學生名單(list)
###
def dmq_init(file_name):
    student_info = file_in(file_name)[0]
    # print(students_wg_dict)
    student_upset_name = new_list(file_in(file_name)[1])
    # print(students_wg_list)
    return student_info, student_upset_name


###
# 功能:第一次點名,更新請假名單和遲到名單
# 輸入:打亂的學生名單(list)
# 返回值:None
###
def dmq_dm(student_upset_name):
    student_dm_wrong = []
    print('課程即將開始!開始第一次點名!\n')
    for name in student_upset_name:
        temp = input(name + "到了嗎?(輸入到或沒到,請假輸入已請假)")
        if temp == "到":
            continue
        elif temp == "沒到":
            student_late.append(name)
        elif temp == '已請假':
            student_sick.append(name)
        else:
            student_dm_wrong.append(name)
            print("請按要求輸入!該名字被放置最後點名。")
    if student_dm_wrong:
        for name in student_dm_wrong:
            temp = input(name + "到了嗎?(輸入到或沒到,請假輸入已請假)")
            if temp == "到":
                continue
            elif temp == "沒到":
                student_late.append(name)
            elif temp == '已請假':
                student_sick.append(name)
            else:
                print("仍然未按照要求輸入!算入遲到名單!")
                student_late.append(name)


###
# 功能:遲到名單的寫入和輸出
# 輸入:遲到學生名單(list)和學生全部信息(dict)以及一行的顯示數量
# 返回值:None
###
def dmq_file_in_late(late_list, student_info, num):
    # 向 遲到錄入名單 加入信息
    for name in late_list:
        students_late.append([name, student_info[name]])
    # 輸出 遲到錄入名單
    print_info('遲到', students_late, num)
    # 寫入 遲到錄入名單
    with open("late_students_info.csv", "w", newline="") as f_in:
        file_writer = csv.writer(f_in, quotechar='|', quoting=csv.QUOTE_MINIMAL)
        for info in students_late:
            file_writer.writerow(info)
    print("\n已導出遲到學生名單!文件位置位於當前目錄下late_students_info.csv")


###
# 功能:請假名單的寫入和輸出
# 輸入:請假學生名單(list)和學生全部信息(dict)以及一行的顯示數量
# 返回值:None
###
def dmq_file_in_sick(sick_list, student_info, num):
    # dmq_file_in_sick()、dmq_file_in_early()和dmq_file_in_absence()都是一個原理,註釋參照dmq_file_in_late()
    for name in sick_list:
        students_sick.append([name, student_info[name]])
    print_info('請假', students_sick, num)
    with open("sick_students_info.csv", "w", newline="") as f_in:
        file_writer = csv.writer(f_in, quotechar='|', quoting=csv.QUOTE_MINIMAL)
        for info in students_sick:
            file_writer.writerow(info)
    print("\n已導出請假學生名單!文件位置位於當前目錄下sick_students_info.csv")


###
# 功能:早退名單的寫入和輸出
# 輸入:早退學生名單(list)和學生全部信息(dict)以及一行的顯示數量
# 返回值:None
###
def dmq_file_in_early(early_list, student_info, num):
    for name in early_list:
        students_early.append([name, student_info[name]])
    print_info('早退', students_early, num)
    with open("early_students_info.csv", "w", newline="") as f_in:
        file_writer = csv.writer(f_in, quotechar='|', quoting=csv.QUOTE_MINIMAL)
        for info in students_early:
            file_writer.writerow(info)
    print("\n已導出早退學生名單!文件位置位於當前目錄下early_students_info.csv")


###
# 功能:曠課名單的寫入和輸出
# 輸入:曠課學生名單(list)和學生全部信息(dict)以及一行的顯示數量
# 返回值:None
###
def dmq_file_in_absence(absence_list, student_info, num):
    for name in absence_list:
        students_absence.append([name, student_info[name]])
    print_info('曠課', students_absence, num)
    with open("absence_students_info.csv", "w", newline="") as f_in:
        file_writer = csv.writer(f_in, quotechar='|', quoting=csv.QUOTE_MINIMAL)
        for info in students_absence:
            file_writer.writerow(info)
    print("\n已導出曠課學生名單!文件位置位於當前目錄下absence_students_info.csv")


###
# 功能:輸出 特定 列表數據
# 輸入:名單名稱、特定的list  [[*, *], [*, *], [*, *], ...]和每行顯示數字
# 返回值:None
###
def print_info(string, special_list, num):
    count = 0
    print('--'*5 + '**' + string + '名單(' + str(num) + '個一行)' + '**' + '--'*5)
    for i in special_list:
        if (count % num == 0) & (count != 0):
            print()
        print(i[0]+","+i[1], end=' ')
        count += 1


###
# 功能:第二次點名
# 輸入:打亂的學生名單(list)
# 返回值:早退的學生名單(list)
###
def dmq_dm_2(list_1):
    name_list = list(set(list_1) - set(student_sick))
    student_dm_wrong = []
    print('\n下課時間到!開始第二次點名!\n')
    for name in name_list:
        temp = input(name + "在嗎?(輸入在或不在)")
        if temp == "在":
            continue
        elif temp == "不在":
            student_early.append(name)
        else:
            student_dm_wrong.append(name)
            print("請按要求輸入!該名字被放置最後點名。")
    if student_dm_wrong:
        for name in student_dm_wrong:
            temp = input(name + "在嗎?(輸入在或不在)")
            if temp == "在":
                continue
            elif temp == "不在":
                student_early.append(name)
            else:
                print("仍然未按照要求輸入!算入早退名單!")
                student_early.append(name)


###
# 功能: 計算兩列表的交集
# 輸入: 兩個列表(不分先後)
# 返回: None
###
def list_mix(list_1, list_2):
    mix = []
    for i in list_1:
        if i in list_2:
            mix.append(i)
    return mix


def main(file_name, num):
    # 讀入csv文件
    temp = dmq_init(file_name)
    student_info = temp[0]
    name_list = temp[1]

    # 第一次點名
    dmq_dm(name_list)
    # 第二次點名
    dmq_dm_2(name_list)

    # 對運算結果做出調整
    # 交集運算出曠課名單
    student_absence = list_mix(student_late, student_early)
    # 遲到名單裏不能有曠課和請假的人(確保一下)
    student_late_new = list(set(student_late) - set(student_absence) - set(student_sick))
    # 早退名單裏不能有曠課和請假的人(確保一下)
    student_early_new = list(set(student_early) - set(student_absence) - set(student_sick))

    # 輸出並導入請假名單
    dmq_file_in_sick(student_sick, student_info, num)
    # 輸出並導入遲到名單
    dmq_file_in_late(student_late_new, student_info, num)
    # 輸出並導入早退名單
    dmq_file_in_early(student_early_new, student_info, num)
    # 輸出並導入曠課名單
    dmq_file_in_absence(student_absence, student_info, num)
    # return '程序結束'


# 5代表5個名字一行輸出
main("test.csv", 5)

這裏就強調一下main函數裏面的兩次點名和輸出寫入中間的部分,因爲曠課名單是遲到和早退的交集,所以名單肯定會重複,那我們就運用集合的差運算來避免這個問題,然後爲了確保請假學生名單不會出現在遲到和早退名單裏,就順便加上了(感覺這種情況肯定不會發生,自己也就寫一下確保一下)。

運行截圖

這裏就給出一組測試圖了,但自己也測了很多遍了。
(以下人名不要在意)
開始第一次點名,這裏可以看出請假的人有李浩,遲到的人有程陽王芝偉
在這裏插入圖片描述
然後我們繼續輸入,這裏可以知道,袁震王芝偉是早退了,而且第二次點名的名單裏沒有第一次點名名單裏的請假學生李浩(原因見代碼中dmq_dm_2()開頭的集合差運算)在這裏插入圖片描述
然後我們想一下,最終的名單應該是王芝偉曠課,袁震早退,李浩請假,程陽遲到。我們接着來看看輸出的是否符合我們得到的結論
在這裏插入圖片描述
我們再看看文件裏面是否正確
在這裏插入圖片描述正確,程序結束。

總結

這次從看到要求到寫出代碼花了挺長時間的,主要總結了幾點自己犯的錯誤:

  1. 自己變量取名字太相近了,如果看我V2的代碼,會發現很多方法裏面的參數名字很相像,導致我V3在改的時候,很暈,畢竟200多行代碼 /= =/
  2. 自己的V2寫的方法還是沒有真正達到降低耦合性的效果,有一定效果,但很少,這次V3的代碼,我就已經一上來就把自己最終要的參數一一羅列爲全局變量,讓每個函數都少一點return值,第一是爲了減少參數名,不然想名字想半天,第二就是想全力達到想要的從一開始的空值,一步步方法改變,到最後變成想要的值,過程中只知道經過了哪幾個方法調用,而看不到方法內部。(不知道講清楚了沒,可以看代碼體會下。。)
  3. 自己代碼應該再多加點註釋,自己就隔了三四天吧,拿到自己寫的V2的代碼,想改成V3的還花了點時間放在看參數上面(可能是自己參數太亂了,就是第一點提到的問題),挺暈的。第一次看自己的代碼看暈= =

最後給大家看看自己一開始搞的GUI界面,畢竟是自己寫的,代碼就不給出了,就看看界面效果(後期可能會出個有關tkinter的博客,因爲隨着點名器功能的增加,很可能需要更換顯示界面)
這裏給出片段代碼,然後我們就開始展示界面。
在這裏插入圖片描述
主界面:
在這裏插入圖片描述
選擇點名名單和上課時間之後,點擊開始點名;就會彈出實時顯示四個名單的文本域和處理上課時來的學生的補籤事件,點擊返回就可以關閉界面。
在這裏插入圖片描述
點擊補籤,彈出新窗口,輸入補籤學生學號然後確定就可以了;
在這裏插入圖片描述
補籤成功就會顯示一行字;
在這裏插入圖片描述
主界面點擊叉號還可以彈出messageBox提示窗口。
在這裏插入圖片描述文章到這就結束了。

最後就希望大家給點建議,如果文章給你提供了幫助和感觸,自己也很高興。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章