【问题标题】:Python Credit Card ValidationPython信用卡验证
【发布时间】:2017-04-02 23:00:03
【问题描述】:

我是一名 Python 初学者,目前正在研究 Luhn 算法来检查信用卡验证。我编写了大部分代码,但是我遇到了 2 个错误,我得到的第一个错误是在分配之前引用了 num。我得到的第二个是'_io.TextIOWrapper'类型的对象没有len()。进一步的帮助/指导将不胜感激。

这些是 Luhn 算法(Mod10 检查)的步骤

  1. 从右到左每隔一个数字加一次。如果这个“加倍”的结果是两位数,则将两位数相加 获得一位数。
  2. 现在添加步骤 1 中的所有个位数。
  3. 在信用卡号的奇数位上从右到左添加所有数字。
  4. 对第 2 步和第 3 步的结果求和。
  5. 如果第4步的结果能被10整除,则卡号有效;否则无效。

这就是我的输出应该是什么

Card Number         Valid / Invalid
--------------------------------------
3710293             Invalid
5190990281925290    Invalid
3716820019271998    Valid
37168200192719989   Invalid
8102966371298364    Invalid
6823119834248189    Valid

这是代码。

def checkSecondDigits(num):
    length = len(num)
    sum =  0
    for i in range(length-2,-1,-2):
      number = eval(num[i])
      number = number * 2
      if number > 9:
          strNumber = str(number)
          number = eval(strNumber[0]) + eval(strNumber[1])
          sum += number
      return sum

def odd_digits(num):
    length = len(num)
    sumOdd = 0
    for i in range(length-1,-1,-2):
        num += eval(num[i])
    return sumOdd

def c_length(num):
    length = len(num)
    if num >= 13 and num <= 16:
    if num [0] == "4" or num [0] == "5" or num [0] == "6" or (num [0] == "3" and num [1] == "7"):
        return True
    else:
        return False


def main():
    filename = input("What is the name of your input file? ")
    infile= open(filename,"r")
    cc = (infile.readline().strip())
    print(format("Card Number", "20s"), ("Valid / Invalid"))
    print("------------------------------------")
    while cc!= "EXIT":
        even = checkSecondDigits(num)
        odd = odd_digits(num)
        c_len = c_length(num)
        tot = even + odd

        if c_len == True and tot % 10 == 0:
            print(format(cc, "20s"), format("Valid", "20s"))
        else:
            print(format(cc, "20s"), format("Invalid", "20s"))
        num = (infile.readline().strip())

main()

【问题讨论】:

  • 您应该提供回溯,而不仅仅是错误消息
  • even = checkSecondDigits(num)... 检查这一行。什么是数字?这是你的第一个错误
  • 回溯(最近一次调用最后一次):第 58 行,在 main() 第 48 行,在 main 中 even = checkSecondDigits(num) UnboundLocalError: 在赋值之前引用了局部变量 'num'
  • 运行代码时出现此错误
  • 检查你的while,这个num变量来自哪里?

标签: python function validation python-3.x luhn


【解决方案1】:

你只是忘了初始化 num

def main():
    filename = input("What is the name of your input file? ")
    infile= open(filename,"r")
    # initialize num here
    num = cc = (infile.readline().strip())
    print(format("Card Number", "20s"), ("Valid / Invalid"))
    print("------------------------------------")
    while cc!= "EXIT":
        even = checkSecondDigits(num)
        odd = odd_digits(num)
        c_len = c_length(num)
        tot = even + odd

        if c_len == True and tot % 10 == 0:
            print(format(cc, "20s"), format("Valid", "20s"))
        else:
            print(format(cc, "20s"), format("Invalid", "20s"))
        num = cc = (infile.readline().strip())

【讨论】:

  • 他居然在else下面初始化了。
  • 你是个救命的兄弟。非常感谢
  • 只能将 cc 重命名为 num
【解决方案2】:

首先,也许你应该删除多余的字符:

def format_card(card_num):
    """
    Formats card numbers to remove any spaces, unnecessary characters, etc
    Input: Card number, integer or string
    Output: Correctly formatted card number, string
    """
    import re
    card_num = str(card_num)
    # Regex to remove any nondigit characters
    return re.sub(r"\D", "", card_num)

使用 Luhn 算法检查信用卡是否有效后:

def validate_card(formated_card_num):
    """
    Input: Card number, integer or string
    Output: Valid?, boolean
    """
    double = 0
    total = 0

    digits = str(card_num)

    for i in range(len(digits) - 1, -1, -1):
        for c in str((double + 1) * int(digits[i])):
            total += int(c)
        double = (double + 1) % 2

    return (total % 10) == 0

【讨论】:

  • 这是 Luhn 算法的一个实现,是的,但是 OP 是在寻求帮助以找出他们的错误,而不是在寻求它的实现
【解决方案3】:

