How to debug a TypeError “no attribute __getitem__”? [closed]

谁说我不能喝 提交于 2019-12-13 22:45:49

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!