From: faassen at pop.vet.uu.nl (Martijn Faassen)
Date: Thu, 22 Apr 1999 19:49:24 +0200
Subject: Pointers to variables
References: <19990422121403.A279051@vislab.epa.gov>
Message-ID: <371F6124.48EA9794@pop.vet.uu.nl>
Content-Length: 3214
X-UID: 11                                                 

Randall Hopper wrote:
> 
> This doesn't work:
> 
>     for ( var, str ) in [( self.min, 'min_units' ),
>                          ( self.max, 'max_units' )]:
>       if cnf.has_key( str ):
>         var = cnf[ str ]
>         del cnf[ str ]
> 
> It doesn't assign values to self.min, self.max (both integers).  The values
> of these variables are inserted into the tuples and not references to the
> variables themselves, which is the problem.
> 
> How can I cause a reference to the variables to be stored in the tuples
> instead of their values?

Hi there, 

I've been trying to understand the purpose of the code in your fragment
and your question for a minute or so, but I'm not entirely sure I get it
yet.

I'm assuming what you want is to get 'cnf[str]' assigned to self.min or
self.max.

What you could do is something like this:

    for str in ('min_units', 'max_units'):
        if cnf.has_key(str):
            setattr(self, str, cnf[str])
            del cnf[str]

Tuples, by the way are immutable, so you can't change what values their
elements point to after they've been created (though if these values
point to other things themselves you can change that). That is, you
can't do this:

    foo = (value1, value2)
    foo[0] = "hey"

But, if you'd use a mutable list, you still run into trouble. If you say
this:

    mylist = [None]                         # list with a single element
None
    variable_i_want_to_change = "Foo"       # a variable I want to
change
    mylist[0] = variable_i_want_to_change   # okay, mylist[0] points to
same data
    mylist[0] = "Bar"                       # now mylist[0] points to
different data

then 'variable_i_want_to_change' won't change. You've simply changed
what value mylist[0] points at. This is because a string (and integers
etc) are immutable values in Python. If you use a mutable value such as
a dictionary, you get this:

    mylist = [None]
    variable_i_want_to_change = {}
    mylist[0] = variable_i_want_to_change
    mylist[0]["some key"] = "bar" # indeed changes
variable_i_want_to_change!
    # mylist[0] = "Bar" -- doesn't work, makes mylist[0] point elsewhere

I suspect I'm making things sound horribly complicated when they aren't
really. I can keep all this in my head easily, it's just hard
communicating it. I can understand the confusion with pointers from C,
but note that this is the actual semi-equivalent C code (of the first
fragment, not the dict one, and using ints instead of strings):

/* Initialize the variables, assume easy allocate functions which do all
the 
   malloc() calls I don't want to figure out right now */
int** mylist = allocate_list();
*mylist[0] = 0;  
/* now we have a list with a pointer to an int value, which is 0 */

int* variable_i_want_to_change = allocate_int();
*variable_i_want_to_change = 1;
/* now we have a variable which points to an int value, which is 1 */

*mylist[0] = *variable_i_want_to_change;
/* now the data mylist[0] points at becomes 1 too */

*mylist[0] = 2;
/* now the data mylist[0] points at becomes 2 */

/* has the data *variable_i_want_to_change changed? no. I hope! :)*/
 
I don't expect this explained a lot. I feel like Tim Peters somehow...
:)

Regards,

Martijn




