penguin02007
penguin02007

Reputation: 79

Python Passing variables within (sub) functions

I am trying to understand a basic concept about passing variables and scoping in python but I am clearly missing something as I have spent a lot time reading but not getting what I am expecting.

I expect the following as:

  1. Define global a in main ()

  2. In define_stuff(), add a to 1 and assign to b, pass b or 3 back to main().

  3. In add_stuff(), add a to b and assign c, pass c or 5 back to main().

    def main(): a = '2'

    def define_stuff():
        b = 1 + float(a)
        print 'returning', b
        return b
    
    def add_stuff():
        print 'adding b to a ', 
        c = float(a) + float(b)
        print 'getting', c
        return c 
    
    define_stuff()
    add_stuff()
    

    if name == 'main': main()

I am using 2.7. Clearly "return" does not perform what I am expecting.

What I need to do to pass a local variables within a (sub) function to main()?

returning 3.0
adding b to a
Traceback (most recent call last):
  File "C:\scripts\testscope.py", line 19, in <module>
    main()
  File "C:\scripts\testscope.py", line 16, in main
    add_stuff()
  File "C:\scripts\testscope.py", line 11, in add_stuff
    c = float(a) + float(b)
NameError: global name 'b' is not defined

Upvotes: 2

Views: 5784

Answers (2)

juanpa.arrivillaga
juanpa.arrivillaga

Reputation: 95948

First, a is not "global" in main, it is local to main. In any event, when you return a local variable from some function, it doesn't affect anything in the surrounding scope unless you assign the return value in that scope.

In [1]: def main():
   ...:     a = '2'
   ...:
   ...:     def define_stuff():
   ...:         b = 1 + float(a)
   ...:         print 'returning', b
   ...:         return b
   ...:
   ...:     def add_stuff():
   ...:         print 'adding b to a ',
   ...:         c = float(a) + float(b)
   ...:         print 'getting', c
   ...:         return c
   ...:
   ...:     b = define_stuff() # or else the value get's discarded
   ...:     c = add_stuff() # or else the value gets discarded
   ...:

In [2]: main()

returning 3.0
adding b to a  getting 5.0

Note, this is a brittle way to write code, since your add_stuff function depends on some non-local b, so if you want to use add_stuff, you have to make sure there is a b somewhere in variable resolution order (local, enclosing... global). Instead, it is a better practice to only deal with local variables and return values from functions and pass values as arguments to functions if the function will make use of them. Only use global variables sparingly. So, this would be better:

In [5]: def main():
   ...:
   ...:     def define_stuff(a):
   ...:         b = 1 + float(a)
   ...:         print 'returning', b
   ...:         return b
   ...:
   ...:     def add_stuff(a, b):
   ...:         print 'adding b to a ',
   ...:         c = float(a) + float(b)
   ...:         print 'getting', c
   ...:         return c
   ...:
   ...:     x = '2'
   ...:     y = define_stuff(x) # or else the value get's discarded
   ...:     z = add_stuff(x, y) # or else the value gets discarded
   ...:

In [6]: main()
returning 3.0
adding b to a  getting 5.0

Note, I've used x, y, z just to emphasize that these are separate, local variables, but you could have used a,b,c, but just remember, they don't have any intrinsic connection to the a, b, c in your inner function scopes.

Upvotes: 3

JohanL
JohanL

Reputation: 6891

return breturns the value of b alright, but it needs to be stored in a variable in main. The variable b is right now local to your function add_stuff. What you need is a variable b also in main to catch the value you return:

def main():
    a = '2'

    def define_stuff():
        b = 1 + float(a)
        print 'returning', b
        return b

    def add_stuff():
        print 'adding b to a ', 
        c = float(a) + float(b)
        print 'getting', c
        return c 

    b = define_stuff()
    c = add_stuff()

if __name__ == '__main__':
     main()

And in addition you probably want to catch the result of add_stuff also, in c as I have shown above.

Upvotes: 2

Related Questions