Reputation: 79
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:
Define global a in main ()
In define_stuff(), add a to 1 and assign to b, pass b or 3 back to main().
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
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
Reputation: 6891
return b
returns 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