Based on the comments, your goal is to get back the return status of a function that you don't call directly, and you want to avoid globals. In C you'd have no choice but to use a reference, but in python you have much more flexibility than just locals and (C-style) globals: You can use "closures" to let your callback assign to a local variable directly.
In Python 3
If you use python 3, you can do this straightforwardly with the nonlocal
keyword. The simplest case is when you define your callback on the spot:
myfunction():
x = None
def callback():
nonlocal x # Python 3 only
x = 5
gtk.somefunction(callback) # Executes callback()
print "My callback returned", x
But your callback is probably defined elsewhere, or called from lots of different places? No problem, just define on the spot a wrapper that captures the return value of the real callback:
def real_callback():
return 11
def myfunction():
x = 0
def wrapper():
nonlocal x # Python 3 only
x = real_callback()
gtk.somefunction(wrapper)
print "my callback returned", x
This can be obscured by turning wrapper
into decorator, but that's a different matter.
Python 2 solution
In python 2 there's no nonlocal
statement, and implicit closures are read-only: If you try the above without the nonlocal
statement, you get an error. You can assign to a variable if you declare it global
, and that's all. So, some trickery is necessary:
First, the function locals()
returns a dictionary with all the variables of the local context. locals()['x']
is the local variable x
. But locals()
is normally read-only. Fortunately there's a nice (or terrible) work-around: For its own reasons, exec
disables the optimization that renders locals()
read-only... and, it turns out, it stays disabled for the lifetime of the calling function! (Tested on Python 2.6.6, YMMV. If it doesn't work, try exec "a = 0"
instead). So, you can do it like this:
def wrapper(callback, context, varname):
def _callback():
context[varname] = callback()
return _callback
def mycode():
exec ""
some_library_function(wrapper(real_callback, locals(), 'z'))
print "The callback returned", z
Is this preferable to just using a mutable container for your return value? That's a matter of taste, I guess. But you can use the same wrapper any number of times, so in a sense it's cleaner than the python 3 solution... if you ignore the magic exec
.