passing class by reference does not work??

W

wswilson

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

antred

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

Alex Martelli

wswilson said:
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
 
W

wswilson

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

wswilson

wswilson said:
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]

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.
 

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

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top