indirectly addressing vars in Python

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Ross

    indirectly addressing vars in Python

    Forgive my newbieness - I want to refer to some variables and indirectly
    alter them. Not sure if this is as easy in Python as it is in C.

    Say I have three vars: oats, corn, barley

    I add them to a list: myList[{oats}, {peas}, {barley}]

    Then I want to past that list around and alter one of those values.
    That is I want to increment the value of corn:

    myList[1] = myList[1] + 1

    Is there some means to do that?. Here's my little session trying to
    figure this out:
    >>oats = 1
    >>peas = 6
    >>myList=[]
    >>myList
    []
    >>myList.append (oats)
    >>myList
    [1]
    >>myList.append (peas)
    >>myList
    [1, 6]
    >>myList[1]= myList[1]+1
    >>myList
    [1, 7]
    >>peas
    6
    >>>
    So I don't seem to change the value of peas as I wished. I'm passing
    the values of the vars into the list, not the vars themselves, as I
    would like.

    Your guidance appreciated...

    Ross.
  • Jeremy Sanders

    #2
    Re: indirectly addressing vars in Python

    Ross wrote:
    >>myList[1]= myList[1]+1
    The problem is this makes myList[1] point to a new integer, and not the one
    that peas points to.

    Python 2.5.1 (r251:54863, Jul 10 2008, 17:25:56)
    [GCC 4.1.2 20070925 (Red Hat 4.1.2-33)] on linux2
    Type "help", "copyright" , "credits" or "license" for more information.
    >>oats=[1]
    >>peas=[6]
    >>mylist = [oats, peas]
    >>mylist[1][0] = mylist[1][0]+1
    >>mylist
    [[1], [7]]
    >>peas
    [7]

    This is because integers are immutable, but lists are mutable.

    --
    Jeremy Sanders

    Comment

    • Grant Edwards

      #3
      Re: indirectly addressing vars in Python

      On 2008-10-01, Ross <nobody@nospam. nowaywrote:
      Forgive my newbieness - I want to refer to some variables and
      indirectly alter them. Not sure if this is as easy in Python
      as it is in C.
      Python doesn't have variables. It has names bound to objects.
      When you do an assignment, that binds (or rebinds) a name to an
      object. There is no such thing as a C-like "variable" (a named
      region of memory with a fixed location into which you can write
      different values).

      Some objects (e.g. lists, dictionaries) are mutable (you can
      change their value or contents), some objects (e.g. strings,
      integers, floats) are not mutable.
      Say I have three vars: oats, corn, barley
      >
      I add them to a list: myList[{oats}, {peas}, {barley}]
      >
      Then I want to past that list around and alter one of those
      values. That is I want to increment the value of corn:
      >
      myList[1] = myList[1] + 1
      >
      Is there some means to do that?. Here's my little session
      trying to figure this out:
      >
      >oats = 1
      >peas = 6
      Those two lines created two integer objects with values 1 and 6
      and bound the names "oats" and "peas" to those two objects.
      >myList=[]
      >myList
      []
      >myList.append( oats)
      That line finds the object to which the name "oats" is
      currently bound and appends that object to the list.
      >myList
      [1]
      >myList.append( peas)
      Likewise for the object to which the name "peas" is currently
      bound.
      >myList
      [1, 6]
      >myList[1]= myList[1]+1
      That line creates a new integer object (whose value happens to
      be 7) and replaces the object at position 1 in the list with
      the new object.
      >myList
      [1, 7]
      >peas
      6
      >>
      >
      So I don't seem to change the value of peas as I wished.
      Correct. The name "peas" is still bound to the same object it
      was before
      I'm passing the values of the vars into the list, not the vars
      themselves, as I would like.
      There are no "vars" as the word is used in the context of C
      programming. Just names and objects.

      Here's an article explaining it:

      If you are going to start programming in Python and come from languages like C or C++, there are a couple of things you should know about variable names. In Python, variable names do not have the s…


      A couple other good references:




      --
      Grant Edwards grante Yow! What GOOD is a
      at CARDBOARD suitcase ANYWAY?
      visi.com

      Comment

      • Chris Rebert

        #4
        Re: indirectly addressing vars in Python

        On Wed, Oct 1, 2008 at 7:53 AM, Ross <nobody@nospam. nowaywrote:
        Forgive my newbieness - I want to refer to some variables and indirectly
        alter them. Not sure if this is as easy in Python as it is in C.
        >
        Say I have three vars: oats, corn, barley
        >
        I add them to a list: myList[{oats}, {peas}, {barley}]
        You mean:
        myList = [oats, peas, barley]

        And you're not adding *variables* to a list, you're adding *values* to
        the list. The list elements (and the Python runtime) have *no idea*
        what variables they are/were bound to.
        >
        Then I want to past that list around and alter one of those values. That is
        I want to increment the value of corn:
        >
        myList[1] = myList[1] + 1
        This won't do what you're expecting. Integers in Python are immutable,
        so instead of changing the value of 'corn', you're calculating a new
        int object and overwriting the first element of the list with it.
        >
        Is there some means to do that?. Here's my little session trying to figure
        this out:
        >
        >>>oats = 1
        >>>peas = 6
        >>>myList=[]
        >>>myList
        []
        >>>myList.appen d(oats)
        >>>myList
        [1]
        >>>myList.appen d(peas)
        >>>myList
        [1, 6]
        >>>myList[1]= myList[1]+1
        >>>myList
        [1, 7]
        >>>peas
        6
        >>>>
        >
        So I don't seem to change the value of peas as I wished. I'm passing the
        values of the vars into the list, not the vars themselves, as I would like.
        >
        Your guidance appreciated...
        Python uses *call-by-object*, not call-by-value or call-by-reference
        semantics, so unlike C/C++ but like Java you can't make a "reference"
        to a variable and use that to non-locally rebind the variable to a new
        value. To do what you want, you need to create a mutable value that
        can be updated. You could code a "MutableInt " class wrapping 'int', or
        you could use a dictionary to hold the values and then always refer to
        the values using the dictionary. There are a few other ways to do it.

        Hope that elucidates it for you somewhat. Then again I am a little
        short on sleep :)

        Cheers,
        Chris
        --
        Follow the path of the Iguana...

        Comment

        • Bruno Desthuilliers

          #5
          Re: indirectly addressing vars in Python

          Chris Rebert a écrit :
          On Wed, Oct 1, 2008 at 7:53 AM, Ross <nobody@nospam. nowaywrote:
          >Forgive my newbieness - I want to refer to some variables and indirectly
          > alter them. Not sure if this is as easy in Python as it is in C.
          >>
          >Say I have three vars: oats, corn, barley
          >>
          >I add them to a list: myList[{oats}, {peas}, {barley}]
          >
          You mean:
          myList = [oats, peas, barley]
          >
          And you're not adding *variables* to a list, you're adding *values*
          s/values/references to objects/, actually

          (snip)

          Comment

          • Lie Ryan

            #6
            Re: indirectly addressing vars in Python

            On Wed, 01 Oct 2008 10:53:08 -0400, Ross wrote:
            Forgive my newbieness - I want to refer to some variables and indirectly
            alter them. Not sure if this is as easy in Python as it is in C.
            >
            Say I have three vars: oats, corn, barley
            >
            I add them to a list: myList[{oats}, {peas}, {barley}]
            >
            Then I want to past that list around and alter one of those values. That
            is I want to increment the value of corn:
            >
            myList[1] = myList[1] + 1
            >
            Is there some means to do that?. Here's my little session trying to
            figure this out:
            >
            >>oats = 1
            >>peas = 6
            >>myList=[]
            >>myList
            []
            >>myList.append (oats)
            >>myList
            [1]
            >>myList.append (peas)
            >>myList
            [1, 6]
            >>myList[1]= myList[1]+1
            >>myList
            [1, 7]
            >>peas
            6
            >>>
            >>>
            So I don't seem to change the value of peas as I wished. I'm passing
            the values of the vars into the list, not the vars themselves, as I
            would like.
            >
            Your guidance appreciated...
            >
            Ross.
            Short answer: Python is not C.

            Long answer: In python, integers are immutable (they do not change), i.e.
            if you do:
            a = 1
            b = 2
            c = a + b

            a + b creates a new integer object that has the value 3 and assign it to c

            Other examples of immutable values are: number types, string, tuple, etc.

            In python, "variable" is usually called "name". The concept of variable
            and name is slightly different.

            In C, a variable contains an object. In python, a name contains a pointer
            to an object. (the term "pointer" is used a bit loosely here)

            In python, a "list" is a list of pointers to objects.

            i.e.:

            |--"Hello World"
            myList |--1
            |--6

            when you do, for example, myList[2] + 1
            what you're doing is:
            1. fetch the value of myList[2] (i.e. 6)
            2. do an arithmetic addition of 6 + 1
            3. create a new integer object with value 7
            4. bind myList[2] to that new integer object (_new integer object_ since
            integer is immutable, you cannot change its value[1])

            in short, pea is left intact since pea points to integer object 6.

            beware though, that things are different if myList[2] is a mutable value
            instead and the operation is an in-place operation, e.g. list.sort
            >>a = [1, 2]
            >>b = [3, 2]
            >>myList.append (a)
            >>myList.append (b)
            >>myList[1].sort()
            >>myList
            [[1, 2], [2, 3]]
            >>b
            [2, 3]

            in this case a, b is mutable object, so:
            myList.append(x ) binds myList to the list object pointed by x
            myList[1].sort() is an in-place sort to the list object [3, 2] (i.e. it
            mutates the list [3, 2] instead of creating a new list[1]).

            in this case:

            myList |--[1, 2]
            |--[3, 2]

            myList[1].sort(), being an in-place sort, modifies the list object [3, 2]
            in-place. Since b points to the same list object, b's list is changed too.

            To summarize, you don't usually use that line of thinking in python. If
            you really insists, though is not pythonic (and is really absurd anyway),
            you may use this:
            >>a = [1]
            >>b = [2]
            >>myList.append (a)
            >>myList.append (b)
            >>myList[1][0] = myList[1][0] + 1
            >>myList
            [[1], [2]]
            >>b
            [3]

            [1] Well, not always though, in CPython (the standard python reference
            implementation) , small immutable values are cached as speed optimization.
            This is a safe operation, except for identity testing. But that doesn't
            matter much, since identity testing of immutable is moot.
            [2] If you want a sorting operation that returns a new list, use sorted
            (list)

            Comment

            Working...