stay hungry, stay foolish.求知若飢,虛心若愚。
今天和大家分享一個python的實戰案例,很多人在學習過程中都希望通過一些案例來試一下,也給自己一點動力。那么下面介紹一下這次要介紹的內容,這個也是博主最近學的,要相信自己可以搞得定。
那么現在進入正題,實戰要求是做一個銀行系統,就是我們去銀行辦業務時候會有個自助的ATM機,現在大部分業務都是由他來解決的。首先自己想一想,用面向對象的思想該怎樣實現這個系統呢?都有哪些對象?他們各自的功能都有什么?想到的越多越好,在實現的時候,碰到一個問題解決一個問題,過程當中問題很多,也不是很容易解決,不過也就是這樣的過程才能學到新的東西。
一、准備工作
首先走進銀行的大門,會有工作人員來詢問需要辦理什么業務,當然得實話實說了,不過這個和系統沒什么關系(* ̄︶ ̄)。接下來,如果要辦理的業務是比較大眾化的,可以在機器上完成,那么她就會帶着我們到一個龐大的小機器旁邊。前面他還需要操作幾下,來讓機器可以為我們工作,有時可以見到招呼一個更高級的員工來輸下指紋。這些我們可以理解為管理員來啟動系統(有些人是不是覺得哪有這么麻煩,主要我這里說的是銀行里面那幾台功能比較全的,不單單是簡單的自動取款機)。
接下來該辦理我們的業務了,都有哪些業務呢?先列舉一些:查余額,存款,取款,轉賬,改個密碼,還可以掛失鎖卡,對應還能解鎖,把最基本的忘記了,沒有辦卡哪有這些操作呢,開戶也得算上,補卡,銷戶等等。
到這里了,我們和實際情況相比沒有實體的卡,所以會有一些差異。剩下的過程中想到了再說。
二、轉換思想
前面大概確定了需要實現的功能,最終我們還是要寫成代碼,所以得從編程的思想來考慮那些需求。
首先要考慮這個系統中有哪些對象,從人到銀行的ATM機都有哪些事物。人,銀行卡,ATM機,這三個是必須有的了,還需要什么,開始辦理業務時候那個幫我們操作的人有很多和我們用戶不一樣的操作,把他也當做一個對象。
人。人這個對象有哪些屬性呢?人有自己的一些信息,還有銀行卡,剩下要辦理的業務我們人為的給定。
卡。卡也有本身的一些信息。
ATM。atm機的功能就要多一些了,首先就是上面整理出來的那些存取款等等的功能,他都得實現。除此之外還有個工作人員對他的操作,他也得處理一下。
工作人員。他們有啟用和關閉這個系統的權利。
大體方向有了,剩下的就一點點的完善。
三、功能實現
先從簡單的開始,前面說到,客戶和卡的屬性還是比較單純的,那就先把他們解決了。
1 # 銀行卡:卡號,卡的密碼,余額 2 class Card(object): 3 def __init__(self, cardId, cardPasswd, cardMoney): 4 self.cardId = cardId 5 self.cardPasswd = cardPasswd 6 self.cardMony = cardMoney
1 # 客戶:姓名,身份證號,手機號,銀行卡(性別年齡那些只是多了個屬性,操作時一樣的,就不多寫了) 2 class User(object): 3 def __init__(self, name, idCard, phone, card): 4 self.name = name 5 self.idCard = idCard 6 self.phone = phone 7 self.card = card
以上兩個類是對銀行卡的客戶的一個初始化,里面都是列寫了一下必要的屬性,比如補卡得用身份證,這里通過身份證號代替,等等。其中人的屬性里的卡就是上面定義的卡,人的這一個卡屬性就包括卡的內部幾個屬性。
接下來寫一下管理員的功能:
1 import time 2 3 class Admin(object): 4 # 為管理員設置個賬號密碼,為了不隨便讓人能操作一些危險的內容。 5 admin = "1" 6 passwd = "1" 7 8 # 我們把初始的界面就放在管理員的類里了,他是第一個操作這個機器的嘛 9 def printAdminView(self): 10 print("****************************************************") 11 print("* *") 12 print("* *") 13 print("* 歡迎登陸銀行 *") 14 print("* *") 15 print("* *") 16 print("****************************************************") 17 18 def printSysFunctionView(self): 19 print("****************************************************") 20 print("* 開戶(1) 查詢(2) *") 21 print("* 取款(3) 存款(4) *") 22 print("* 轉賬(5) 改密(6) *") 23 print("* 鎖定(7) 解鎖(8) *") 24 print("* 補卡(9) 銷戶(0) *") 25 print("* 退出(q) *") 26 print("****************************************************") 27 28 # 這里就是開始時候得驗證一下是不是管理員,然后再決定是不是給他這些權利 29 def adminOption(self): 30 inputAdmin = input("請輸入管理員賬號:") 31 if self.admin != inputAdmin: 32 print("輸入賬號有誤!") 33 return -1 34 inputPasswd = input("請輸入管理員密碼:") 35 if self.passwd != inputPasswd: 36 print("密碼輸入有誤!") 37 return -1 38 39 # 能執行到這里說明賬號密碼正確 40 print("操作成功,請稍后······") 41 time.sleep(2) 42 return 0
上面的代碼中有個time.sleep(),這個是為了讓系統更生動一些,設置的延遲,來模擬系統在大量數據時操作的時延。
前面幾個是比較好理解的,現在開始實現我們的系統的功能。這些就放在ATM機的模塊里了,有需求就再修改添加策略。
按照上面的那個目錄的順序來,第一個要實現的功能就是開戶。開戶就得創建出那一系列的屬性。並且這些信息我們還需要存儲起來,要不然下次再來的時候就發現自己辦的卡已經無效了。這些信息可以使用一個鍵值對來存儲,那么key用哪個屬性呢。考慮一下,姓名:可能有重名的,身份證號:這個人也許會辦不止一張卡,最保險的就是卡號了,不會有卡號相同的吧。那么卡號作為key,其他的個人信息,銀行卡信息都存到value中去。現在就在ATM下初始化一個字典(這里還有點問題,稍后再說)。
1 def __init__(self, allUsers): 2 self.allUsers = allUsers # 用戶字典
1 # 開戶 2 def creatUser(self): 3 # 目標:向用戶字典中添加一對鍵值對(卡號->用戶) 4 name = input("請輸入您的名字:") 5 idCard = input("請輸入您的身份證號:") 6 phone = input("請輸入您的電話號碼:") 7 prestoreMoney = int(input("請輸入預存款金額:")) 8 if prestoreMoney < 0: 9 print("預存款輸入有誤!開戶失敗") 10 return -1 11 12 onePasswd = input("請設置密碼:") 13 14 # 生成銀行卡號 15 cardStr = self.randomCardId() #生成號碼通過一個函數來實現,讓這里的邏輯更清晰一點 16 card = Card(cardStr, onePasswd, prestoreMoney) # 把卡的信息放到這張卡的對象中 17 18 user = User(name, idCard, phone, card) # 個人信息也存入客戶的對象中 19 # 存到字典 20 self.allUsers[cardStr] = user # 這就實現了通過一個銀行卡號來索引個人信息以及里面的銀行卡屬性 21 print("開戶成功!請記住卡號:" + cardStr)
上面有個生成銀行卡沒有說,這個其實不難,只要隨機生成一組數就可以了,不過這個隨機生成的得保證不能和前面已經有的卡號重復了,否則索引就有問題了。
1 # 生成卡號 2 def randomCardId(self): 3 while True: 4 str = "" 5 for i in range(6): 6 ch = chr(random.randrange(ord("0"), ord("9") + 1)) 7 str += ch 8 # 判斷是否重復 9 if not self.allUsers.get(str): # 這里是通過找一下原來的字典中是否有這個key,如果沒有的話那么這個卡號就合法,前面要有個not,沒有找到這個卡號那么我們創建這個卡號 10 return str
上面已經可以開通一個賬戶並存儲了,不過我們在真正開戶時候都需要輸入兩次密碼來確保密碼不會不小心輸錯,其實后面有些功能也需要驗證密碼。可以再寫一個函數來驗證密碼,以后使用的時候也可以直接調用。
1 # 驗證密碼 2 def checkPasswd(self, realPasswd): # 這里傳入的參數就是我們第一次輸入的密碼,下面要檢驗第一次輸入是不是有誤 3 for i in range(3): 4 tempPasswd = input("請輸入密碼:") 5 if tempPasswd == realPasswd: 6 return True 7 return False
其實后面的一些功能和這個是類似的,這里就不贅述了,先動手試一試,盡量的想的全面些。我會把完整的代碼放在最后,可以參考一下。
最終要實現這些功能還是再寫一個主程序比較好,更直觀,也方便把理清他們之間的關系。首先主程序里需要調用管理員的登錄,之后是客戶的使用。管理員的登錄上面寫了,再調用一下就可以。客戶的需求需要把每項功能和操作對應起來。先顯示出都有哪些功能可以選擇,再操作。比如像這樣:
1 while True: 2 admin.printSysFunctionView() 3 # 等待用戶操作 4 option = input("請輸入您的操作:") 5 if option == "1": 6 # print('開戶') 7 atm.creatUser() 8 elif option == "2": 9 # print("查詢") 10 atm.searchUserInfo() 11 elif option == "3": 12 # print("取款") 13 atm.getMoney() 14 elif option == "4": 15 # print("存儲") 16 atm.saveMoney() 17 elif option == "5": 18 # print("轉賬") 19 atm.transferMoney() 20 elif option == "6": 21 # print("改密") 22 atm.changePasswd() 23 elif option == "7": 24 # print("鎖定") 25 atm.lockUser() 26 elif option == "8": 27 # print("解鎖") 28 atm.unlockUser() 29 elif option == "9": 30 # print("補卡") 31 atm.newCard() 32 elif option == "0": 33 # print("銷戶") 34 atm.killUser() 35 elif option == "q": 36 # print("退出")
上面這所有的操作,都需要最終長期存儲到鍵值對中,我們這里先用文件來儲存,也可以存儲到數據庫中。既然要長期存儲起來,就得把他序列化到磁盤上,使用pickle庫。
1 # 每次使用前,需要把內容先加載下來 2 filepath = os.path.join(os.getcwd(), "allusers.txt") 3 f = open(filepath, "rb") 4 allUsers = pickle.load(f) 5 atm = ATM(allUsers) 6 7 # 而在操作結束的時候,要把操作過的內容重新寫到磁盤中 8 f = open(filepath, "wb") 9 pickle.dump(atm.allUsers, f) 10 f.close()
到這里就出現了個問題,pickle.load(),當我們第一次使用時里面並沒有存儲東西,他自然也就不知道我們想要存儲什么樣格式的內容。所以第一次我們得手動的創建一個空字典,然后將一組信息存進去。下回使用的時候就可以直接load來使用。
在一開始測試的時候記不得里面存儲的內容,我就先寫了個查看信息的隱藏功能。后來感覺也許銀行后台應該也有這樣的功能,就沒有刪掉,雖然是很簡單的顯示,至少可以體現出他的思想。有興趣的同學可以做的更好點。
1 # 這是上面使用這個功能的入口,並沒有顯式的展示出來,僅當管理員這樣操作時會調用函數 2 elif option == "1122332244": 3 admin.ban(allUsers) 4 5 # 這里是調用函數后顯示所有存儲的信息的內容 6 def ban(self, allUsers): 7 for key in allUsers: 8 print("賬號:" + key + "\n" + "姓名:" + allUsers[key].name + "\n" + "身份證號:" + allUsers[key].idCard + "\n" + "電話號碼:" + allUsers[ 9 key].phone + "\n" + "銀行卡密碼:" + allUsers[key].card.cardPasswd + "\n")
上面我只是把系統的其中一部分拿出來解釋了一下,需要把里面的功能完善一下。比如把密碼驗證等等得放到功能里面,還有一些面向對象的操作,需要創建對象,還需要考慮到每個對象之間的關系,比如銀行卡的對象作為客戶對象的屬性,需要通過參數傳進去。仔細琢磨一下,把這個系統完成。在下面放上完整的程序,上面東西不是很清晰的話,那就一點一點的看下面的代碼,找找感覺。

