tracking variable value changes
Steven D'Aprano
steve+comp.lang.python at pearwood.info
Fri Dec 9 19:41:25 EST 2011
On Thu, 08 Dec 2011 12:17:11 -0800, Catherine Moroney wrote:
> Hello,
>
> Is there a way to create a C-style pointer in (pure) Python so the
> following code will reflect the changes to the variable "a" in the
> dictionary "x"?
Strictly speaking, no, but there may be a way to get something close. See
below.
> For example:
>
> >>> a = 1.0
> >>> b = 2.0
> >>> x = {"a":a, "b":b}
> >>> x
> {'a': 1.0, 'b': 2.0}
> >>> a = 100.0
> >>> x
> {'a': 1.0, 'b': 2.0} ## at this point, I would like the value
> ## associated with the "a" key to be 100.0 ##
> rather than 1.0
The line "a = 100" is a rebinding, and so what you are asking for isn't
directly possible. But if you are willing to live with an explicit
redirection, you can somewhat simulate a pointer with a list:
py> aPtr = [1.0] # not really a pointer, but let's pretend it is
py> bPtr = [2.0]
py> x = {'a': aPtr, 'b': bPtr}
py> x
{'a': [1.0], 'b': [2.0]}
py> aPtr[0] = 100.0
py> x
{'a': [100.0], 'b': [2.0]}
If you prefer, you can write a simple class to handle the redirection
with the interface of your choice. Something like this might be a good
start:
class SharedValue:
def set(self, value):
self.value = value
def get(self):
return self.value
def __repr__(self):
# Somewhat dubious.
return str(self.value)
py> a = SharedValue() # create a pointer
py> a.set(1.0)
py> x = {'a': a}
py> x
{'a': 1.0}
py> a.set(100.0)
py> x
{'a': 100.0}
Look at the automatic delegation pattern for a way to have operations on
"a" automatically apply to the object being pointed to. (This will be
*much* simpler if you don't inherit from object.)
But be warned, whatever you do, rebinding will behave in the standard
Python way. E.g.:
py> aPtr = [2000.0] # Oops, rebound the name to something else!
py> x # and the connection is lost
{'a': [100.0], 'b': [2.0]}
> If I make "a" and "b" numpy arrays, then changes that I make to the
> values of a and b show up in the dictionary x.
Yes, because numpy arrays are mutable objects. In this case, you have two
(or more) references to a single object: the name "a", and the entry in
dict "x". When you modify the object in either place, the change is
visible in both places because they are the same object.
But when you rebind the name "a" to another object -- not necessarily a
*new* object, just a different one -- there is no way for the dict "x" to
notice this change and follow along.
> My understanding is that when I redefine the value of "a", that Python
> is creating a brand-new float with the value of 100.0, whereas when I
> use numpy arrays I am merely assigning a new value to the same object.
Correct. Although the float need not be brand-new. Python could (but
probably doesn't) re-use an existing float object.
--
Steven
More information about the Python-list
mailing list