1

I've been fighting with this for three hours now.

ETA- Should have mentioned this, but for purposes of this class, not allowed to use global variables.

Within function main(), I want to run a function firstPass if and only if it's the first time the whole function is being run. The firstPass function initializes a couple variables and prints some information that is not interesting if it's not the first time you see it.

I duly have:

#Initialize variables that need to run before we can do any work here
count = 0

def firstPass():
    x = 5
    y = 2
    print "Some stuff"
    count = count + 1
    print "Count in firstPass is",count
    return count,x,y

def main ():
    print "Count in main is",count
    if count == 0:
        firstPass()
    else:
        #Do a whole bunch of other stuff that is NOT supposed to happen on run #1
        #because the other stuff uses user-modified x and y values, and resetting
        #to start value would just be self-defeating.

main()

This returns correctly on the first pass, but on subsequent passes, returns:

Count in main is 1

This is also a problem for my user-modified x and y values within other functions. Though I haven't modified them here, I did include them because I need to pass multiple values between functions later on in the code, but who wants to read all that when I could just put them here for the sake of the example...

I was under the impression that

return [variable]

passed the CURRENT (i.e. whatever that variable became within the current function) value of the variable back to other subsequent functions. Either my understanding is wrong, or I am just doing it wrong.

11
  • 2
    You need to understand how variable scope works in python, namely global variables. Commented Mar 27, 2013 at 3:23
  • Is this your actual code? you need def main at least ... Commented Mar 27, 2013 at 3:24
  • The main of python looks something like if __name__ == "__main__": Commented Mar 27, 2013 at 3:24
  • This seems like it would raise an UnboundLocalError ... Commented Mar 27, 2013 at 3:25
  • 1
    Why not pass arguments like main(count)? Commented Mar 27, 2013 at 3:39

4 Answers 4

2

You need to do:

def firstPass():
    global count

to get the count variable to update.

By using the global keyword you tell the interpreter to load and store the value into the global count variable instead of saving it to a local variable of the same name. For example:

I define two functions, one with and one without using global:

>>> a = 0
>>> def foo():
...   a += 1
...   return a
>>> def bar():
...   global a
...   a += 1
...   return a

After disassembling both functions using the dis module, it becomes apparent what the difference is:

>>> import dis
>>> dis.dis(foo)
  2           0 LOAD_FAST                0 (a)
              3 LOAD_CONST               1 (1)
              6 INPLACE_ADD         
              7 STORE_FAST               0 (a)

  3          10 LOAD_FAST                0 (a)
             13 RETURN_VALUE        

>>> dis.dis(bar)
  3           0 LOAD_GLOBAL              0 (a)
              3 LOAD_CONST               1 (1)
              6 INPLACE_ADD         
              7 STORE_GLOBAL             0 (a)

  4          10 LOAD_GLOBAL              0 (a)
             13 RETURN_VALUE        
Sign up to request clarification or add additional context in comments.

3 Comments

+1 And then not try to do something crazy like return it as part of a tuple.
OP said he cannot use globals.
OP, cheerfully village-idioting it up when someone with more sense would be asleep, hadn't said that at the time Mike was posting. :)
2

Your understanding of return is wrong.

The values returned aren't just inserted back into the namespace of the caller, they have to be received. They don't have to be received with the same name either.

count,a,b = firstPass()

Also I'd suggest passing the current count into the function as a parameter, rather than grabbing it from a global. It's just better style all around, and makes your functions easier to understand.

Comments

0

You probably want to consider using a class. It's a better container for maintaining state.

def firstPass():
    x = 5
    y = 2
    print "Some stuff"
    count = count + 1
    print "Count in firstPass is",count
    return count,x,y        

class MyActivityManager(object):
    def __init__(self):
        """Initialize instance variables"""
        self.run_count = 0

    def run(self):
        if not self.run_count:
            results = firstPass()
            self.run_count += 1
            # consider saving results in the instance for later use
        else:
            # other stuff


if __name__ == "__main__":
    runner = MyActivityManager()
    runner.run()

Comments

0
def firstPass(count):
    x = 5
    y = 2
    print "Some stuff"
    count = count + 1
    print "Count in firstPass is",count
    return count,x,y

def main():
    count = 0 # initialize it here; you're only running main once
    print "Count in main is",count
    if count == 0:
        count, x, y = firstPass(count) # sets the values from firstPass()
    else:
        #Do a whole bunch of other stuff that is NOT supposed to happen on run #1
        #because the other stuff uses user-modified x and y values, and resetting
        #to start value would just be self-defeating.

main()

However, if you want to initialize count outside of main(), use main(count):

#Initialize variables that need to run before we can do any work here
count = 0

def firstPass(count):
    x = 5
    y = 2
    print "Some stuff"
    count = count + 1
    print "Count in firstPass is",count
    return count,x,y

def main (count):
    print "Count in main is",count
    if count == 0:
        firstPass()
    else:
        #Do a whole bunch of other stuff that is NOT supposed to happen on run #1
        #because the other stuff uses user-modified x and y values, and resetting
        #to start value would just be self-defeating.

main(count) # pass it as an argument

However, if you are only calling main() once, you can rewrite your code and general structure like this:

def main():
    count = 0
    count, x, y = firstPass(count) # no need to check if it is 0
    # do everything else

def firstPass(count):
    x, y = 5, 2 # multiple assignment, same as x = 5; y = 2
    print "some stuff"
    count += 1 # shorthand for count = count + 1
    print "Count in firstpass is", count
    return count, x, y

main()

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.