Style
Python has a style guide called PEP 8. It is a good habit to try to follow it.
In your case, that would mean fixing the missing whitespaces, removing parenthesis in if(result).
Also, you could get rid of old commented code and add a proper docstring if you want to describe the behavior of the function.
Tests
It could be a good idea to write tests before trying to improve your code.
I wrote a very simple code but you could get this chance to dive into unit testing frameworks:
TESTS = [
(1456734512345698, False),
(4539869650133101, True),
(1456734512345698, False),
(5239512608615007, True),
]
for (card_number, expected_valid) in TESTS:
valid = validate_credit_card_number(card_number)
assert valid == expected_valid
Useless test
At the end of the function, you can return directly:
return final_sum % 10 == 0
Useless variables
The my_list variable is not required.
Also, we can take this chance to get rid of the variables at the end of the function:
return (sum(t_list) + sum(list2)) % 10 == 0
Conversion of card_number
At the beginning of the function, you could convert the parts of card_number directly to integer so that you do it in a single place.
Also, that removed the need to the call of list. We just have:
temp_list = [int(c) for c in str(card_number)]
And we can get rid of the line:
list2 = [int (n) for n in list2]
At this stage, the code looks like:
def validate_credit_card_number(card_number):
temp_list = [int(c) for c in str(card_number)]
list1 = temp_list[-2::-2]
list1 = [2 * n for n in list1]
list2 = temp_list[::-2]
t_list = list1
for el in list1:
sum_res = 0
if el > 9:
idx = list1.index(el)
t_list.pop(idx)
while el:
rem = el % 10
sum_res += rem
el = el // 10
t_list.insert(idx, sum_res)
return (sum(t_list) + sum(list2)) % 10 == 0
Yet another useless variable
t_list aliases list1 (I am not sure if this is intended if if you were planning to have a copy of list1). Whenever you update the list through one variable, the other is affected as well. I highly recommend Ned Batchelder's talk about names and values.
In your case, we can get rid of t_list completely without changing the behavior of the function.
Simplify list logic
You go through multiple steps to modify list1 (or t_list) : index, pop, index. These steps are more expensive/complicated than required. At the end of the day, you do not care about list1, you just want its final sum. You could keep track of the sum directly:
sum1 = 0
for el in list1:
if el > 9:
sum_res = 0
while el:
rem = el % 10
sum_res += rem
el = el // 10
sum1 += sum_res
else:
sum1 += el
return (sum1 + sum(list2)) % 10 == 0
We can take this chance to perform the multiplication in the loop to remove a list comprehension.
Also, we can initialise the sum with sum(list2) so that we don't have to add them at the end:
def validate_credit_card_number(card_number):
temp_list = [int(c) for c in str(card_number)]
list1 = temp_list[-2::-2]
list2 = temp_list[::-2]
total_sum = sum(list2)
for el in list1:
el *= 2
if el > 9:
sum_res = 0
while el:
rem = el % 10
sum_res += rem
el = el // 10
total_sum += sum_res
else:
total_sum += el
return total_sum % 10 == 0
Math logic
The code uses 10 (the base used for computations) everywhere except for one 9 which seems unexpected. You could write: el >= 10 instead.
Also, that check is not required because the logic applies exactly the same way for elements smaller than 10:
for el in list1:
el *= 2
sum_res = 0
while el:
rem = el % 10
sum_res += rem
el = el // 10
total_sum += sum_res
Also, you could use el //= 10 but you can get the best ouf of the Python builtins by using divmod returning both the quotient and the remainder:
while el:
el, rem = divmod(el, 10)
sum_res += rem
total_sum += sum_res
Then, it becomes clear that the variable sum_res is not really required as we could use total_sum instead:
while el:
el, rem = divmod(el, 10)
total_sum += rem
"Final" code
def validate_credit_card_number(card_number):
temp_list = [int(c) for c in str(card_number)]
list1 = temp_list[-2::-2]
list2 = temp_list[::-2]
total_sum = sum(list2)
for el in list1:
el *= 2
while el:
el, rem = divmod(el, 10)
total_sum += rem
return total_sum % 10 == 0
TESTS = [
(1456734512345698, False),
(4539869650133101, True),
(1456734512345698, False),
(5239512608615007, True),
]
for (card_number, expected_valid) in TESTS:
valid = validate_credit_card_number(card_number)
assert valid == expected_valid
More simplification
Thinking about it, things can still be simplified a lot.
What you are doing with the while loop can be performed using str conversion:
total_sum = sum(list2)
for el in list1:
total_sum += sum(int(c) for c in str(2 * el))
Going further (too far?), this leads to:
def validate_credit_card_number(card_number):
temp_list = [int(c) for c in str(card_number)]
list1 = temp_list[-2::-2]
list2 = temp_list[::-2]
total_sum = sum(list2) + sum(sum(int(c) for c in str(2 * el)) for el in list1)
return total_sum % 10 == 0
Edit:
More simplification
We are using str and int to get the digits of a number... which is known to be smaller than 18 (2 * 9).
A trick could be, once again, to use divmod returning the quotient and remainder and use sum on it.
total_sum = sum(list2)
for el in list1:
total_sum += sum(divmod(2 * el, 10))
or
total_sum = sum(list2) + sum(sum(divmod(2 * el, 10)) for el in list1)
Playing with indices
Instead of splitting the list into 2 lists, we could iterate over the (reversed) list once and handle differently elements at odd positions and elements at even positions.
We'd get something like:
def validate_credit_card_number(card_number):
temp_list = [int(c) for c in str(card_number)]
total_sum = 0
for i, e in enumerate(reversed(temp_list)):
if i % 2 == 0:
total_sum += e
else:
total_sum += sum(divmod(2 * e, 10))
return total_sum % 10 == 0
Or the more concise solution taking advantage of the fact that the divmod trick works for both cases:
def validate_credit_card_number(card_number):
total_sum = 0
for i, c in enumerate(reversed(str(card_number))):
e = int(c) * (2 if i % 2 else 1)
total_sum += sum(divmod(e, 10))
return total_sum % 10 == 0
or
def validate_credit_card_number(card_number):
return sum(sum(divmod(int(c) * (2 if i % 2 else 1), 10))
for i, c in enumerate(reversed(str(card_number)))) % 10 == 0