國際慣例:實踐是檢驗真理的惟一標準。
衆所周知,在編程過程當中理論知識再充實也須要經過項目的鍊金石。下面給你們看一下我徒弟作的一個小項目實戰要求,是作一個銀行系統,就是咱們去銀行辦業務時候會有個自助的ATM機,如今大部分業務都是由他來解決的。首先本身想想,用面向對象的思想該怎樣實現這個系統呢?都有哪些對象?他們各自的功能都有什麼?想到的越多越好,在實現的時候,碰到一個問題解決一個問題,過程中問題不少,也不是很容易解決,不過也就是這樣的過程才能學到新的東西。數據庫
1、準備工做 首先走進銀行的大門,會有工做人員來詢問須要辦理什麼業務,固然得實話實說了,不過這個和系統沒什麼關係(* ̄︶ ̄)。接下來,若是要辦理的業務是比較大衆化的,能夠在機器上完成,那麼她就會帶着咱們到一個龐大的小機器旁邊。前面他還須要操做幾下,來讓機器能夠爲咱們工做,有時能夠見到招呼一個更高級的員工來輸下指紋。這些咱們能夠理解爲管理員來啓動系統(有些人是否是以爲哪有這麼麻煩,主要我這裏說的是銀行裏面那幾臺功能比較全的,不僅僅是簡單的自動取款機)。編程
接下來該辦理咱們的業務了,都有哪些業務呢?先列舉一些:查餘額,存款,取款,轉帳,改個密碼,還能夠掛失鎖卡,對應還能解鎖,把最基本的忘記了,沒有辦卡哪有這些操做呢,開戶也得算上,補卡,銷戶等等。dom
到這裏了,咱們和實際狀況相比沒有實體的卡,因此會有一些差別。剩下的過程當中想到了再說。函數
2、轉換思想 前面大概肯定了須要實現的功能,最終咱們仍是要寫成代碼,因此得從編程的思想來考慮那些需求。學習
首先要考慮這個系統中有哪些對象,從人到銀行的ATM機都有哪些事物。人,銀行卡,ATM機,這三個是必須有的了,還須要什麼,開始辦理業務時候那個幫咱們操做的人有不少和咱們用戶不同的操做,把他也當作一個對象。測試
人。人這個對象有哪些屬性呢?人有本身的一些信息,還有銀行卡,剩下要辦理的業務咱們人爲的給定。.net
卡。卡也有自己的一些信息。rest
ATM。atm機的功能就要多一些了,首先就是上面整理出來的那些存取款等等的功能,他都得實現。除此以外還有個工做人員對他的操做,他也得處理一下。code
工做人員。他們有啓用和關閉這個系統的權利。對象
大致方向有了,剩下的就一點點的完善。
3、功能實現 先從簡單的開始,前面說到,客戶和卡的屬性仍是比較單純的,那就先把他們解決了。
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("* 519970686 歡迎登錄銀行(Python資料學習羣) *") 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文件,把他搞懂後,相信讓他運行起來不難。(原文出處:https://blog.csdn.net/Stephen_shijun/article/details/83212989)