前言
12月3日的文章里,我们设计了isValid [1](#1)
一、题面(文字版)
(金融:信用卡号合法性)使用"字符串"输入作为一个信用卡号来改写编程题6.29
二、题面里的函数
python
# Return true if the card number is valid
def isValid(number):
# Get the result from Step 2
def sumOfDoubleEvenPlace(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)
三、Luhn运算流程图

四、def sumOfDoubleEvenPlace(number):偶数求和
python
def sumOfDoubleEvenPlace(number): #对偶数进行乘2,然后累加
lenNum = len(number) #量出字符串长度
for i in range(1,lenNum,2): #按隔一个进行一次的原则取偶数
print(number[-i],end=" ") #先打印看一下是否是偶数

4.1 我们做累加设计
4.1.1 print好还是return好呢??
python
def sumOfDoubleEvenPlace(number):
lenNum = len(number)
mulNum = 0
for i in range(1, lenNum, 2):
mulNum += int(number[-i])
return mulNum
sumNum =sumOfDoubleEvenPlace(a)
print(sumNum)
print(type(sumNum))

这个和我们之前的print好还是return好一个情况,打印是遍历一遍所有的偶数,可是return有一个结果就停了 [2](#2) [3](#3)
4.1.2 将return的缩进提前
python
def sumOfDoubleEvenPlace(number):
lenNum = len(number)
mulNum = 0
for i in range(1, lenNum, 2):
mulNum += int(number[-i])
return mulNum
a = "4388576018402626"
sumNum =sumOfDoubleEvenPlace(a)
print(f"{a} 偶数位相加等于",sumNum)
print("sumNum函数输出的类型",type(sumNum))

五、sumOfOddPace(number)奇数求和
5.1初期代码
python
def sumOfOddPace(number):
lenNum = len(number)#计算字符串长度
mulNum = 0
print(f"倒序显示字符串{number}的奇数位,如下: ")
for i in range(2, lenNum+2, 2):
if 2 * int(number[-i]) > 9:#如果相乘结果大于9就进行相加
mulNum=2*int(number[-i])#相乘结果存储器
a = str(mulNum) #将变量字符串话进行提取
print(int(a[0]) + int(a[1])) #将提取后的两个字符再次变回int进行相加
5.2简单累积
python
def sumOfOddPace(number):
lenNum = len(number)#计算字符串长度
mulNum = 0
mulNumThanNine = 0 #存储相乘结果大于9的累加变量
mulNumTotal = 0 #存储相乘小于9的累加变量
print(f"倒序显示字符串{number}的奇数位,如下: ")
for i in range(2, lenNum+2, 2):
if 2 * int(number[-i]) > 9:#如果相乘结果大于9就进行相加
mulNum = 2 * int(number[-i])#相乘结果存储器
a = str(mulNum) #将变量字符串话进行提取
mulNumThanNine +=int(a[0]) + int(a[1]) #将提取后的两个字符再次变回int进行相加
else:#如果相乘结果小于2
mulNumTotal += 2 * int(number[-i])
return mulNumThanNine + mulNumTotal #将两种结果进行相加
a = "4388576018402626"
print("对奇数进行相乘和相加最后得到的结果",sumOfOddPace(a))
print("结果的type为整数",type(sumOfOddPace(a)))

六、奇数偶数求和并且进行整除判断
python
识别银行卡
def isValid(number):
lenNum = len(number) # 识别银行卡字符串长度
if 13 <= lenNum <= 16: # 如果银行卡长度在13到16之间就识别属于什么类银行卡
if number[0] == "4" and getResult(number) is True: # 如果头一个字符是4则是visa卡
print(f"银行卡{number}是Visa卡")
elif number[0] == "5" and getResult(number) is True:
print(f"银行卡{number}是Master卡")
elif number[:2] == "37" and getResult(number) is True:
print(f"银行卡{number}是American Express卡")
elif number[0] == "6" and getResult(number) is True:
print(f"银行卡{number}是Discover卡")
else: # 如果不符合则显示磁卡
print(f"{number},此卡无法识别,请您提供该卡类型给管理员")
else:
print(f"{number}不是银行卡,请您重新输入,或联系管理员")
def sumOfDoubleEvenPlace(number):
lenNum = len(number)
mulNum = 0
for i in range(1, lenNum, 2):
mulNum += int(number[-i])
return mulNum
def sumOfOddPace(number):
lenNum = len(number)#计算字符串长度
mulNum = 0
mulNumThanNine = 0 #存储相乘结果大于9的累加变量
mulNumTotal = 0 #存储相乘小于9的累加变量
for i in range(2, lenNum+2, 2):
if 2 * int(number[-i]) > 9:#如果相乘结果大于9就进行相加
mulNum = 2 * int(number[-i])#相乘结果存储器
a = str(mulNum) #将变量字符串话进行提取
mulNumThanNine +=int(a[0]) + int(a[1]) #将提取后的两个字符再次变回int进行相加
else:#如果相乘结果小于2
mulNumTotal += 2 * int(number[-i])
return mulNumThanNine + mulNumTotal #将两种结果进行相加
def getResult(number):
sumTotal = sumOfDoubleEvenPlace(number) + sumOfOddPace(number) #奇数偶数结果相加
if sumTotal % 10 == 0: #对结果进行整除,能除尽为合格卡号
print("用户输入的此银行卡号是有效")
return True
else:
print("用户输入的此银行卡号不是有效格式,请检查后重新输入")
return False
def main():
a = isValid("4388576018402626")
b = isValid("438852601840707") # visa卡
c = isValid("5388576018402626") # Master卡
d = isValid("3788576018402626") # American Express卡
e = isValid("6388576018402626") # Discover卡
main()

IndexError:string index out of range
不对呀。sumOfOddPace(number):之前是好使的。大家可以看第四节,怎么到这里就不好使了呢?

没有加入到isValid的sumOfOddPace是可用的呀?
问题
当卡号长度为奇数(比如438852601840707是 15 位),lenNum+2会导致i超出字符串索引范围:
例:15 位卡号lenNum=15,循环range(2,17,2)会生成2,4,6,8,10,12,14,16,当i=16时,number[-16]超出 15 位字符串的索引范围(15 位字符串倒数索引最大是 - 15),所以直接报IndexError: string index out of range
解决
吸取了教训我之前在面对偶数位卡号时写的是for i in range(2, lenNum+2, 2):,其实循环范围改为:从2开始,到lenNum+1(而非lenNum+2),步幅2
七 最终解决代码
python
# 识别银行卡
def isValid(number):
lenNum = len(number) # 识别银行卡字符串长度
if 13 <= lenNum <= 16: # 如果银行卡长度在13到16之间就识别属于什么类银行卡
if number[0] == "4" and getResult(number) is True: # 如果头一个字符是4则是visa卡
print(f"银行卡{number}是Visa卡")
elif number[0] == "5" and getResult(number) is True:
print(f"银行卡{number}是Master卡")
elif number[:2] == "37" and getResult(number) is True:
print(f"银行卡{number}是American Express卡")
elif number[0] == "6" and getResult(number) is True:
print(f"银行卡{number}是Discover卡")
else: # 如果不符合则显示磁卡
print(f"{number},此卡无法识别,请您提供该卡类型给管理员")
else:
print(f"{number}不是银行卡,请您重新输入,或联系管理员")
def sumOfDoubleEvenPlace(number):
lenNum = len(number)
mulNum = 0
for i in range(1, lenNum, 2):
mulNum += int(number[-i])
return mulNum
def sumOfOddPlace(number):
lenNum = len(number)#计算字符串长度
mulNumThanNine = 0 #存储相乘结果大于9的累加变量
mulNumTotal = 0 #存储相乘小于9的累加变量
for i in range(2, lenNum+1, 2):
if 2 * int(number[-i]) > 9:#如果相乘结果大于9就进行相加
mulNum = 2 * int(number[-i])#相乘结果存储器
a = str(mulNum) #将变量字符串话进行提取
mulNumThanNine +=int(a[0]) + int(a[1]) #将提取后的两个字符再次变回int进行相加
else:#如果相乘结果小于2
mulNumTotal += 2 * int(number[-i])
return mulNumThanNine + mulNumTotal #将两种结果进行相加
def getResult(number):
sumTotal = sumOfDoubleEvenPlace(number) + sumOfOddPlace(number) #奇数偶数结果相加
if sumTotal % 10 == 0: #对结果进行整除,能除尽为合格卡号
print("用户输入的此银行卡号是有效")
return True
else:
print("用户输入的此银行卡号不是有效格式,请检查后重新输入")
return False
def main():
a = isValid("4388576018402626")# 非visa卡
b = isValid("438852601840707") # 非visa卡
c = isValid("5388576018402626") # 非Master卡
d = isValid("3788576018402626") # 非American Express卡
e = isValid("6388576018402626") # Discover卡
main()

八 小技巧简化版奇数位求和
将sumOfOddPlace的"翻倍后两位数相加" 简化为 "减 9"
(比如 12→1+2=3=12-9,16→1+6=7=16-9),
翻倍后若为两位数,直接减 9 等价于 "各位相加"(如 12-9=3,16-9=7),代码中可直接用doubled - 9,无需判断位数。
python
def sumOfOddPlace(number): # 修正函数名拼写
lenNum = len(number)
mulNumThanNine = 0
mulNumTotal = 0
# 循环范围改为:从2开始,到lenNum+1(而非lenNum+2),步幅2
for i in range(2, lenNum+1, 2):
digit = int(number[-i]) # 取倒数第i位(奇数位,需要翻倍)
doubled = digit * 2
if doubled > 9:
# 简化:两位数相加 = 减9(比如12→3=12-9,16→7=16-9)
mulNumThanNine += doubled - 9
else:
mulNumTotal += doubled
return mulNumThanNine + mulNumTotal
"你还遇到过哪些字符串索引的坑?评论区聊聊~"