I have been trying to return a variable in a function in a variable and use it outside of it:
test = 0
def testing():
test = 1
return test
testing(
Because you declare test
in the function, it is not a global variable, thus, you can not access the variable test
you created in the function outside of it as they are different scopes
If you want to return test
to a variable, you have to do
result = testing()
print(result)
Or, you can also add a global
statement:
test = 0
def testing():
global test
test = 1
return test
testing()
print(test)
By the way, when doing a conditional statement, you don't need the brackets around the 1==1
:).
You are messing up a bit the scopes and/or assignment. Try this:
def testing():
test = 1
return test
test = testing()
print(test)
Explanation: The test
inside testing
is different to the test
inside the module. You have to assign it on module-level to get the expected result.
Inside the function testing()
, you're creating a new variable test
, not referring to the one that already exists. If you want to do that, you should use a global
statement in the top, as in:
def testing():
global test
...etc...
TLDR: A return
value must be assigned to something at the call site.
test = testing()
Functions in Python have their own scope. It is created on entering (calling) the function, and destroyed when leaving it. Assignment to a name inside a scope makes that name local to this scope - causing it to be destroyed along with the scope.
# start outer scope
test = 0 # create name outer:test
def testing():
# start inner scope
test = 1 # create name outer.testing:test
return test
# end inner scope
# destroy name outer.testing:test
testing() # new temporary inner scope outer.testing
print(test) # use name outer:test
# end outer scope
Notably, names in an inner scope may "shadow" names from an outer scope. While the name test
exists in both testing
and the outer scope, it does not refer to the same thing. This has two important implications:
test
does not affect the outer test
.testing
, the inner test
is destroyed and only the outer test
remains.This is why calling testing()
does not have the desired effect: it never modifies the outer test
passed to print
.
The return statement defines the value returned by calling a function. It does not return the name, only the value pointed to.
def testing():
test = 1 # test refers to the value 1
return test # return test => value 1
The value returned by a function is like any other value - be it from a literal, lookup, or other. Most importantly, the value does not persist unless you assign it to a name or use it directly.
testing() # call test, discard its value
test = testing() # call test, store its value as `test`
print(testing()) # call test, use its value in `print`
So in order to return something from a function for later use, you must store the result to a name. You can then use that name in a later statement. A minimal example for your case looks like this:
# we already can define testing here
# it is overwritten later on, then
def testing():
# all names we use inside of testing are gone at the end
# if we just want a value, we can skip temporary names
return 1
# store the return value of testing() for later use
test = testing()
print(test)
Addendum: It is possible for a function to modify its containing scope. However, names must then be explicitly declared as being from a foreign scope.
The nonlocal and global keywords allow to modify names from outer scopes. A nonlocal
is the name in the closest matching function scope. A global
is the name at the module scope, regardless of any functions in-between.
test = 0
def increment():
global test # declare test as belonging to a specific scope
test += 1
# no need to return something
# we already modified the outer `test`
print(test) # 0
increment()
print(test) # 1
Note that modifying outer names is often the sign of an anti-pattern, moreso for global
s than nonlocal
s. Beyond small scripts, it gets difficult to trace what is accessing and modifying global
s. Often, it is more appropriate to use classes or generators to hold state.
A function can always read names from its containing scope, provided it never writes to the same name. Such closures are very easy to create, and the lack of modification makes them easier to trace. Note that modifying a name anywhere in a function makes it local, unless declared global
or nonlocal
:
test = 0
def increment():
global test
test += 1
def show_test():
# we never modify `test`, so it is fetched from the outside
print(test)
def show_and_increment1(): # this function is broken!
print(test) # `test` is *not* the outer one, since we modify it in the function
test += 1 # modifying `test` makes it local for the *entire* function
def show_and_increment2(): # this function works!
global test # force `test` to be global
print(test)
test += 1
show_test() # 0
increment()
show_test() # 1
show_and_increment2() # 1
show_and_increment2() # 2
show_and_increment2() # 3
show_test() # 4
show_and_increment1() # UnboundLocalError: local variable 'test' referenced before assignment
Your test
variable inside the function does not have a global scope. So, if you want to store the return value in a variable and output it after that, you can do something like this:
result = testing()
print(result)