问题
I'm having some difficulties with my code in python. I want to create a code which will check if the number of a credit card is valid. But it keep showing me the message:
Traceback (most recent call last):
File "C:\Users\George\Desktop\FRONTISTHRIAKH ASKHSH 6.py", line 14, in <module>
if int(x[0][0])>4 and int(x[0][0])<7:
TypeError: 'builtin_function_or_method' object has no attribute '__getitem__'
Here is my code:
n=raw_input()
while n!="END" and n!="end":
s=0
x=[n]
if int(x[0][0])>4 and int(x[0][0])<7:
if x[0][3]==" " or x[0][3]=="-":
if x[0][3]==" ":
x[0].remove(" ")
else:
x[0].remove("-")
if len(x[0])>16:
print False
else:
a=[int(x[0][0]),int(x[0][1]),int(x[0][2]),int(x[0][3]),int(x[0][4]),int(x[0][5]),int(x[0][6]),int(x[0][7]),int(x[0][8]),int(x[0][9]),int(x[0][10]),int(x[0][11]),int(x[0][12]),int(x[0][13]),int(x[0][14])]
for i in range(0,14,2):
a[i]=2*a[i]
if a[i]/10!=0:
a[i]=a[i]/10+a[i]%10
for i in range(15):
s=s+a[i]
if s%10==0:
print True
else:
print False
else:
if len(x[0])>16:
print False
else:
a=[int(x[0][0]),int(x[0][1]),int(x[0][2]),int(x[0][3]),int(x[0][4]),int(x[0][5]),int(x[0][6]),int(x[0][7]),int(x[0][8]),int(x[0][9]),int(x[0][10]),int(x[0][11]),int(x[0][12]),int(x[0][13]),int(x[0][14])]
for i in range(0,14,2):
a[i]=2*a[i]
if a[i]/10!=0:
a[i]=a[i]/10+a[i]%10
for i in range(15):
s=s+a[i]
if s%10==0:
print True
else:
print False
else:
print False
n=raw_input
回答1:
Your second call to raw_input
doesn't call the function:
n=raw_input
Should be
n=raw_input()
回答2:
Your code has various issues. For example, you convert the input string to an array x
, of which you subsequently only use x[0]
. That's very confusing. Also you shouldn't call int
on the characters of the string until you are sure that they are decimal digits. An exception will be raised if you call int on a non-digit. And you shouldn't consider the strings with spaces or dashes and without as two separate cases, because the core algorithm is the same.
I've extracted that core algorithm into a separate function, which you can call on the input string. The input is supposed to be direct user input and may therefore be an invalid credit card number for various reasons. The function returns None
if the test is passed and an informative string that describes the kind of error otherwise.
The code performs various steps: First "purify" the string so that it only contains digits. If the user formats the string with spaces or dashes, these are strippe regardless of their poistion. (Letters and other non-digits are also stripped, which is unfortunate; catching these weeds out futher user errors.) Next the function checks for the correct length and applies the Luhn algorithm:
def invalid_credit_card_number(s):
""" Returns None if s is a valid credit card number
and a string describing the error otherwise.
The string may contains non-digits, which are ignored.
"""
# strip dashes from string and convert to list of digits
dig = [int(x) for x in list(s) if "0" <= x <= "9"]
if len(dig) != 16:
return "Invalid length"
if dig[0] < 5 and dig[0] > 6:
return "Invalid initial digit"
# multiply and cast out nines for every other digit
for i in range(0, 16, 2):
dig[i] *= 2
if dig[i] > 9:
dig[i] -= 9
# calculate checksum
s = (9 * sum(dig)) % 10
if s != 0:
return "Invalid checksum"
return None
Note that the Wikipedia page on Luhn's formula has example code in Python.
回答3:
Assuming that your raw_input
is a credit card number:
n == "1234567891234567"
Then x = [n]
gives you
x == ["1234567891234567"]
This isn't terribly helpful; did you want x = list(n)
?
x == ['1', '2', '3', ...]
This is why you keep having to use x[0]
to get anything done.
Also, you have a whole chunk of code duplicated within your if: else:
structure, due to your handling of punctuation. You can turn a string into a list of only digits using:
l = [int(c) for c in s if c.isdigit()]
which handles both removing any punctuation and making everything an integer, saving your (not terribly elegant) line of
a = [int(x[0][0]), int(x[0][1]), ...]
Putting it together, I would separate the actual test into a function (which allows you to use it programmatically in other contexts):
def ccn_is_valid(s):
"""Validate a supplied string s as a credit card number."""
LENGTH = 16
l = [int(c) for c in s if c.isdigit()]
# Test 1: length
if len(l) != LENGTH:
return False
# Test 2: first digit
if not 4 <= l[0] <= 7:
return False
# Test 3: algorithm
for i in range(0, LENGTH, 2):
l[i] *= 2
if l[i] % 10:
l[i] = l[i] / (10 + (l[i] % 10))
return not sum(l) % 10
(Note that range([start, ]stop[, step])
doesn't include stop
)
This function will return
as soon as any test fails, so doesn't bother continuing to process once it knows the number isn't valid.
Then you can loop through the user requests using:
while True:
s = raw_input("Enter credit card number or 'end': ")
if s.lower() == "end":
break
print(ccn_is_valid(s))
来源:https://stackoverflow.com/questions/20920911/how-to-debug-a-typeerror-no-attribute-getitem