Reputation: 1248
How to access a variable x
that is local for a function main()
from another function sub()
that is called inside main()
?
The MEW below throws an error NameError: global name 'x' is not defined
when the script is run.
If I add global x, l
in main()
there are no errors anymore, but I do not want to make these variables global as such.
MWE:
def sub():
print "x from main: {}".format(x)
print "l from main: {}".format(l)
def main():
x = 5
l = [1,2,3,4,5]
print "z from top: {}".format(z)
sub()
if __name__ == "__main__":
z = 'SOME'
main()
Edit1 I am editing an existing code and prefer not to change arity of functions
Upvotes: 1
Views: 75
Reputation: 1209
The best way to do what you'd like, also requires the least amount of changes. Just change the way you're declaring the variables; by adding the function name before the variable name, you're able to access the variable from anywhere in your code.
def sub():
print "x from main: {}".format(main.x)
print "l from main: {}".format(main.l)
def main():
main.x = 5
main.l = [1,2,3,4,5]
print "z from top: {}".format(z)
sub()
if __name__ == "__main__":
z = 'SOME'
main()
This will print:
z from top: SOME
x from main: 5
l from main: [1, 2, 3, 4, 5]
Upvotes: 1
Reputation: 27485
Passing the parameters as arguments gets what you want done.
def sub(x, l):
print "x from main: {}".format(x)
print "l from main: {}".format(l)
def main(z):
x = 5
l = [1,2,3,4,5]
print "z from top: {}".format(z)
sub(x, l)
if __name__ == "__main__":
z = 'SOME'
main(z)
This prints:
z from top: SOME
x from main: 5
l from main: [1, 2, 3, 4, 5]
If you don't want to use this approach, I guess you could follow this answer's approach, although seems convoluted for a case like this.
import inspect
z = 'SOME'
def sub():
frame = inspect.currentframe()
locales = None
try: locales = frame.f_back.f_locals
finally: del frame
if locales:
for k, v in locales.items():
print("{} from main: {}".format(k, v))
def main():
x = 5
l = [1,2,3,4,5]
print("z from top: {}".format(z))
sub()
main(z)
Maybe this would be cleaner if you could turn this into a context manager.
You could also use *args
and *kwargs
def function(*args, **kwargs):
if args:
for a in args:
print "value: {} was passed in args".format(a)
if kwargs:
for k, v in kwargs.items():
print "key {} was passed with value: {} in kwargs".format(k, v)
def caller():
x = 5
l = [1,2,3,4,5]
function(x, l = l)
caller()
#value: 5 was passed in args
#key l was passed with value: [1, 2, 3, 4, 5] in kwargs
From here you can assign values to locals
within function
locals['x'] = args[0]
locals['l'] = kwargs[l]
OR use dict.get
this way you can set defaults:
l = kwargs.get('l', None)
Upvotes: 3