一、题面(文字版)
(金融:信用卡号合法性)使用"字符串"输入作为一个信用卡号来改写编程题6.29
二、题面里的函数
python
# Return true if the card number is valid
def isValid(number):
# Get the result from Step 2
def sumOfFoubleEvenPlace(number):
# Return this number if it is a single digit, otherwise, return
# the sum of the two digits
def getDigit(number):
# Return sum of odd place digits in number
def sumOfOddPlace(number):
# Return true, if the digit d is a prefix for number
def perfixMatched(number,d):
# Return the number of digits in d
def getSize(d):
# Return the first k number of digits from number. If the
# number of digits in number is less than k, return number.
def getPerfix(number,k)
三 识别卡号有效
信用卡号必须是13位到16位,且数字开头需满足以下
- 4是指Visa卡 16位
- 5是指Master卡 16位
- 37是指American Express卡 15位
- 6是指Discover卡 16
3.1 输入设计
* 问题1 是先把字符串变成整数,还是一个一个把字符变成整数??
python
#先把银行卡直接变成整数
def isValid(number):
# 用户银行卡号输入模块
digitNum = int(number)
print("用户输入的银行卡", digitNum)
# 对用户输入的银行卡进行甄别模块
if 13 < digitNum < 16: # 如果银行卡长度在13到16之间就识别属于什么类银行卡
if digitNum == 4:
print(f"银行卡{digitNum}是Visa卡")
elif digitNum == 5:
print(f"银行卡{digitNum}是Master卡")
elif digitNum == 37:
print(f"银行卡{digitNum}是American Express卡")
elif digitNum == 6:
print(f"银行卡{digitNum}是Discover卡")
else:
print(f"{digitNum},此卡有问题")
else:
print("不是合格的银行卡")
def main():
a = isValid("10")
b = isValid("4388576018402626")
print(type(a)) #利用type来看看isValid的属性
print(type(b)) #利用type来看看isValid的属性
main()

这个结果似乎不对。我们来分析一下
我们先把银行卡 4388576018402626转换成了整数,看似很对,可此时的4388576018402626其实是 4,388,576,018,402,626就变成了4千万亿这个超级大的整数。

* 分析
从图2中可以看出这个函数无法进行字符串操作。我们这个函数def isValid(number):看似处理的是整数,但实际上是字符串。所以问题1先把字符串变成整数是不行的。
* 计划
我们应该利用第8章学的切片技术逐一把银行卡号单独提取成数字。当然如果仅仅是识别银行卡属于哪种类型。我的意思也可以不使用转为整数形式。但是逐一切片然后进行字符与字符之间的对比也是可以的。
实施过程中问题
1、if范围是<还是 <=?
13小于lenNum小于16这恰恰将范围限制到了12和15之间,没法进行我们初期的设计即长度在13到16之间,所以我们要加上小于等于<=

2、lenNum[0]还是number[0]?
我们用lenNum来进行
结果TypeError: 'int' object is not subscriptable
我们的目的是利用字符串切片取lenNum中的第一个字符,其实是取银行卡中的第1位
lenNum是利用len后的银行卡长度,而不是银行卡本身
所以我们应该用isValid(number)的numbert

3、if number[0] == 4:还是if number[0] == "4":
我们看一下结果

我处理了lenNum但是这里又忽略了4,应该是字符'4'而不是整数4
3.2 增加全数字验证逻辑
比如"4a88576018402626"会误判为 Visa 卡
python
def isValid(number):
# 新增:验证是否全为数字
if not number.isdigit():
print(f"{number}含非数字字符,不是合法银行卡号")
return
lenNum =len(number) #识别银行卡字符串长度
if 13 <= lenNum <= 16 : # Visa/Master/Discover:13/16位;American Express:15位
if number[0] == '4':# 如果头一个字符是4则是visa卡
print(f"银行卡{number}是Visa卡")
return True #返回True表示验证成功
elif number[0] == '5':
print(f"银行卡{number}是Master卡")
return True #返回True表示验证成功
elif number[0:2] == '37':
print(f"银行卡{number}是American Express卡")
return True #返回True表示验证成功
elif number[0] == '6':
print(f"银行卡{number}是Discover卡")
return True #返回True表示验证成功
else: #如果不符合则显示磁卡
print(f"{number},此卡无法识别,请您提供该卡类型给管理员")
return False
else:
print(f"{number}不是银行卡,请您重新输入,或联系管理员")
return False
def main():
a = isValid("10") # 故意输入的非法数
b = isValid("4388576018402626") #visa卡
c = isValid("5388576018402626") #Master卡
d = isValid("3788576018402626") #American Express卡
e = isValid("6388576018402626") #Discover卡
main()
最终结果

3.3 细化代码
python
#识别银行卡
def isValid(number):
# 新增:验证是否全为数字
if not number.isdigit():
print(f"{number}含非数字字符,不是合法银行卡号")
return
lenNum =len(number) #识别银行卡字符串长度
if 13 <= lenNum <= 16 : # Visa/Master/Discover 16位;American Express:15位
if number[0] == '4' and lenNum == 16:# 如果头一个字符是4则是visa卡
print(f"银行卡{number}是Visa卡")
return True #返回True表示验证成功
elif number[0] == '5' and lenNum == 16:
print(f"银行卡{number}是Master卡")
return True #返回True表示验证成功
elif number[0:2] == '37' and lenNum == 15:
print(f"银行卡{number}是American Express卡")
return True #返回True表示验证成功
elif number[0:4] == '6011' and lenNum == 16:
print(f"银行卡{number}是Discover卡")
return True #返回True表示验证成功
else: #如果不符合则显示磁卡
print(f"{number},此卡无法识别,请您提供该卡类型给管理员")
return False
else:
print(f"{number}不是银行卡,请您重新输入,或联系管理员")
return False
def main():
a = isValid("10") # 故意输入的非法数
b = isValid("4388576018402626") #visa卡
c = isValid("5388576018402626") #Master卡
d = isValid("3788576018402626") #American Express卡
e = isValid("6388576018402626") #非Discover卡
d = isValid("6011576018402626") #Discover卡
main()