这是一个非常简单的代码版本,它基于 lunh 算法

def validator(n):

    validatelist=[]

    for i in n:
        validatelist.append(int(i))


    for i in range(0,len(n),2):


        validatelist[i] = validatelist[i]*2

        if validatelist[i] >= 10:

            validatelist[i] = validatelist[i]//10 + validatelist[i]%10


    if sum(validatelist)%10 == 0:
        print('This a valid credit card') 

    else:
        print('This is not valid credit card')

def cardnumber():

    result=''
    while True:
        try:
            result = input('Please enter the 16 digit credit card number : ')

            if not (len(result) == 16) or not type(int(result) == int) :
                raise Exception

        except Exception:    
            print('That is not a proper credit card number. \nMake sure you are entering digits not characters and all the 16 digits.')
            continue

        else:
            break


    return result

def goagain():
    return input('Do you want to check again? (Yes/No) : ').lower()[0] == 'y'

def main():

    while True:

        result = cardnumber()
        validator(result)


        if not goagain():
            break

if __name__ == '__main__':
    main()

【讨论】:

    【解决方案4】:

    旧线程,但答案与我有关……真正的问题并未确定。 实际上,错误是您在主线中调用函数时将 checkSecondDigits 定义为参数的标识符/名称时使用了参数的标识符(num)。该函数应在 main() 中调用 even = checkSecondDigits(cc) 因此 cc 中的值(即参数)被传递给 num (作为参数)以在函数中使用。 使用odd_digits 和cc_length 也会出现同样的菜鸟错误。

    这个问题(以及最初建议的答案)表明了对将参数传递给参数的基本误解...... 建议的 num 的“声明”只是隐藏了这个错误/误解,并且混淆了 num (应该只是本地的)和 cc (它是全局的)的本地和全局范围,所以虽然这个建议在这种情况下有效,但它适用于错误的原因,糟糕的风格和糟糕的编程。

    【讨论】:

    • 这并没有提供问题的答案。一旦你有足够的reputation,你就可以comment on any post;相反,provide answers that don't require clarification from the asker。 - From Review
    • 其实它确实提供了答案。它准确地说明了原始海报的错误是什么,并准确地描述了如何解决它。很遗憾看起来有足够声誉的贡献者可以给出错误的答案!显然声誉!=知识,必然。发布错误诊断问题的代码,然后建议对它的错误答案应该被调出。如果这是司空见惯的事情,请对 stackoverflow 的声誉表示不满...
    【解决方案5】:

    此外, num 不应出现在 main() 中的任何位置,因为它应该是被调用的函数的本地(仅出现在其中)... 这段代码的最后一行应该和第一行一样,但是最后一行错误地将数据赋给了num而不是cc

    cc = (infile.readline().strip())
    print(format("Card Number", "20s"), ("Valid / Invalid"))
    print("------------------------------------")
    while cc!= "EXIT":
        even = checkSecondDigits(num)
        odd = odd_digits(num)
        c_len = c_length(num)
        tot = even + odd
    
        if c_len == True and tot % 10 == 0:
            print(format(cc, "20s"), format("Valid", "20s"))
        else:
            print(format(cc, "20s"), format("Invalid", "20s"))
        num = (infile.readline().strip())
    

    【讨论】:

      【解决方案6】:

      您可以使用我的代码进行卡片验证,它是 100% 动态的,因为卡片结构存储在 CSV 文件中,因此很容易更新这里的代码是 GitHub profilepython file linkcode explanation file linkCSV for datafile link

      python 代码:

      # -*- coding: utf-8 -*-
      """
      Created on Tue Sep 10 20:55:30 2019
      @author: Preyash2047@gmail.com
      """
      
      
      import csv
      import numpy as np
      
      #csv file imported and storf in reader
      reader = csv.DictReader(open("card_data.csv"))
      
      #input card number
      card_number = input("Enter the card No: ")
      
      #global variable declaration
      min_digits=0
      max_digits=0
      card_number_list = list(card_number)
      card_number_list_reverse=card_number_list[::-1]
      card_number_length=len(card_number_list)
      first_digit = int(card_number_list[0])
      
      #global variable for final output
      card_provider_list_number = 0
      result_found = False
      card_number_digits = 0
      mit_name=""
      
      #list
      start=[]
      end=[]
      name=[]
      c_d=[]
      number_length=[]
      min_max_digits_list=[]
      
      #append the list from csv
      for raw in reader:
          start.append(raw['start'])
          end.append(raw['end'])
          name.append(raw['name'])
          c_d.append(raw['c_d'])
          number_length.append(raw['number_length'])
      
      #initialize the value of min_digits & max_digits
      def min_max_digits():
          global min_digits
          global max_digits
          for i in range(len(start)):
              available_length=number_length[i].split(',')
              for j in range(len(available_length)):
                  min_max_digits_list.append(available_length[j])
          min_max_digits_array = np.array(min_max_digits_list) 
          np.unique(min_max_digits_array)
          min_digits=int(min(min_max_digits_array))
          max_digits=int(max(min_max_digits_array))
      
      #list to int
      def list_to_int(noofdigits): 
          str1 = ""
          return int(str1.join(noofdigits))
      
      #card validation
      def iin_identifier():
          first_six_digit = list_to_int(card_number_list[0:6])
          for i in range(len(start)):
              if(first_six_digit >= int(start[i]) and first_six_digit <= int(end[i])):
                  available_length=number_length[i].split(',')
                  for j in range(len(available_length)):
                      if(card_number_length == int(available_length[j])):
                          global card_provider_list_number
                          card_provider_list_number = i
                          global card_number_digits
                          card_number_digits = available_length[j]
                          global result_found
                          result_found = True
      
      #Major Industry Identifier (MII) identification
      def mit_identifier():
          global first_digit
          global mit_name
          switcher = { 
               1: "Airlines",
               2: "Airlines",
               3: "Travel and Entertainment",
               4: "Banking and Financial Services",
               5: "Banking and Financial Services",
               6: "Merchandising and Banking",
               7: "Petroleum",
               8: "Health care, Telecommunications",
               9: "National Assignment"
          }
          mit_name=switcher.get(first_digit, "MIT Identifier Not Found") 
      
      #Luhn Algorithm or modulo-10 Algorithm
      def luhn_algorithm():
          for i in range(card_number_length):
              if(i%2!=0 and i!=0):
                  card_number_list_reverse[i]=int(card_number_list_reverse[i])*2
                  #print(str(i)+" "+ str(card_number_list_reverse[i]))
                  if(len(str(card_number_list_reverse[i]))==2):
                      even_number_2=list(str(card_number_list_reverse[i]))
                      card_number_list_reverse[i] = int(even_number_2[0])+int(even_number_2[1])
                      #print("\tsubsum "+str(i)+" "+str(card_number_list_reverse[i]))
              else:
                  card_number_list_reverse[i]=int(card_number_list_reverse[i])
          division_int = int(sum(card_number_list_reverse)/10)
          division_float=sum(card_number_list_reverse)/10
          if(division_int-division_float==0):
              return True
      
      #initial level number length validation
      def card_number_validation():
          min_max_digits()
          if(card_number_length>= min_digits and card_number_length <= max_digits and first_digit != 0):
              iin_identifier()
              mit_identifier()
              if(result_found and luhn_algorithm()):
                  print("\nEntered Details are Correct\n")
                  print("\nHere are the some details we know about you card")
                  print("\nNo: "+card_number)
                  print("\nIssuing Network: "+name[card_provider_list_number])
                  print("\nType: "+c_d[card_provider_list_number]+" Card")
                  print("\nCategory of the entity which issued the Card: "+mit_name)
              else:
                  print("\nCard Number is Invalid\nPlease renter the number!\n")
          else:
              print("\nCard Number is Invalid\n")
      
      #method called to run program
      card_number_validation()
      

      【讨论】:

        【解决方案7】:
        n = input("Enter 16-digit Credit Card Number:")
        lst = []
        for i in range(16):
            lst.append(n[i])
        # print(lst)
        # list1 = n.split()
        # print(list1)
        
        
        def validate_credit_card():
            global lst
            if len(lst) == 16:
                for i in range(0, len(lst)):
                    lst[i] = int(lst[i])
                # print(lst)
                last = lst[15]
                first = lst[:15]
                # print(first)
                # print(last)
                first = first[::-1]
                # print(first)
                for i in range(len(first)):
                    if i % 2 == 0:
                        first[i] = first[i] * 2
                    if first[i] > 9:
                        first[i] -= 9
                sum_all = sum(first)
                # print(first)
                # print(sum_all)
                t1 = sum_all % 10
                t2 = t1 + last
                if t2 % 10 is 0:
                    print("Valid Credit Card")
                else:
                    print("Invalid Credit Card!")
            else:
                print("Credit Card number limit Exceeded!!!!")
                exit()
        
        
        if __name__ == "__main__":
            validate_credit_card()
        

        【讨论】:

        • 卢恩公式: 1.删除数字的最后一位。最后一位是我们要检查的数字 2. 反转数字 3. 将奇数位(1、3、5 等)的数字乘以 2,然后将所有高于 9 的结果减去 9 4. 将所有数字加在一起 ​​5.校验位(卡的最后一个数字)是您需要添加的金额才能获得 10 的倍数(模 10)
        猜你喜欢
        • 2021-09-24
        • 2020-09-15
        • 2014-08-14
        • 2014-01-30
        • 2015-06-04
        • 2016-01-22
        • 2011-01-24
        • 2012-08-14
        • 2016-11-15
        相关资源
        最近更新 更多