Search code examples
pythonrandommodulepython-module

Code is correct, teacher approved, but it's not working. How do I make it run? (Python random module)


This code is absolutely, 100% correct. It works on the teacher's computer and runs perfectly, but on mine it does not. I have no clue why that would be. The issue is the same on Mac and Windows (someone else had the same problem). I have Windows 8.1, if that's relevant, and I save all of my python files in Documents. I have Python 3.5, and I have the same issues in the Shell and in the command window.

It does work to a point - it prints the student names it's supposed to, but then it prints the ending message twice and freaks out.

I've imported the turtle module before with 0 issues. I haven't imported anything other than it and random, so I'm not sure if it's JUST random or if it's other modules too.

Here's the code. It's to randomly pick students for activities:

def addlist():
    maxLengthList = int(input("How many students?"))
    turtle.title("Class Chooser")
    while len(kids) < maxLengthList:
        name = turtle.textinput("Students", "Enter a name")
        kids.append(name)
    nextturn()

def nextturn():
    turn = random.choice(kids)
    kids.remove(turn)
    print("Next " + turn)
    again=len(kids)
    while again>0:
        nextturn()
        again=again-1
    else:
        print("Have a nice day!")

import random
import turtle
kids = []
addlist()

And here's the error message. I've inputted lucy, alex, jake, and bro for the students' names:

How many students?4
Next lucy
Next alex
Next jake
Next bro
Have a nice day!
Have a nice day!
Traceback (most recent call last):
  File "C:\Users\Seren\AppData\Local\Programs\Python\Python35-32\lib\random.py", line 253, in choice
    i = self._randbelow(len(seq))
  File "C:\Users\Seren\AppData\Local\Programs\Python\Python35-32\lib\random.py", line 230, in _randbelow
    r = getrandbits(k)          # 0 <= r < 2**k
ValueError: number of bits must be greater than zero

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\Seren\Documents\~School~\Computer Programming\isolated code ex.py", line 24, in <module>
    addlist()
  File "C:\Users\Seren\Documents\~School~\Computer Programming\isolated code ex.py", line 7, in addlist
    nextturn()
  File "C:\Users\Seren\Documents\~School~\Computer Programming\isolated code ex.py", line 16, in nextturn
    nextturn()
  File "C:\Users\Seren\Documents\~School~\Computer Programming\isolated code ex.py", line 16, in nextturn
    nextturn()
  File "C:\Users\Seren\Documents\~School~\Computer Programming\isolated code ex.py", line 10, in nextturn
    turn = random.choice(kids)
  File "C:\Users\Seren\AppData\Local\Programs\Python\Python35-32\lib\random.py", line 255, in choice
    raise IndexError('Cannot choose from an empty sequence')
IndexError: Cannot choose from an empty sequence

Do any of you have a fix for this? If I can't import random properly, my assignments will be nearly impossible to do.

EDIT: I think it's a problem with my computer, or my operating system, or the version of python I've downloaded. Anything outside the code that would cause the random module to go weird.

UPDATE: If I put quit() after print("Have a nice day!"), no error message pops up and the program seems to run as intended. I'm not sure if this is so much a solution as a band-aid, though.


Solution

  • The reason of this weird behavior is the use of recursion and a while loop to call the same function.

    There are many ways to solve this; however, I recommend to get rid of the while loop entirely as it is confusing:

    def addlist():
        maxLengthList = int(input("How many students?"))
        turtle.title("Class Chooser")
        while len(kids) < maxLengthList:
            name = turtle.textinput("Students", "Enter a name")
            kids.append(name)
        nextturn()
    
    def nextturn():
        turn = random.choice(kids)
        kids.remove(turn)
        print("Next " + turn)
        again=len(kids)
        if again>0:
            nextturn()
            again=again-1
        else:
            print("Have a nice day!")
    
    import random
    import turtle
    kids = []
    addlist()
    

    I would also standarize the code a bit, to make it more readable:

    import random
    import turtle
    kids = []
    def addlist():
        maxLengthList = int(input("How many students?"))
        turtle.title("Class Chooser")
        while len(kids) < maxLengthList:
            name = turtle.textinput("Students", "Enter a name")
            kids.append(name)
        nextturn()
    
    def nextturn():
        turn = random.choice(kids)
        kids.remove(turn)
        print("Next " + turn)
        if kids:
            nextturn()
        else:
            print("Have a nice day!")
    
    addlist()
    

    Update:

    This is the long explanation of what your code was doing:

    Suppose you have a list with [ann, bob, charlie].

    • On Call #1 to nextturn: you remove a kid so the variables are like this: (global kids=['ann', 'bob'], local again=2) before entering the loop.

    • On Call #2 to nextturn your variables are like this before entering the loop(global kids=[ann], local again=1)

    • On Call #3 it will be (global kids=[empty], local again=0) before (not) entering the loop. This will simply print "Have a nice day" and exit successfully

    Call 3 will end leaving the list empty. BUT Call 1 and 2 are still active. After the first iteration of the while loop on Call #2 the local variable again is 0, so it prints "Have a nice day" (again) and exits.

    But then in Call 1: the local variable again is 1, which means the loop will execute again on an empty list!!!.

    And that caused the problem.