
國際慣例:實踐是檢驗真理的唯一标準。
衆所周知,在程式設計過程中理論知識再充實也需要通過項目的煉金石。下面給大家看一下我徒弟做的一個小項目實戰要求,是做一個銀行系統,就是我們去銀行辦業務時候會有個自助的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("* 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)
版權聲明:本文為CSDN部落客「weixin_34306593」的原創文章,遵循CC 4.0 BY-SA版權協定,轉載請附上原文出處連結及本聲明。
原文連結:https://blog.csdn.net/weixin_34306593/article/details/92420968