tracking variable value changes

  • Thread starter Catherine Moroney
  • Start date
C

Catherine Moroney

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"?

For example:
{'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

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.

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.

Is there some way to rewrite the code above so the change of "a" from
1.0 to 100.0 is reflected in the dictionary. I would like to use
simple datatypes such as floats, rather than numpy arrays or classes.
I tried using weakref's, but got the error that a weak reference cannot
be created to a float.

Catherine
 
I

Ian Kelly

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"?

For example:

{'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

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.

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.

Sort of. In the code above, you are binding a and x["a"] to the same
float object. Then when you do "a = 100.0", you are rebinding a but
not x["a"]. In the case of arrays it's the same story, except that
you can also *modify* the contents of the array instead of rebinding
to a new array. In that case both a and x["a"] are still bound to the
original array, the contents of which have changed.

You can get the same effect with a float by putting it in a container
object and binding both variables to the same container objects rather
than to the float directly. Then, to change the value, change the
contents of the container object. What you use as a container object
is up to you. Some use a 1-element list, although I find that ugly.
 
A

Arnaud Delobelle

You can get the same effect with a float by putting it in a container
object and binding both variables to the same container objects rather
than to the float directly.  Then, to change the value, change the
contents of the container object.  What you use as a container object
is up to you.  Some use a 1-element list, although I find that ugly.

This kind of trick is not often necessary anyway. It may be a sign
that there is a better approach to the problem that the OP is trying
to solve.
 
A

Andrea Crotti

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"?

For example:

{'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

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.

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.

Is there some way to rewrite the code above so the change of "a" from
1.0 to 100.0 is reflected in the dictionary. I would like to use
simple datatypes such as floats, rather than numpy arrays or classes.
I tried using weakref's, but got the error that a weak reference cannot
be created to a float.

Catherine

Not sure if it's exactly pure python but Traits can actually do this
https://github.com/enthought/traits
 
S

Steven D'Aprano

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} ## 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.
 
A

alex23

Andrea Crotti said:
Not sure if it's exactly pure python but Traits can actually do thishttps://github.com/enthought/traits

At an attribute level, absolutely, but not at the variable level like
the OP is requesting.

It's a great package, though :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,992
Messages
2,570,220
Members
46,807
Latest member
ryef

Latest Threads

Top