passing class by reference does not work??

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

    #1

    passing class by reference does not work??

    Here is my code:

    class A():
    val = 0

    def b(item, a):
    a.val = a.val + 1
    return item + a.val

    def c():
    d = [1, 2, 3]
    print [b(item, A()) for item in d]

    c()

    I expected this to output [2, 4, 6]. However, it outputs [2, 3, 4]
    which is not what I wanted. I thought that if I passed the A()
    instance in my list comprehension in c(), then the changes I made to
    a.val in b() would be reflected in the A() instance next time the list
    comprehension called b(). But, obviously that is not happening. I'm
    kinda new at python so I may be missing something obvious here.

    Any suggestions?

  • antred

    #2
    Re: passing class by reference does not work??

    def b(item, a):
    a.val = a.val + 1
    return item + a.val



    This is where the problem lies, specifically the line a.val = a.val +
    1
    What happens here is that the 1st a.val refers to a member of the
    class instance a, called val ... which does not yet exist and is
    therefore created as the result of taking the val member of the class
    A and adding 1 to it. In other words, a.val is not the same variable
    as A.val. Are you following? If not, change your b() method to this:

    def b(item, a):
    a.val = a.val + 1
    assert a.val is A.val
    return item + a.val

    and see what happens.

    Comment

    • Alex Martelli

      #3
      Re: passing class by reference does not work??

      wswilson <wswilson@gmail .comwrote:
      Here is my code:
      >
      class A():
      val = 0
      >
      def b(item, a):
      a.val = a.val + 1
      return item + a.val
      >
      def c():
      d = [1, 2, 3]
      print [b(item, A()) for item in d]
      >
      c()
      >
      I expected this to output [2, 4, 6]. However, it outputs [2, 3, 4]
      which is not what I wanted. I thought that if I passed the A()
      instance in my list comprehension in c(), then the changes I made to
      a.val in b() would be reflected in the A() instance next time the list
      comprehension called b(). But, obviously that is not happening. I'm
      kinda new at python so I may be missing something obvious here.
      Yep:

      a.val = a.val + 1

      sets in INSTANCE variable a the value computed on the RHS. A.val (the
      CLASS variable) is never changed. You're not "passing the class", of
      course, but rather an instance of the class.

      To increment A.val, you need to assign to the class variable, or write
      some method in class A which assigns to the class variable. If you
      want, you can change class A only, leaving all of the rest of your code
      untouched, with a property (but then A needs to be newstile), e.g.:

      class A(object):
      _val = 0
      def getval(self): return A._val
      def setval(self, value): A._val = value
      val = property(getval , setval)

      now your code should work as intended: any read access to a.val returns
      A._val, and any setting of a.val actually sets A._val, as you appear to
      desire.


      Alex

      Comment

      • wswilson

        #4
        Re: passing class by reference does not work??

        On Apr 11, 10:36 am, "antred" <Nut...@gmx.net wrote:
        def b(item, a):
        a.val = a.val + 1
        return item + a.val
        >
        This is where the problem lies, specifically the line a.val = a.val +
        1
        What happens here is that the 1st a.val refers to a member of the
        class instance a, called val ... which does not yet exist and is
        therefore created as the result of taking the val member of the class
        A and adding 1 to it. In other words, a.val is not the same variable
        as A.val. Are you following? If not, change your b() method to this:
        >
        def b(item, a):
        a.val = a.val + 1
        assert a.val is A.val
        return item + a.val
        >
        and see what happens.
        OK, I see that. I thought I was creating an instance of the class A()
        when I called the list comprehension and that the a parameter in b()
        was then a reference to that instance. What can I do instead?

        Comment

        • wswilson

          #5
          Re: passing class by reference does not work??

          On Apr 11, 10:40 am, a...@mac.com (Alex Martelli) wrote:
          wswilson <wswil...@gmail .comwrote:
          Here is my code:
          >
          class A():
          val = 0
          >
          def b(item, a):
          a.val = a.val + 1
          return item + a.val
          >
          def c():
          d = [1, 2, 3]
          print [b(item, A()) for item in d]
          >
          c()
          >
          I expected this to output [2, 4, 6]. However, it outputs [2, 3, 4]
          which is not what I wanted. I thought that if I passed the A()
          instance in my list comprehension in c(), then the changes I made to
          a.val in b() would be reflected in the A() instance next time the list
          comprehension called b(). But, obviously that is not happening. I'm
          kinda new at python so I may be missing something obvious here.
          >
          Yep:
          >
          a.val = a.val + 1
          >
          sets in INSTANCE variable a the value computed on the RHS. A.val (the
          CLASS variable) is never changed. You're not "passing the class", of
          course, but rather an instance of the class.
          >
          To increment A.val, you need to assign to the class variable, or write
          some method in class A which assigns to the class variable. If you
          want, you can change class A only, leaving all of the rest of your code
          untouched, with a property (but then A needs to be newstile), e.g.:
          >
          class A(object):
          _val = 0
          def getval(self): return A._val
          def setval(self, value): A._val = value
          val = property(getval , setval)
          >
          now your code should work as intended: any read access to a.val returns
          A._val, and any setting of a.val actually sets A._val, as you appear to
          desire.
          >
          Alex
          Thanks, that should work well. I appreciate it.

          Comment

          Working...