What I essentially need is a mutable integer which can accomplish the equivalent of the below without having to resort to using single element lists.
Below is a contrived code sample which is representative of the essence of my actual use case [1]
>>> a = [5]
>>> b = [77]
>>> def swap(num1, num2):
... temp = num1[0]
... num1[0] = num2[0]
... num2[0] = temp
>>> swap(a, b)
>>> a
[77]
>>> b
[5]
[1] My actual use case is closer to this ->
Returning a value after calling a function with a button in Tkinter
I need to return a value from a callback function associated with a Tkinter widget, and I would like to avoid globals.
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
nonlocalkeyword. The simplest case is when you define your callback on the spot: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:
This can be obscured by turning
wrapperinto decorator, but that’s a different matter.Python 2 solution
In python 2 there’s no
nonlocalstatement, and implicit closures are read-only: If you try the above without thenonlocalstatement, you get an error. You can assign to a variable if you declare itglobal, 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 variablex. Butlocals()is normally read-only. Fortunately there’s a nice (or terrible) work-around: For its own reasons,execdisables the optimization that renderslocals()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, tryexec "a = 0"instead). So, you can do it like this: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.