2
\$\begingroup\$

I have began taking the CS50 course on EDX the past couple of days, and one of the tasks to accomplish was to write a credit card validator in C. I wrote it in C, and then I thought that I could go about the same thing in Python, and wrote the same program in Python. For those of you unfamiliar with the problem, here is the description.

Because I took the program and converted from C to Python, it is probably not going to be written in the most Pythonic way. I tried to add some Pythonic ways of doing things, but there are probably many more things I could have done. If you find anything that could be done in a better, faster, or more Pythonic way, please let me know. Thanks.

def main():
 # cc_number = int(input("Enter a valid credit card number: "))
 cc_number = 12345678912356789
 if not checksum(cc_number):
 print("INVALID")
 else:
 print(check_provider(cc_number))
def check_provider(number):
 if len(str(number)) < 13 or len(str(number)) > 16:
 return 'INVALID'
 if ((list(str(number)))[:2]) == ['3', '4'] or ((list(str(number)))[:2]) == ['3', '7']:
 return 'AMEX'
 elif ((list(str(number)))[:2]) == ['5', '1'] or ((list(str(number)))[:2]) == ['5', '2'] \
 or ((list(str(number)))[:2]) == ['5', '3'] or ((list(str(number)))[:2]) == ['5', '4'] \
 or ((list(str(number)))[:2]) == ['5', '5']:
 return 'MASTERCARD'
 elif ((list(str(number)))[0]) == '4':
 return 'VISA'
 else:
 return 'INVALID'
def checksum(number):
 list_number = list(str(number))
 odd_indices = []
 even_indices = []
 last_index = len(list_number) - 1
 rev_list = list(reversed(list_number))
 for i in rev_list[1::2]:
 odd_indices.append(i)
 for i in rev_list[::2]:
 even_indices.append(i)
 sum_odd = sum(split_to_digits(''.join(int_to_str(mul(odd_indices, 2)))))
 sum_even = sum(split_to_digits(''.join(int_to_str(even_indices))))
 s = sum_odd + sum_even
 print(s)
 if s % 10 == 0:
 return True
 return False
def mul(list, x):
 return [(int(n) * 2) for n in list]
def split_to_digits(n):
 return [int(i) for i in str(n)]
def int_to_str(n):
 return [str(x) for x in n]
def str_to_int(n):
 return [int(x) for x in n]
main()
200_success
145k22 gold badges190 silver badges478 bronze badges
asked Jan 30, 2017 at 15:32
\$\endgroup\$

1 Answer 1

5
\$\begingroup\$

General notes:

  • use if __name__ == '__main__': to avoid the main() function to be executed when the module is imported
  • I'd pass around the credit card number as a string instead of converting it to string in every single validation step
  • add docstrings to each of the defined functions

Regarding check_provider() function:

  • you can check the length to be in range in one go:

    if not(13 <= len(str(number)) <= 16):
    
  • I would improve the way you distinguish between cards by introducing a mapping between brands and regular expressions (like it was done in pycard module). Then, match each of the expressions one by one until you find a match or a brand was not found:

    import re
    BRANDS = {
     'Visa': re.compile(r'^4\d{12}(\d{3})?$'),
     'Mastercard': re.compile(r'''
     ^(5[1-5]\d{4}|677189)\d{10}$| # Traditional 5-series + RU support
     ^(222[1-9]|2[3-6]\d{2}|27[0-1]\d|2720)\d{12}$ # 2016 2-series
     ''', re.VERBOSE),
     'American Express': re.compile(r'^3[47]\d{13}$'),
     'Discover': re.compile(r'^(6011|65\d{2})\d{12}$'),
    }
    def check_provider(number):
     """Checks a credit card number and returns a matching brand name, or INVALID if no brand matched."""
     for brand, regexp in BRANDS.items():
     if regexp.match(number):
     return brand
     return 'INVALID'
    

Regarding implementing the Luhn algorithm, check the pycard's implementation - it is quite clean and understandable.

answered Jan 30, 2017 at 18:13
\$\endgroup\$
0

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.