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