dpsguy
dpsguy

Reputation: 7

Returning value to calling class in Python

I’m new to Python and OOP (& StackOverflow), so excuse me if the question is too naïve, but I can’t seem to get it solved on my own. I’ve just written a very simple program to see how OOP works, which I reproduce below:

from System import *

class trial(object):
    def __init__(self, counter):
        self.counter = counter

    def passon(self):
        p = person(self.counter)
        p.increase()

class person(object):
    def __init__(self, counter):
       self.counter = counter


    def increase(self):
       self.counter +=1
       return self.counter

I call the function like this:

t = trial(2)
t.passon()

I was expecting the value of counter to updated automatically in class trial, however when I type t.counter, it still returns 2. But if I write:

p = person(t.counter)
p.increase()

then p.counter becomes 3. How do I increase the value of counter in class trial? I know I am making some elementary mistake here, but I’d appreciate any help.

Upvotes: 1

Views: 216

Answers (4)

cwallenpoole
cwallenpoole

Reputation: 81988

Your issue has to do with how Python treats objects -- some are immutable (you can't change them, you can only replace them) and some are mutable (you can change their internal state).

(If you know about references and pass by value vs. pass by reference etc. ints, floats, strings and tuples are like pass by value, (almost) everything else is mutable).

ints are "immutable" which means that when you perform some operation on it, it is actually returning a new copy (it can also be a cached value) of the int.

So this:

self.counter = self.counter + 1

is almost like this

self.counter = new int(counter + 1) # I know, "new" isn't pythonic, 
     #but it is clearer in OOP with the int function.

So, since self.counter is not the same thing which was originally passed to it, there is no way to have both p and t point to the same object.

The solution? Make Trial have a Person as a property:

from System import *

class trial(object):
    def __init__(self, counter):
        self.person = person(counter)

    def passon(self):
        p.increase()

class person(object):
    def __init__(self, counter):
       self.counter = counter

    def increase(self):
       self.counter +=1
       return self.counter

t = trial(2);
t.person # <!-- this is your person object.
t.passon()
print(t.person.counter) # 3
t.passon()
print(t.person.counter) # 4

Upvotes: 0

martineau
martineau

Reputation: 123393

Each of your classes has a separate counter attribute. If you want to update the trial object's counter with the result of calling p.increase(), you would need to do something similar to this in passon():

def passon(self):
    p = person(self.counter)
    self.counter = p.increase()

Upvotes: 0

Artsiom Rudzenka
Artsiom Rudzenka

Reputation: 29093

I believe that each class has it's own counter. Modify your 'passon' function the following way and you will see this:

def passon(self):
    p = person(self.counter)
    print 't', self.counter
    print 'p', p.counter
    p.increase()
    print 'p', p.counter
    print 't', self.counter

Upvotes: 1

Ignacio Vazquez-Abrams
Ignacio Vazquez-Abrams

Reputation: 798456

Integers in Python are immutable. Pass the trial to the person, and increment the attribute on the saved trial instead.

Upvotes: 4

Related Questions