0

I'm trying to create a program that runs a basic simulation. Create a row of ten boxes, let a random number generator pick which direction he moves, and keep track of him. The problem for the last while now is that the initial position is not being friendly. I want to start in the middle - five - but no matter where I put that line, I get an error.

Here's the code:

import random


def right_movement():
    p = p + 1
    m = m + 1
    times[p] = p
    print times


def left_movement():
    p = p - 1
    m = m + 1
    times[p] =+ 1

def main():
    p = 5
    times = [0] * 11
    times[p] = 1
    m = 0
    print times

    while p >= 0 and p <= 10:
        x = random.randint(0, 1)
        if x > 0:
            right_movement()
        else:
            left_movement()
    if p == 11:
        print "Movement to the right into location 11."
        print "Number of moves is " + m + "."
    else:
        print "Movement to the left into location 0."
        print "Number of moves is " + m + "."


main()

No matter where I put p = 5, I get an error in reference to that. I'm running Python 2.7.

David Cain
  • 16,484
  • 14
  • 65
  • 75

2 Answers2

3

The problem is related to something called scope.

In a nutshell, what you did is you first created a variable called "p" within your main function. However, that does not mean that the other functions you create will be able to know that p exists.

I think this might be easier to understand if I give an example. In the first line of right_movement, you do p = p + 1. Since you're using p to add 1 to it, Python is going to look to see if you've assigned the variable p within right_movement. Since you didn't, it's going to sort of "move up" a layer, and see if you assigned the variable p within the file in general. Since you didn't assign p in either of those (you assigned inside main), Python will give up.

There are several solutions to this. The quick-and-dirty one would be to use something called "global" variables, and would look like this:

import random

p = 5
m = 0
times = [0] * 11

def right_movement():
    global p
    global m
    global times
    p = p + 1
    m = m + 1
    times[p] = p
    print times



def left_movement():
    global p
    global m
    global times
    p = p - 1
    m = m + 1
    times[p] =+ 1
    print times



def main():
    times[p] = 1

    print times
    while p >= 0 and p <= 10:
        x = random.randint(0, 1)
        if x > 0:
            right_movement()
        else:
            left_movement()
    if p == 11:
        print "Movement to the right into location 11."
        print "Number of moves is " + str(m) + "."
    else:
        print "Movement to the left into location 0."
        print "Number of moves is " + str(m) + "."

main()

You move the p, m, and times variables outside of the main function to the file, and make sure to use the global keyword to let Python know that you want to modify the variables inside the function, rather then temporarily creating a new one.

However, this isn't the cleanest solution -- using global variables is considered bad practice for a variety of reasons.

A better solution might be to keep track of the state within main, and rewrite your code to look like this:

import random

def right_movement(times, p):
    p += 1
    times[p] += 1
    return p

def left_movement(times, p):
    p -= 1
    times[p] =+ 1
    return p

def main():
    p = 5
    moves = 0
    times = [0] * 11
    times[p] = 1

    print times
    while 0 <= p <= 10:
        moves += 1
        x = random.randint(0, 1)
        if x > 0:
            p = right_movement(times, p)
        else:
            p = left_movement(times, p)
        print times
    if p == 11:
        print "Movement to the right into location 11."
        print "Number of moves is " + str(moves) + "."
    else:
        print "Movement to the left into location 0."
        print "Number of moves is " + str(moves) + "."

main()
Community
  • 1
  • 1
Michael0x2a
  • 58,192
  • 30
  • 175
  • 224
  • Very nice answer. Maybe explain why `times` works, being defined in `main()` but updated in the functions (whereas this caused problems for `p`)? – beroe Aug 28 '13 at 06:36
1

You are trying to share the same variables among several functions, without passing the values in to the functions as arguments. In order to do this, you need to use global variables.

Something like this:

import random
p = 5
times = [0] * 11
m = 0

def right_movement():
    global p, times, m
    p = p + 1
    ...

So, first you need to declare the variables outside of any function, then you need that global statement in each function that uses the variables.

Markku K.
  • 3,840
  • 19
  • 20