This is a container class, suitable for use to answer the question "How do I pass a reference to a variable to a function", abusing some of the methods to get a syntax that's easier to use than more conventional containers.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | class Ref(object):
_unbound = object()
def __new__(cls, value = _unbound):
"""We're an object, but need to ignore the optional argument."""
return object.__new__(cls)
def __init__(self, value = _unbound):
"""Bind the optional value, if provided."""
if value is not self._unbound:
self._value = value
def __pos__(self):
"""Return value, if bound."""
try:
return self._value
except AttributeError:
raise NameError, "%s object does not have a value stored." % \
self.__class__.__name__
def __iadd__(self, value):
self._value = value
return self
|
A common question on comp.lang.python is "How do I pass a reference to a variable to change it in a function." This usually comes from people used to other languages, where that's the solution of choice for returning multiple values. The better solution for this in Python is to return a tuple and assign the new value to the variable. However, answers involving using a container class for the variable always surface, with the usual objection that the syntax for them is ugly.
The Ref class is designed to be a simple container class with a cleaner syntax than other alternatives. It abuses the ability to have operators invoke methods to use the monadic plus and add-assign operator to retrieve and set the values in the container. I.e.:
a = Ref(20) print +a # Prints 20 b = a b += 23 print +a # Prints 23 a += "Testing" print +b # Prints 23
The problem with your solution is that you must wrap all of the underlying methods to be effective. I personally prefer the standard answer of "use a list."
No other wrappers needed. I clearly didn't provide sufficient examples. You use a Ref object just like you'd use a list, except the syntax for setting/reading a value looks more like an extended lambda-calculus Cell than a list. Where you'd write arg[0] in a method if you passed a list, you'd write +arg to get the value, and arg[0] = value becomes arg += value.
To write the classic "inc" function, you'd write: