Search code examples
pythonstringlistnonetype

Object of type NoneType has no length error


I have written the following function to add the elements of a list to a string.


import random 
import string 

def printmatches (word,x):
    y = len(word)
    z = [" "] *y 
    i = 0 
    while i<y:
        if word[i] == x: 
            z[i] = x 
        else:
            z[i] = " "  
        i+=1

    return (z)

def append(string,chars): ##append list to a string
    q = 0
    while q < len(string): 
        if string[q] == " " and chars[q] != " ":
            string[q] = chars[q]
        q+=1  

x = random.randint(0,55899)

def convertlist(x):
    q = " "
    a = 0
    while (a < len(x)):
        q+=x[a]
        a+=1
    return (q) 

try:
    f = open('words.txt', 'r')
    s = " "
    s = f.readline()

    L = s.split()

    word = L[x]

    f.close()

except IOError:
    print('file not found')

q=0

print word

print (printmatches('ereesvox','o') == [" "] * 8)  
current = [" "] * len(word)  
c = 0
char = " " 
while char != word and q < 3 and c <35: 
    char = raw_input (" ") 
    c+=1
    ##current.append(printmatches(word,char)) 
    append(current, printmatches(word,char)) 
    str = (append(current, printmatches(word,char)))
    if (convertlist(str) == word): 
        print 'Congratulations, you have won'
    if printmatches(word,char) == [" "]*len(word):    
        print "You have ", (2-q), " guesses left"   
        q+=1 
    if (q == 3):
        print "Game over"
    print ' '.join(current)     



x is meant to be a list but when I execute the code its type is interpreted as Nonetype, and I get the error message because I am trying to access elements within x and compare its length. How can I fix this problem?


Solution

  • def append(string,chars): ##append list to a string
        q = 0
        while q < len(string): 
            if string[q] == " " and chars[q] != " ":
                string[q] = chars[q]
            q+=1  
    

    This does not explicitly return a value, so it implicitly returns None.

    (The name string is also a very poor choice here: first off, you expect to be passed a list rather than a string (since as you presumably learned earlier, you cannot modify a string like this), and second it hides the imported string module. But then again, your code does not use the string module, so you shouldn't import it in the first place.)

    str = (append(current, printmatches(word,char)))
    

    Now str is None, because it is the result of an append call.

    if (convertlist(str) == word): 
    

    Now we attempt to convertlist with None, which of course does not work since we wanted a list to be passed in...

    def convertlist(x):
        q = " "
        a = 0
        while (a < len(x)):
            q+=x[a]
            a+=1
        return (q) 
    

    ... and thus here len is invalid applied to None.


    The natural way to get information out of a function is to return that information. Create a new string in append, and return it; then you can use the result the way you're trying to use it. As a bonus, since you are creating a new object, you can actually pass in a string again.

    Except, I have no idea why this function is called append, since despite the comment, it doesn't seem intended to do any such thing....