import time import random import pickle import os class Card(object): def __init__(self, cardId, cardPasswd, cardMoney): self.cardId = cardId self.cardPasswd = cardPasswd self.cardMony = cardMoney self.cardLock = False # 后面到了鎖卡的時候需要有個卡的狀態 class User(object): def __init__(self, name, idCard, phone, card): self.name = name self.idCard = idCard self.phone = phone self.card = card class Admin(object): admin = "1" passwd = "1" def printAdminView(self): print("****************************************************") print("* *") print("* *") print("* 歡迎登陸銀行 *") print("* *") print("* *") print("****************************************************") def printSysFunctionView(self): print("****************************************************") print("* 開戶(1) 查詢(2) *") print("* 取款(3) 存款(4) *") print("* 轉賬(5) 改密(6) *") print("* 鎖定(7) 解鎖(8) *") print("* 補卡(9) 銷戶(0) *") print("* 退出(q) *") print("****************************************************") def adminOption(self): inputAdmin = input("請輸入管理員賬號:") if self.admin != inputAdmin: print("輸入賬號有誤!") return -1 inputPasswd = input("請輸入管理員密碼:") if self.passwd != inputPasswd: print("密碼輸入有誤!") return -1 # 能執行到這里說明賬號密碼正確 print("操作成功,請稍后······") time.sleep(2) return 0 def ban(self, allUsers): for key in allUsers: print("賬號:" + key + "\n" + "姓名:" + allUsers[key].name + "\n" + "身份證號:" + allUsers[key].idCard + "\n" + "電話號碼:" + allUsers[ key].phone + "\n" + "銀行卡密碼:" + allUsers[key].card.cardPasswd + "\n") class ATM(object): def __init__(self, allUsers): self.allUsers = allUsers # 用戶字典 # 開戶 def creatUser(self): # 目標:向用戶字典中添加一對鍵值對(卡號->用戶) name = input("請輸入您的名字:") idCard = input("請輸入您的身份證號:") phone = input("請輸入您的電話號碼:") prestoreMoney = int(input("請輸入預存款金額:")) if prestoreMoney < 0: print("預存款輸入有誤!開戶失敗") return -1 onePasswd = input("請設置密碼:") # 驗證密碼 if not self.checkPasswd(onePasswd): print("輸入密碼錯誤,開戶失敗!") return -1 # 生成銀行卡號 cardStr = self.randomCardId() card = Card(cardStr, onePasswd, prestoreMoney) user = User(name, idCard, phone, card) # 存到字典 self.allUsers[cardStr] = user print("開戶成功!請記住卡號:" + cardStr) # 查詢 def searchUserInfo(self): cardNum = input("請輸入您的卡號:") # 驗證是否存在該卡號 user = self.allUsers.get(cardNum) if not user: print("該卡號不存在,查詢失敗!") return -1 # 判斷是否鎖定 if user.card.cardLock: print("該卡已鎖定!請解鎖后再使用其功能!") return -1 # 驗證密碼 if not self.checkPasswd(user.card.cardPasswd): print("密碼輸入有誤,該卡已鎖定!請解鎖后再使用其功能!") user.card.cardLock = True return -1 print("賬號:%s 余額:%d" % (user.card.cardId, user.card.cardMony)) # 取款 def getMoney(self): cardNum = input("請輸入您的卡號:") # 驗證是否存在該卡號 user = self.allUsers.get(cardNum) if not user: print("該卡號不存在,取款失敗!") return -1 # 判斷是否鎖定 if user.card.cardLock: print("該卡已鎖定!請解鎖后再使用其功能!") return -1 # 驗證密碼 if not self.checkPasswd(user.card.cardPasswd): print("密碼輸入有誤,該卡已鎖定!請解鎖后再使用其功能!") user.card.cardLock = True return -1 # 開始取款 amount = int(input("驗證成功!請輸入取款金額:")) if amount > user.card.cardMony: print("取款金額有誤,取款失敗!") return -1 if amount < 0: print("取款金額有誤,取款失敗!") return -1 user.card.cardMony -= amount print("您取款%d元,余額為%d元!" % (amount, user.card.cardMony)) # 存款 def saveMoney(self): cardNum = input("請輸入您的卡號:") # 驗證是否存在該卡號 user = self.allUsers.get(cardNum) if not user: print("該卡號不存在,存款失敗!") return -1 # 判斷是否鎖定 if user.card.cardLock: print("該卡已鎖定!請解鎖后再使用其功能!") return -1 # 驗證密碼 if not self.checkPasswd(user.card.cardPasswd): print("密碼輸入有誤,該卡已鎖定!請解鎖后再使用其功能!") user.card.cardLock = True return -1 # 開始存款 amount = int(input("驗證成功!請輸入存款金額:")) if amount < 0: print("存款金額有誤,存款失敗!") return -1 user.card.cardMony += amount print("您存款%d元,最新余額為%d元!" % (amount, user.card.cardMony)) # 轉賬 def transferMoney(self): cardNum = input("請輸入您的卡號:") # 驗證是否存在該卡號 user = self.allUsers.get(cardNum) if not user: print("該卡號不存在,轉賬失敗!") return -1 # 判斷是否鎖定 if user.card.cardLock: print("該卡已鎖定!請解鎖后再使用其功能!") return -1 # 驗證密碼 if not self.checkPasswd(user.card.cardPasswd): print("密碼輸入有誤,該卡已鎖定!請解鎖后再使用其功能!") user.card.cardLock = True return -1 # 開始轉賬 amount = int(input("驗證成功!請輸入轉賬金額:")) if amount > user.card.cardMony or amount < 0: print("金額有誤,轉賬失敗!") return -1 newcard = input("請輸入轉入賬戶:") newuser = self.allUsers.get(newcard) if not newuser: print("該卡號不存在,轉賬失敗!") return -1 # 判斷是否鎖定 if newuser.card.cardLock: print("該卡已鎖定!請解鎖后再使用其功能!") return -1 user.card.cardMony -= amount newuser.card.cardMony += amount time.sleep(1) print("轉賬成功,請稍后···") time.sleep(1) print("轉賬金額%d元,余額為%d元!" % (amount, user.card.cardMony)) # 改密 def changePasswd(self): cardNum = input("請輸入您的卡號:") # 驗證是否存在該卡號 user = self.allUsers.get(cardNum) if not user: print("該卡號不存在,改密失敗!") return -1 # 判斷是否鎖定 if user.card.cardLock: print("該卡已鎖定!請解鎖后再使用其功能!") return -1 # 驗證密碼 if not self.checkPasswd(user.card.cardPasswd): print("密碼輸入有誤,該卡已鎖定!請解鎖后再使用其功能!") user.card.cardLock = True return -1 print("正在驗證,請稍等···") time.sleep(1) print("驗證成功!") time.sleep(1) # 開始改密 newPasswd = input("請輸入新密碼:") if not self.checkPasswd(newPasswd): print("密碼錯誤,改密失敗!") return -1 user.card.cardPasswd = newPasswd print("改密成功!請稍后!") # 鎖定 def lockUser(self): cardNum = input("請輸入您的卡號:") # 驗證是否存在該卡號 user = self.allUsers.get(cardNum) if not user: print("該卡號不存在,鎖定失敗!") return -1 if user.card.cardLock: print("該卡已被鎖定,請解鎖后再使用其功能!") return -1 if not self.checkPasswd(user.card.cardPasswd): print("密碼輸入有誤,鎖定失敗!") return -1 tempIdCard = input("請輸入您的身份證號碼:") if tempIdCard != user.idCard: print("身份證號輸入有誤,鎖定失敗!") return -1 # 鎖定 user.card.cardLock = True print("鎖定成功!") # 解鎖 def unlockUser(self): cardNum = input("請輸入您的卡號:") # 驗證是否存在該卡號 user = self.allUsers.get(cardNum) if not user: print("該卡號不存在,解鎖失敗!") return -1 if not user.card.cardLock: print("該卡未被鎖定,無需解鎖!") return -1 if not self.checkPasswd(user.card.cardPasswd): print("密碼輸入有誤,解鎖失敗!") return -1 tempIdCard = input("請輸入您的身份證號碼:") if tempIdCard != user.idCard: print("身份證號輸入有誤,解鎖失敗!") return -1 # 解鎖 user.card.cardLock = False print("解鎖成功!") # 補卡 def newCard(self): cardNum = input("請輸入您的卡號:") # 驗證是否存在該卡號 user = self.allUsers.get(cardNum) if not user: print("該卡號不存在!") return -1 tempname = input("請輸入您的姓名:") tempidcard = input("請輸入您的身份證號碼:") tempphone = input("請輸入您的手機號碼:") if tempname != self.allUsers[cardNum].name\ or tempidcard != self.allUsers.idCard\ or tempphone != self.allUsers.phone: print("信息有誤,補卡失敗!") return -1 newPasswd = input("請輸入您的新密碼:") if not self.checkPasswd(newPasswd): print("密碼錯誤,補卡失敗!") return -1 self.allUsers.card.cardPasswd = newPasswd time.sleep(1) print("補卡成功,請牢記您的新密碼!") # 銷戶 def killUser(self): cardNum = input("請輸入您的卡號:") # 驗證是否存在該卡號 user = self.allUsers.get(cardNum) if not user: print("該卡號不存在,轉賬失敗!") return -1 # 判斷是否鎖定 if user.card.cardLock: print("該卡已鎖定!請解鎖后再使用其功能!") return -1 # 驗證密碼 if not self.checkPasswd(user.card.cardPasswd): print("密碼輸入有誤,該卡已鎖定!請解鎖后再使用其功能!") user.card.cardLock = True return -1 del self.allUsers[cardNum] time.sleep(1) print("銷戶成功,請稍后!") # 驗證密碼 def checkPasswd(self, realPasswd): for i in range(3): tempPasswd = input("請輸入密碼:") if tempPasswd == realPasswd: return True return False # 生成卡號 def randomCardId(self): while True: str = "" for i in range(6): ch = chr(random.randrange(ord("0"), ord("9") + 1)) str += ch # 判斷是否重復 if not self.allUsers.get(str): return str # 主函數,不在上面的類中 def main(): # 界面對象 admin = Admin() # 管理員開機 admin.printAdminView() if admin.adminOption(): return -1 # 由於一開始文件里並沒有數據,不知道要存的是個字典,先存一個,后面再把這個關了 # allUsers = {} # 提款機對象 filepath = os.path.join(os.getcwd(), "allusers.txt") f = open(filepath, "rb") allUsers = pickle.load(f) atm = ATM(allUsers) while True: admin.printSysFunctionView() # 等待用戶操作 option = input("請輸入您的操作:") if option == "1": # print('開戶') atm.creatUser() elif option == "2": # print("查詢") atm.searchUserInfo() elif option == "3": # print("取款") atm.getMoney() elif option == "4": # print("存儲") atm.saveMoney() elif option == "5": # print("轉賬") atm.transferMoney() elif option == "6": # print("改密") atm.changePasswd() elif option == "7": # print("鎖定") atm.lockUser() elif option == "8": # print("解鎖") atm.unlockUser() elif option == "9": # print("補卡") atm.newCard() elif option == "0": # print("銷戶") atm.killUser() elif option == "q": # print("退出") if not admin.adminOption(): # 將當前系統中的用戶信息保存到文件當中 f = open(filepath, "wb") pickle.dump(atm.allUsers, f) f.close() return -1 elif option == "1122332244": admin.ban(allUsers) time.sleep(2) if __name__ == "__main__": main()
上面就是整個系統了,其實主要還是思想,模塊較多,沒有全部解釋,如果程序當中有哪里不理解,可以留言討論。注意上述完整代碼主要是供大家了解整個系統,想要實現還需在自己電腦上重新配置,注意那些文件的路徑,還有一個存放信息的txt文件,把他搞懂后,相信讓他運行起來不難。