目录
一、题目描述
二、分析
三、源码
四、比较
一、题目描述
针对上一个做的银行卡系统的一个升级版,上一个系统做的功能单一,而且结构简单,为此找了一个提升版来练习,可以先看上一篇文章对基本的思路有一个了解,然后再看此文章,此文章也会在不同之处做出比较。
CSDNhttps://mp.csdn.net/mp_blog/creation/editor/124681745
二、分析
1、三个类,分别为用户类,卡类和ATM类
????????①用户类中定义并初始化四个属性的值,分别为姓名(name),身份证号(idcard),手机号(phonenum),以及银行卡号(card)
class User():
def __init__(self, name, idcard, phonenum, card):
self.name = name#姓名
self.idcard = idcard#身份证号
self.phonenum = phonenum#手机号
self.card = card#银行卡号
? ? ? ? ②卡类中定义并初始化四个属性的值,分别为卡号(cardnum),密码(password),金额(money)以及是否锁卡(islock)(当密码错误三次以后会将卡锁住,此变量就是其判断的依据)
class Card:
def __init__(self, cardnum, password, money, islock=False):
self.cardnum = cardnum#卡号
self.password = password#密码
self.money = money#金额
self.islock = islock#
? ? ? ? ③ATM类,类中并没有初始化属性值,但是ATM中定义了很多的方法,包括静态方法、和类方法
2、整体思路
? ? ? ? ①首先要有个欢迎界面:此方法因为不涉及到类属性和对象属性,所以定义为静态方法即可,输出的内容也极为简单,就是打印一个简单的页面而已
@staticmethod
def welcome():
print('''
**********************
* *
* 欢迎来到中国农业银行 *
* ABC *
* *
**********************
''')
? ? ? ? ②第二步就是一个选择界面了,此方法因为不涉及到类属性和对象属性,所以定义为静态方法即可;因为用户的选择可以有很多以及用户可以不断的进行,所以接下来的操作要在一个无限循环中,直到选择退出才退出系统;选择方法的内容也很简单就是展现有的功能,然后引导用户按照界面去选择相应的功能,此时是需要用户输入自己的选择的,输入的数用变量存储起来,判断其所选择的功能,然后去执行相应的方法。
@staticmethod
def select():
print('''
**********************
* 1.登陆 2.开户 *
* 3.查询 4.取款 *
* 5.存款 0.退出 *
* 6.转账 7.改密 *
* 8.注销 9.解锁 *
* 10.忘记密码 *
**********************
''')
num = input("请选择服务项目:")
return num
? ? ? ? ③在写好了欢迎界面和选择界面之后,接下来就是写相应的功能了,开户
????????首先介绍的是开户,也就是注册方法,因为要用到类属性,所以定义为一个类方法;先定义一个用来存简单密码的列表,防止用户设置的密码过于简单(类似于111111,222222,333333);
????????因为是开户,而用户的操作可能有多个,所以接下来的代码也是在一个无限循环中;
????????开户需要用户输入相应的信息,例如姓名,身份证号,,手机号等(卡所拥有的属性),然后其进行一些简单的判断;
????????为了模拟真实的环境,还会发送验证码到其手机(虚拟的),验证码是利用随机函数产生的6位随机数,发送的内容是之前就定义好格式,然后加上属性即可;
????????因为有了验证码,所以要对其进行验证,判断是否是本人在操作,验证码只有三次的输入机会,如果都错则退出系统,正确就进行下一步的输入密码;
????????设置密码会有三道验证,分别是长度、不能与身份证相同和过于简单;
????????密码设置好之后会再次确认一遍,然后再进行的是预存;
????????如果预存的金额合法,那么此时也就开户成功了,但是此时还没有生成卡号以及没有将卡的信息实例化到卡的类对象中,也就是说这些信息是零散的,并不能做到从属于某个对象;
????????卡号可以写一个静态方法去随机生成(因为不需要类属性和对象属性),然后再将卡号、密码、余额三个值实例化给一个卡对象,再将这个卡的对象和输入的姓名、身份证号、电话四者实例化为用户对象;最后将卡号和用户以键值对的形式存储到用户字典中(数据库)
????????此方法逻辑和过程都是最多的,因为涉及到的属性最多,而且属性还要进行一些简单的判断操作,所以很容易搞混乱以及写漏,所以用先写框架,即将if..else全部写出来,复杂的先用pass占位,简单的先写,然后再回来写复杂的部分。
@classmethod
def openUser(cls):
simple_pas = []
for i in range(10):#设置一个列表用来存储简单的密码,即111111这种,用于判定后面密码是否过于简单
simple_pas.append(str(i) * 6)
user_mas = '''#定义发送邮件的格式,方便之后直接赋值使用
+-------------------+
---{}
【中国农业银行】尊敬的{}
{},您已成功注册中国农业
银行账户{}
+-------------------+
'''
send_mas = '''#定义发送邮件的格式,方便之后直接赋值使用
+-------------------+
---{}
【中国农业银行】尊敬的{}
{},您正在申请中国农业银行
的账户,验证码 {},请勿告
诉他人
+-------------------+
'''
users = '''#定义发送邮件的格式,方便之后直接赋值使用
+-------------------+
姓 名: {}
性 别: {}
年 龄: {}
电 话: {}
身份证:{}
余 额: {}
卡 号:{}
+-------------------+
'''
while True:
try:
name = input("请输入您的姓名:")
idcard = input("请输入您的身份证号码:")
if len(idcard) != 18:
continue
if int(idcard[-2]) % 2 == 0:
sex = '女士'
else:
sex = '先生'
while True:
phonenum = input("请输入您的电话号码:")
if len(phonenum) != 11:
continue
yanzhengma = ""
for x in range(6):
yanzhengma += str(random.randrange(0, 10))
print(send_mas.format(phonenum, name, sex, yanzhengma))
print("已经向您的电话 {} 发送验证码".format(phonenum))
count = 0
while True:
recv = input("请您输入收到的验证码!").strip()
count += 1
if recv != yanzhengma:
if count > 2:
print("验证码输入3次错误!三秒后退出系统!")
time.sleep(3)
exit()
continue
else:
break
break
while True:
psd = input("请设置您的密码:").strip()
if len(psd) != 6 or psd in idcard or psd in simple_pas:
print("您的密码不应该与身份证号相同或者过于简单和格式不对")
continue
psd2 = input("请确认您的密码:")
print("密码保存成功!请您牢记!切勿告诉他人")
if psd == psd2:
mon = int(input("请输入您的预存余额:"))
if mon > 0:
cardnum = cls.getcardnum()
card = Card(cardnum, psd, mon)
user = User(name, idcard, phonenum, card)
cls.userDict[cardnum] = user
print("开卡成功,您的卡号为%s,请牢记..." % cardnum)
print(user_mas.format(phonenum, name, sex, cardnum))
today = datetime.datetime.today()
age = int(today.year) - int(idcard[6:10])
print(users.format(name, sex, age, phonenum, idcard, mon, cardnum))
break
else:
print("预存余额非法,开卡失败...")
else:
print("两次输入密码不一致,开卡失败...")
except:
print("输入错误!")
exit(0)
finally:
break
? ? ? ? ④接下来的工作就是将方法一个个的完善了,登录
????????首先需要用户输入银行卡号,然后判断卡号是否属于数据库中的某个用户,如果属于,则输入密码,不属于则提醒用户卡号不存在;
????????当卡号在数据库中时,接下来就需要用户输入密码,然后对其进行验证,此处有一个保护机制,就是如果密码输错三次就会将卡锁上,用到的是卡的islock属性,如果密码正确,即登录成功,然后将判断是否登录的属性赋值为其卡号(cls.islogin),此属性是为了接下来的查询、取钱等操作准备的,因为进行其它操作都要在登录的前提下进行的;
@classmethod
def login(cls):
cardnum = input("请输入您的卡号:")
#判断卡号是否存在,卡号的存储用的是字典.get
user = cls.userDict.get(cardnum)
if user:
while True:
psd = input("请输入您的密码:")
if psd == user.card.password:
print("登录成功!!!")
cls.changshicishu = 0
cls.islogin = cardnum
break
else:
cls.changshicishu += 1
# 如果尝试次数大于三 将锁卡
if cls.changshicishu >= 3:
print("卡已被锁,请先解锁")
cls.islogin = False
print(cls.islogin)
break
else:
print("密码错误,请重新输入,还有%d次将锁卡" % (3 - cls.changshicishu))
else:
print("卡号不存在,请查证后登录...")
? ? ? ? ⑤查询
? ? ? ? 查询先通过登录时将卡号赋值给cls.islogin判断其是否登录,然后再通过卡号找到数据库中卡的信息,也就能获得到余额的信息了
@classmethod
def search(cls):
print(cls.islogin)
if cls.islogin:
print("您当前的余额为%d" % (cls.userDict.get(cls.islogin).card.money))
else:
print("请先登录")
? ? ? ? ⑥取钱
? ? ? ? 首先要进行判断的还是用户是否登录,然后再用记录的卡号获取相应的信息,与查询不同的是此方法还要传入一个参数,即取出的金额;
????????此时需要判断的是账户的余额与需要取出的金额的大小,然后再进行相应的操作,如果小于,则提示用户余额不足,取款失败,如果大的话,那么先要将账户的余额减去取出的金额保存在余额中,然后提示用户取款成功
# 取钱
@classmethod
def setmoney(cls):
if cls.islogin:
money = int(input("请输入您要取的金额:"))
print(cls.userDict.get(cls.islogin).card.money)
if cls.islogin:
if cls.userDict.get(cls.islogin).card.money - money >= 0:
print("取款%d成功!" % money)
cls.userDict.get(cls.islogin).card.money -= money
print("您卡里的余额为%d" % cls.userDict.get(cls.islogin).card.money)
else:
print("余额不足,取款失败!")
else:
print("未登录,请登录后再试")
else:
print("请先登录")
? ? ? ? ⑦存钱
? ? ? ? 存钱相比于取钱来说少了一层判断,相比查询来说多了要传入一个参数
@classmethod
def getmoney(cls):
if cls.islogin:
while True:
gmoney = int(input("请输入您要存储的款项:"))
if gmoney > 0:
cls.userDict.get(cls.islogin).card.money += gmoney
print("您卡上的余额为%d" % cls.userDict.get(cls.islogin).card.money)
break
else:
print("输入有误,请重新输入金额")
else:
print("请先登录!")
? ? ? ? ⑧转账
? ? ? ? 首先要判断的还是用户是否登录,然后输入要转账的卡号,再就判断要转账的卡号是否在数据库中,如果不在则提示卡号有误,如果在则通过卡号获取到拥有此卡的用户的信息,然后需要用户输入要转账的金额,此时可以理解为转账的账户执行的是取钱的操作,接受账户执行的是存钱的操作(只是逻辑上这么理解),也就是一个账户的金额减少,一个账户的金额增加,当然,还是可以加一个判断转账的卡里面的余额是否充足的判断
@classmethod
def zhuanzhang(cls):
if cls.islogin:
while 1:
kahao = input("您需要转到的卡号为:")
for x in cls.userDict.keys():
if x == kahao:
print("您要转的卡号为%s,持卡人为%s" % (x, cls.userDict[x].name))
amoney = int(input("您需要转的金额为"))
# 转账人卡内余额减少
cls.userDict.get(cls.islogin).card.money -= amoney
# 被转账人卡内余额增加
cls.userDict.get(x).card.money += amoney
else:
continue
print("卡号有误,请重新输入")
break
else:
print("请先登录!")
? ? ? ? ⑨下面还有几个完善的方法,逻辑上都不难理解,此处就不过多的解释了
三、源码
# -*- coding: utf-8 -*-
__auth__ = '穆穆max'
data = '2021/1/4'
class User():
def __init__(self, name, idcard, phonenum, card):
self.name = name#姓名
self.idcard = idcard#身份证号
self.phonenum = phonenum#手机号
self.card = card#银行卡号
class Card:
def __init__(self, cardnum, password, money, islock=False):
self.cardnum = cardnum#卡号
self.password = password#密码
self.money = money#金额
self.islock = islock#
import random, time, datetime
class ATM:
userDict = {}
# 是否登录
islogin = None
# 尝试密码的次数
changshicishu = 0
@staticmethod
def welcome():
print('''
**********************
* *
* 欢迎来到中国农业银行 *
* ABC *
* *
**********************
''')
# 静态方法 :普通方法和类无关
@staticmethod
def select():
print('''
**********************
* 1.登陆 2.开户 *
* 3.查询 4.取款 *
* 5.存款 0.退出 *
* 6.转账 7.改密 *
* 8.注销 9.解锁 *
* 10.忘记密码 *
**********************
''')
num = input("请选择服务项目:")
return num
@staticmethod
def getcardnum():
"""
创造银行卡号
:return:
"""
cardnum = "622848"
for x in range(10):
cardnum += str(random.randrange(0, 10))
return cardnum
# 开户 类方法: 给类使用 第一个参数为 cls
@classmethod
def openUser(cls):
simple_pas = []
for i in range(10):#设置一个列表用来存储简单的密码,即111111这种,用于判定后面密码是否过于简单
simple_pas.append(str(i) * 6)
user_mas = '''#定义发送邮件的格式,方便之后直接赋值使用
+-------------------+
---{}
【中国农业银行】尊敬的{}
{},您已成功注册中国农业
银行账户{}
+-------------------+
'''
send_mas = '''#定义发送邮件的格式,方便之后直接赋值使用
+-------------------+
---{}
【中国农业银行】尊敬的{}
{},您正在申请中国农业银行
的账户,验证码 {},请勿告
诉他人
+-------------------+
'''
users = '''#定义发送邮件的格式,方便之后直接赋值使用
+-------------------+
姓 名: {}
性 别: {}
年 龄: {}
电 话: {}
身份证:{}
余 额: {}
卡 号:{}
+-------------------+
'''
while True:
try:
name = input("请输入您的姓名:")
idcard = input("请输入您的身份证号码:")
if len(idcard) != 18:
continue
if int(idcard[-2]) % 2 == 0:
sex = '女士'
else:
sex = '先生'
while True:
phonenum = input("请输入您的电话号码:")
if len(phonenum) != 11:
continue
yanzhengma = ""
for x in range(6):
yanzhengma += str(random.randrange(0, 10))
print(send_mas.format(phonenum, name, sex, yanzhengma))
print("已经向您的电话 {} 发送验证码".format(phonenum))
count = 0
while True:
recv = input("请您输入收到的验证码!").strip()
count += 1
if recv != yanzhengma:
if count > 2:
print("验证码输入3次错误!三秒后退出系统!")
time.sleep(3)
exit()
continue
else:
break
break
while True:
psd = input("请设置您的密码:").strip()
if len(psd) != 6 or psd in idcard or psd in simple_pas:
print("您的密码不应该与身份证号相同或者过于简单和格式不对")
continue
psd2 = input("请确认您的密码:")
print("密码保存成功!请您牢记!切勿告诉他人")
if psd == psd2:
mon = int(input("请输入您的预存余额:"))
if mon > 0:
cardnum = cls.getcardnum()
card = Card(cardnum, psd, mon)
user = User(name, idcard, phonenum, card)
cls.userDict[cardnum] = user
print("开卡成功,您的卡号为%s,请牢记..." % cardnum)
print(user_mas.format(phonenum, name, sex, cardnum))
today = datetime.datetime.today()
age = int(today.year) - int(idcard[6:10])
print(users.format(name, sex, age, phonenum, idcard, mon, cardnum))
break
else:
print("预存余额非法,开卡失败...")
else:
print("两次输入密码不一致,开卡失败...")
except:
print("输入错误!")
exit(0)
finally:
break
# 登录
@classmethod
def login(cls):
cardnum = input("请输入您的卡号:")
#判断卡号是否存在,卡号的存储用的是字典.get
user = cls.userDict.get(cardnum)
if user:
while True:
psd = input("请输入您的密码:")
if psd == user.card.password:
print("登录成功!!!")
cls.changshicishu = 0
cls.islogin = cardnum
break
else:
cls.changshicishu += 1
# 如果尝试次数大于三 将锁卡
if cls.changshicishu >= 3:
print("卡已被锁,请先解锁")
cls.islogin = False
print(cls.islogin)
break
else:
print("密码错误,请重新输入,还有%d次将锁卡" % (3 - cls.changshicishu))
else:
print("卡号不存在,请查证后登录...")
# 查询
@classmethod
def search(cls):
print(cls.islogin)
if cls.islogin:
print("您当前的余额为%d" % (cls.userDict.get(cls.islogin).card.money))
else:
print("请先登录")
# 取钱
@classmethod
def setmoney(cls):
if cls.islogin:
money = int(input("请输入您要取的金额:"))
print(cls.userDict.get(cls.islogin).card.money)
if cls.islogin:
if cls.userDict.get(cls.islogin).card.money - money >= 0:
print("取款%d成功!" % money)
cls.userDict.get(cls.islogin).card.money -= money
print("您卡里的余额为%d" % cls.userDict.get(cls.islogin).card.money)
else:
print("余额不足,取款失败!")
else:
print("未登录,请登录后再试")
else:
print("请先登录")
# 存钱
@classmethod
def getmoney(cls):
if cls.islogin:
while True:
gmoney = int(input("请输入您要存储的款项:"))
if gmoney > 0:
cls.userDict.get(cls.islogin).card.money += gmoney
print("您卡上的余额为%d" % cls.userDict.get(cls.islogin).card.money)
break
else:
print("输入有误,请重新输入金额")
else:
print("请先登录!")
# 转账
@classmethod
def zhuanzhang(cls):
if cls.islogin:
while 1:
kahao = input("您需要转到的卡号为:")
for x in cls.userDict.keys():
if x == kahao:
print("您要转的卡号为%s,持卡人为%s" % (x, cls.userDict[x].name))
amoney = int(input("您需要转的金额为"))
# 转账人卡内余额减少
cls.userDict.get(cls.islogin).card.money -= amoney
# 被转账人卡内余额增加
cls.userDict.get(x).card.money += amoney
else:
continue
print("卡号有误,请重新输入")
break
else:
print("请先登录!")
# 改密码
@classmethod
def gaimi(cls):
yanzhengma = ""
for x in range(6):
yanzhengma += str(random.randrange(0, 10))
reset_password = '''
+-------------------+
【中国农业银行】您正在尝试
修改密码,验证码为{}
请勿告诉他人
+-------------------+
'''
if cls.islogin:
count = 0
while True:
count += 1
print('已经向您的手机号发送了手机号')
print(reset_password.format(yanzhengma))
is_true = input("请输入验证码:").strip()
if is_true == yanzhengma:
count_set_pas = 0
while True:
count_set_pas += 1
mima1 = input("请输入您需要修改的密码:").strip()
mima2 = input("请再次输入修改的密码:").strip()
if mima1 == mima2:
cls.userDict.get(cls.islogin).card.password = mima1
print("您的新密码为%s" % mima1)
break
elif count_set_pas > 2:
print("三次改密失败!三秒后退出系统")
time.sleep(3)
exit()
else:
continue
elif count > 2:
print("三次验证码失败!三秒后退出系统")
time.sleep(3)
exit()
else:
print('验证码错误')
continue
break
else:
print("请先登录")
# 锁卡
@classmethod
def suoka(cls):
if cls.changshicishu >= 3:
print("卡以被锁,请先解锁")
# 解锁
@classmethod
def jiesuo(cls):
print("请输入您的卡号和密码")
kahao1 = input("请输入卡号:")
mima3 = input("请输入密码:")
for x in cls.userDict.keys():
if kahao1 == x:
if mima3 == cls.userDict.get(x).card.password:
print("解锁成功")
cls.islogin = cls.userDict.get(x).card.cardnum
else:
print("账号或者密码不正确,请重试")
else:
print("账号或者密码不正确,请重试")
# 注销
@classmethod
def zhuxiao(cls):
cls.islogin = False
print("注销成功")
if __name__ == '__main__':
ATM.welcome()
while True:
time.sleep(1)
print(ATM.userDict)
num = ATM.select()
if num == "2":
print("开户")
ATM.openUser()
elif num == "0":
print("退出")
break
elif num == "1":
print("登录")
ATM.login()
ATM.suoka()
elif num == "3":
print("查询")
ATM.search()
elif num == "4":
ATM.setmoney()
elif num == "5":
ATM.getmoney()
elif num == "6":
ATM.zhuanzhang()
elif num == "7":
ATM.gaimi()
elif num == "8":
ATM.zhuxiao()
elif num == "9":
ATM.jiesuo()
else:
print("选择有误请重新选择...")
四、比较
①功能和逻辑上,上一个都简单许多
②本文更想一个系统,不管是逻辑的判断,还是一些模拟操作上
③本文相当于是上一个的进阶,尤其是思维上的变化,要好好消化
|