Credit card validator in Python 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)) &lt; 13 or len(str(number)) &gt; 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()
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 &lt;= len(str(number)) &lt;= 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.