user6142489
user6142489

Reputation: 532

Python Variables across Class functions - how to call them?

Instead of using a global variable, I'm trying to make an instance of a variable in a class, as it seems to be best practice. How do I reference this variable across other functions in the class? I would have thought that Test.running_sum would work or at least running_sum in test_function, but I'm not having any luck with either. Thanks very much!

class Test:
    def __init__(self):
        self.root = None
        running_sum = 0

    def test_function(self):
        print(Test.running_sum)
        return

    x = Test()
    x.test_function()

Error:

Traceback (most recent call last):
  File "so.py", line 1, in <module>
    class Test:
  File "so.py", line 10, in Test
    x = Test()
NameError: name 'Test' is not defined

Upvotes: 1

Views: 67

Answers (4)

Zanilen
Zanilen

Reputation: 37

In your __init__ function, you've created a local variable. That variable will no longer exist after the function has completed.

If you want to create a variable specific to the object x then you should create a self.running_sum variable

class Test:
    def __init__(self):
        self.root = None
        self.running_sum = 0

    def test_function(self):
        print(self.running_sum)

If you want to create a variable specific to the class Test then you should create a Test.running_sum variable.

class Test:
    running_sum = 0
    def __init__(self):
        self.root = None

    def test_function(self):
        print(Test.running_sum)

Upvotes: 1

Prune
Prune

Reputation: 77900

As an object attribute: each object gets its own. Test is the class; self is the Test object that invoked the method.

class Test:
    def __init__(self):
        self.root = None
        self.running_sum = 0

    def test_function(self):
        self.running_sum += 1
        print(self.running_sum)
        return

x = Test()
y = Test()
x.test_function()
y.test_function()

Output: 1 1

As a class attribute: all objects share the same variable. self.__class__ is the class of the invoking object (i.e. Test).

class Test:
    running_sum = 0

    def __init__(self):
        self.root = None

    def test_function(self):
        self.__class__.running_sum += 1
        print(self.__class__.running_sum)
        return

x = Test()
y = Test()
x.test_function()
y.test_function()

Output:

1
2

Upvotes: 2

FunkySayu
FunkySayu

Reputation: 8091

Use self parameter provided in the method signature.

Note that what you wrote is not a method, but an external function using class Test. To write a method of Test, the def should be at one level of indentation inside class Test as following:

class Test:
    def __init__(self):
        self.running_sum = 0
    def test_function(self):
        print(self.running_sum)

There are several things to add if you want an explanation behind this "best practice".

Assuming you write the following code:

class Test:
    numbers = []
    def add(self, value):
        self.numbers.append(value)

The Test.numbers list is instantiated once and shared accross all instances of Test. Therefore, if 2 different instances add to the list, both act on the same list:

a = Test()
b = Test()
a.add(5)
b.add(10)
assert a.numbers == b.numbers == Test.numbers

When creating instance variables in the __init__ function, __init__ will be run at each instantiation, and therefore, the list will no longer be shared because they will be created for each individual instances.

class Test:
    def __init__(self):
        self.numbers = []
    def add(self, number):
        self.numbers.append(number)

a = Test()
b = Test()
a.add(5)
b.add(10)
assert a != b

Upvotes: 5

Cyzanfar
Cyzanfar

Reputation: 7146

how do I reference this variable across other functions in the class

Several things I see wrong here. First of all, you are calling running_sum on the class itself which doesn't make sense since you are declaring running_sum as an attribute of an instance of Test. Second, from the way you formatted your question, it seems that test_function is outside of the class Test which doesn't make sense since you are passing self to it, implying it is an instance method. To resolve you could do this:

class Test:
    def __init__(self):
        self.running_sum = 0
    def test_function(self):
        print(self.running_sum)

Then again this also is weird... Why would you need a "test_function" when you can simply test the value of running_sum by simply doing:

x = Test()
x.running_sum

Upvotes: 1

Related Questions