Reputation: 1375
I have a function and a flask route setup. However, when I go to "simplepage", I get an error "NameError: global name 'aaa' is not defined". Why aren't any of the objects being passed to testfun? Is this something due to the app.route decorator, or due to flask? Can I make all the objects passed to testfun? My actual code is way more complicated with many more objects that would need to be passed, but this simplified scenario was created to illustrate my issue.
def testfun():
b=aaa
@app.route("/simplepage/", methods=['GET'])
def simplepage():
aaa=1
testfun()
return flask.render_template('page.html')
Upvotes: 1
Views: 1436
Reputation: 159895
This is due to Python's scoping rules (as @johnthexiii pointed out) - testfun->aaa
is bound to the global scope because there is no variable named aaa
declared anywhere inside of testfun
and there is no enclosing scope (i. e. testfun
is not declared inside another function or class).
You'll want to pass aaa
as an argument to testfun
:
testfun(aaa)
If testfun
requires too many params there are several ways you can DRY up the code:
Use multiple functions: If testfun
is doing a lot of work then break it up into multiple functions that return intermediate transformations of the data:
def start_test(arg1, arg2, arg3):
# do stuff with args
return result_stage_1
def continue_test(arg3, arg4, arg5):
# do stuff with args
return result_stage_2
def finalize_test(arg7, arg8):
# do stuff with args
return real_result
Use keyword arguments: If a variable number of arguments are needed and testfun
cannot be broken up you can use keyword arguments to simplify the calling of the function:
def testfun(arg1=None, arg2=None, arg3=None, arg4=None,
arg5=None, arg6=None, arg7=None, arg8=None):
# do stuff with args
# call it as so
args = {"arg1": "some args", "arg5": "have defaults"}
if complex_condition:
args["arg3"] = 17
elif another_condition:
args["arg7"] = 10
testfun(**args)
Encapsulate state and behavior with classes (or closures): If neither of the above will work for you then you probably need to leave the realm of stateless functions and create classes or closure-creating functions to preserve your state and enable you to modify behavior as needed.
Upvotes: 3
Reputation: 13699
Basically what is happening is this
def t():
print aaa
def s():
aaa = "hi"
t()
s()
Python looks for aaa
first in the local scope, then in any wrapping function scopes, then globally, and lastly in the builtins. Since the s
functions scope isn't any of those things python throws an undefined error because it can't find aaa
.
One solution would be to declare aaa
as global.
def t():
print aaa
def s():
global aaa
aaa = "hi"
t()
s()
Upvotes: 1