-5

I am a beginner and recently started python development. The code i was working on:

import random 
import textwrap

def show_message(dotted_line,width):

    print(dotted_line)
    print("\033[1m"+ "Attack of clones:" + "\033[0m")

    message = (
    "The war between humans and their arch enemies , Clones was in the offing. Obi-Wan, one of the brave Jedi on his way ," 
    "he spotted a small isolted settlement .Tired and hoping to replenish his food stock , he decided to take a detour." 
    "As he approached the village, he saw five residence , there was no one to be seen around.He decided to enter" )
    print(textwrap.fill(message, width = width))

def show_mission(dotted_line):
    print("\033[1m"+ "Mission:" + "\033[0m")
    print('\t Choose the hit where Obi wan can rest...')
    print("\033[1m"+ "TIP:" + "\033[0m")
    print("Be careful as there are Stormtroopers lurking around!")
    print(dotted_line)


def occupy_huts():
    global huts
    huts = []

    while len(huts) < 5:
        random_choice = random.choice(occupants)
        huts.append(random_choice)



def process_user_choice(): 
     message = "\033[1m"+ "Choose the hut to enter (1-5) " + "\033[0m"
     uc = input("\n" + message)
     index = int(uc)
     print("Revealing the occupants...")
     message = ""



def reveal_occcupants(index,huts,dotted_line):
    for i in range (len(huts)):
        occupant_info = "<%d:%s>"%(i+1,huts[i])
        if i + 1 == index:

            occipant_info = "\033[1m"+ "" + "\033[0m"
        message += occupant_info + " "
    print("\t" + message)
    print(dotted_line)



def enter_huts(index,huts,dotted_line): 
    print("\033[1m"+ "Entering Hut %d ..." %index + "\033[0m")

    if huts[index - 1] == 'clones':
        print("\033[1m"+ "There's Stormtrooper Here!!" + "\033[0m")
    else:
        print("\033[1m"+ "It's Safe here!" + "\033[0m")
    print(dotted_line)



def run():
    keep_playing = 'y'
    global occupants
    occupants = ['clones','friend','Jedi Hideout']
    width = 70
    dotted_line = '-' * width

    show_message(dotted_line, width)
    show_mission(dotted_line)

    while keep_playing == 'y':
         huts = occupy_huts()
         index = process_user_choice()
         reveal_occcupants(index,huts,dotted_line)
         enter_huts(index,huts,dotted_line)
         keep_playing = raw_input("Play Again?(y/n)")

if __name__ == '__main__':
    run()

and the error is in body of def reveal_occupants. "TypeError: object of type 'NoneType' has no len()"

how this error can be overcome and please suggest an alternative approach too

Desmond
  • 29
  • 7

4 Answers4

1

Here :

while keep_playing == 'y':
     huts = occupy_huts()

Your occupy_huts() function doesn't return anything (it populates a global variable huts but doesn't return it), so the after the huts = occupy_huts() statement huts is now None (the default function return value if you don't explicitely return something). Then you pass this (now None) huts variable to reveal_occupants() :

    reveal_occcupants(index,huts,dotted_line)

The solution is simple: modify occupy_huts so instead of working on a global (which is almost always a very bad idea) and returning None, it works on a local variable and returns it:

def occupy_huts():
    huts = []
    while len(huts) < 5:
        random_choice = random.choice(occupants)
        huts.append(random_choice)
    return huts

While we're at it, you are using a global for occupants too, which is brittle (occupy_huts() will break if called before this variable has been created), while you could just pass it as argument:

def occupy_huts(occupants):
    huts = []
    while len(huts) < 5:
        random_choice = random.choice(occupants)
        huts.append(random_choice)
    return huts

and then in run():

def run():
    keep_playing = 'y'
    occupants = ['clones','friend','Jedi Hideout']
    # ...
    while keep_playing == 'y':
         huts = occupy_huts(occupants)

The funny thing here is that you pass arguments for mundane stuffs that are mostly constants and have no impact on the program's logic (ie dotted_lines), but use globals for the important things - should really be the other way round (declare dotted_lines as a pseudo_constant at the start of your module and don't bother passing it to functions) ;)

Also, note that you have a similar issue with process_user_choice() here :

while keep_playing == 'y':
     huts = occupy_huts()
     index = process_user_choice()

since your process_user_choice() function doesn't return anything either. You should modify it so it returns its local variable index.

bruno desthuilliers
  • 68,994
  • 6
  • 72
  • 93
0

len() method accepts an object as parameter. in your case, at line 43, huts may be None, so you can get an error.

you should insert if condition like below after line 42

if huts is None:
    return
0

My guess is that "huts" is None-type, because occupy_huts() was never called. Or there is an issue with the scope of the "huts" variable -- this might be cleared up by declaring it as an empty set outside of the occupy_huts() function.

Also, you could take advantage of Python's syntax and change line 43 to "for hut in huts:". If you also need the index of the hut, try "for hut, i-hut in enumerate(huts):".

AlexM
  • 649
  • 2
  • 10
  • 29
0

You method "reveal_occupants" receive empty value as huts. That means, that type of huts is None. That why you can't get len of this value.

Andrew
  • 41
  • 2