[Python-3000] in-out parameters
Nick Coghlan
ncoghlan at gmail.com
Sun Apr 30 05:04:14 CEST 2006
Rudy Rudolph wrote:
> I don't much care about the syntax. The proposed "inout" reserved word could
> be "ref" or "&" or "in out". We could even do "param : inout [type]". Whatever.
A more flexible approach would be to look at weakref.proxy and develop a
version that takes a strong reference to the object it contains instead of a
weak reference. This approach means the same mechanism will work for closures
as well as for parameter passing.
Then the usage looks like:
>>> def f(param):
... param += 5
... print "Parameter modified:", param
...
>>> x = 2
>>> f(x)
Parameter modified: 7
>>> print x
2
>>> x = ref(2)
>>> f(x)
Parameter modified: 7
>>> print x
7
So it is up to the caller to decide whether they want to allow the function to
modify their local namespace.
Closures can also selectively enable rebinding in a slightly more intuitive
fashion than with boxing into a list. To use the infamous accumulator example:
>>> def accum(n):
... n = ref(n)
... def increment(i):
... n += i
... return n.__value__
... return increment
... # Use 'return lambda i: n.__iadd__(i).__value__' instead of the last
... # 4 lines if you prefer brevity to readability. Or you can go even
... # further and use 'return lambda i, n=ref(n): n.__iadd__(i).__value__'
... # as the sole line in the body of the function, although doing so
... # slightly changes the signature of the returned function
...
>>> inc = accum(2)
>>> inc(5)
7
>>> inc(3)
10
The one trick with this is that simple assignment to a proxy reference won't
work properly. Instead, you need to write something like:
>>> def f(param):
... param = ref.bind(param, 5)
... print "Parameter replaced:", param
...
>>> x = 2
>>> f(x)
Parameter replaced: 5
>>> print x
2
>>> x = ref(2)
>>> f(x)
Parameter replaced: 5
>>> print x
5
Cheers,
Nick.
-------------------------------
# The following naive version of ref was used for the above examples
# A real proxy type would modify its class dynamically whenever
# __value__ was rebound to a different type of object so that it
# only provided the methods that the referent exposed.
class ref(object):
def __init__(self, referent):
self.__value__ = referent
# Proxying string representation
def __str__(self):
return str(self.__value__)
# Proxying addition
def __add__(self, other):
return self.__value__ + other
__radd__ = __add__
def __iadd__(self, other):
self.__value__ += other
return self
# Proxying assignment
@staticmethod
def bind(proxy, other):
# Static method so it works for non-ref objects
try:
proxy.__value__ = other
except AttributeError:
return other
else:
return proxy
--
Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia
---------------------------------------------------------------
http://www.boredomandlaziness.org
More information about the Python-3000
mailing list