Python Variables across Class functions - how to call them? - python

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

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

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

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

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)

Related

How to access variables created in __init__ in another def in the same instance of a class?

Goal: Being able to access a in play.
Note: I need to save information via variables in the same instance of the class because play will be called multiple times.
Code:
class something():
def __init__(self):
a = 2
def play(self, b):
return True if a == b else False
test = something()
print(test.play(1))
Expectations: It should print False because 2 != 1, but I get this error instead:
UnboundLocalError: local variable 'a' referenced before assignment
I've tried:
Getting rid of __init__ and just putting the int outside a def.
Setting up the int before __init__ and just accessing it in __init__.
Note: I can't pass arguments to __init__ while making a new instance of the class, this is for an exercise, which can be found here, and I don't control the creation of a new instance.
class something():
def __init__(self):
self.a = 2
def play(self, b):
return True if self.a == b else False
test = something()
print(test.play(1))
In the __init__ you have to use self.variable and same can be used in other functions too of same class.

Python class variable accessed by multiple instances

I want to define a global variable which can be accessed (read and write) by all instances of the class. My current solution is shown in the example below. I don't like having a variable in the global namespace, but I was not able to put idx in class. How can I put idx in class and achieve the same?
# working
idx = 0
class test(object):
def add(self):
global idx
idx += 1
def print_x(self):
global idx
print(idx)
test1 = test()
test1.add()
test1.print_x()
test2 = test()
test2.add()
test2.print_x()
# Error
class test(object):
idx = 0
def add(self):
global idx
idx += 1
def print_x(self):
global idx
print(idx)
test1 = test()
test1.add()
test1.print_x()
test2 = test()
test2.add()
test2.print_x()
Traceback (most recent call last):
File "test.py", line 16, in <module>
test1.add()
File "test.py", line 9, in add
idx += 1
NameError: global name 'idx' is not defined
Your code fails because you tried to access a global variable idx without properly declaring it. You need to access your class variable.
class Test(object):
idx = 0
def add(self):
Test.idx += 1
obj = Test()
obj.add()
print(Test.idx)
obj = Test()
obj.add()
print(Test.idx)
Output:
1
2
Here's a hacky little way that doesn't need any global variables. It makes use of the fact that default arguments are only created once when __init__ is called for the first time and if the default arguments are mutable, then changing one of them will impact all future functions/instances of the same class.
We can create idx as a list since lists are mutable and then make sure we only modify that list in place. Doing so like this will ensure that all instances of your Test class point to the exact same idx list. Changing one changes them all, so long as you only do in-place modifications.
class Test:
def __init__(self, idx = [0]):
self.idx = idx
def add(self):
self.idx[0] += 1
a = Test()
b = Test()
a.add()
print(a.idx, b.idx)
# >> Prints [1], [1]
You can achieve this using a singleton pattern. Here is a small example with singleton:
class Singleton:
# Here will be the instance stored.
__instance = None
#staticmethod
def getInstance():
""" Static access method. """
if Singleton.__instance == None:
Singleton()
return Singleton.__instance
def add(self):
self.idx += 1
def __init__(self):
""" Virtually private constructor. """
if Singleton.__instance != None:
raise Exception("This class is a singleton!")
else:
Singleton.__instance = self
self.idx = 0
In [3]: main = Singleton()
In [4]: a = Singleton.getInstance()
In [5]: print(a.idx)
0
In [6]: a.add()
In [7]: print(a.idx)
1
In [8]: b = Singleton.getInstance()
In [9]: print(b.idx)
1
Ref: https://www.tutorialspoint.com/python_design_patterns/python_design_patterns_singleton.htm
There are some elegant Singleton examples on SO as well.
You have to define your variable in the class, outside of methods, and it shall not be a self variable. A self variable is unique to every instances.
In methods you have to use the class name for accessing the variable, otherwise the method will look at it as a private variable, and in most cases you will get an error, because it was not initialized before usage.
class MyClass:
my_public_variable = 0
__my_private_variable = 5
def inc(self):
MyClass.my_public_variable += 1
MyClass.__my_private_variable += 1
def show(self):
print(MyClass.my_public_variable)
print(MyClass.__my_private_variable)
obj1 = MyClass()
obj1.show()
obj2 = MyClass()
obj2.show()
obj1.inc()
obj2.show()
print(obj1.my_public_variable)
print(obj1.my_private_variable) # Invokes error
By running this code, the following will be printed out without the parenthesis:
0 (my_public_variable of obj1)
5 (my_private_variable of obj1)
0 (my_public_variable of obj2)
5 (my_private_variable of obj2)
1 (my_public_variable of obj2, incremented by obj1)
6 (my_private_variable of obj2, incremented by obj1)
1 (my_public_variable of obj1, it can be accessed outside of the class, since it is a public variable of the class)
Error (because, as its name suggests, my_private_variable is a private variable of the class)

Why is a variable in __init__() method not defined in the subclass?

In subclass ComputerGame, Toy.__init__(self,n), n is undefined.
Why is it warning me that the variable n is undefined when I try to call the __init__() function in the base class? Simply put, why is Toy.__init__(self,n) not callable in the subclass? I have declared ComputerGame (Toy):. Why isn't it inheriting the method Toy.__init__(self,n)?
Should I declare the variable outside the class?
class Toy:
def __init__(self,n):
self.__ToyName = n
self.__ToyID = ""
self.__Price = 0.00
self.__MinimumAge = 4
def SetToyName(self,p):
self.__ToyName = p
def SetToyID(self,d):
self.__ToyID = d
def SetPrice(self,i):
self.__Price = i
def SetMinimumAge(self,i):
self.__MinimumAge = i
def GetToyName(self):
return (self.__ToyName)
def GetToyID(self):
return (self.__ToyID)
def GetPrice(self):
return (self.__Price)
def GetMinimumAge(self):
return (self.__MinimumAge)
class ComputerGame(Toy):
def __init__(self):
Toy.__init__(self,n)
self.__Catogory = ""
self.__Console = ""
def SetCatogory(self,c):
self.__Catogory = c
def SetConsole(self,c):
self.__Console = c
def GetCatogory(self):
return (self.__Catogory)
def GetConsole(self):
return (self.__Console)
This is a scoping issue:
class ComputerGame(Toy):
def __init__(self):
Toy.__init__(self,n)
This is the first appearance of n. When you create a ComputerGame, your __init__ methods requires you (the calling program) to supply n as part of the creation. That's how you wrote the code.
The __init__ above assumes that n will appear magically from nowhere. I'm unclear what data flow you expect from this -- and so is the Python compiler. I don't know how to fix this for you, since you failed to supply a Minimal, complete, verifiable example. We should have at least one line of main code to create the object.
One strong possibility is fairly simple:
class ComputerGame(Toy):
def __init__(self, n):
Toy.__init__(self, n)
NewFPS = ComputerGame("Universal Uzi")
Does that clear it up?

confused value scope in python

Hi I have staring programming with c and I conld'nt understand value scope in python.
here is my code
class ScenarioEnvironment():
def __init__(self):
print(self)
class report():
config = ScenarioEnvironment()
def __init__(self):
self.config = ScenarioEnvironment()
what happens passing config and config at init()?
and I wonder the value scope which config will be class valuable?
You need to know the differences between class attribute and instance object attribute.
Maybe these codes will help you:
class TestConfig1(object):
config = 1
def __init__(self):
self.config = 2
class TestConfig2(object):
config = 1
def __init__(self):
self.config2 = 2
if __name__ == "__main__":
print TestConfig1.config
t = TestConfig1()
print t.config
t2 = TestConfig2()
print t2.config
print t2.config2
more you can see the python blog.click here
Since your question seems a bit ambiguous, I'll just comment/fix your code:
class ScenarioEnvironment():
def __init__(self,x):
self.x = x # Assigning instance variable x to constructor parameter x.
print(self) # You're printing the object instance.
class report():
# Static variable shared amongst all classes.
config = ScenarioEnvironment(None) # Assigned to new instance of ScenarioEnvironment.
def __init__(self):
# No argument, must pass one (None).
# self.config is to a new ScenarioEnvironment instance.
self.config = ScenarioEnvironment(None)
Lets try out the classes.
Output:
s = ScenarioEnvironment(None)
r = report()
>>> <__main__.ScenarioEnvironment instance at 0x026F4238>
>>> <__main__.ScenarioEnvironment instance at 0x026F4300>
>>> <__main__.ScenarioEnvironment instance at 0x026F4350>

python using __init__ vs just defining variables in class - any difference?

I'm new to Python - and just trying to better understand the logic behind certain things.
Why would I write this way (default variables are in __init__):
class Dawg:
def __init__(self):
self.previousWord = ""
self.root = DawgNode()
self.uncheckedNodes = []
self.minimizedNodes = {}
def insert( self, word ):
#...
def finish( self ):
#...
Instead of this:
class Dawg:
previousWord = ""
root = DawgNode()
uncheckedNodes = []
minimizedNodes = {}
def insert( self, word ):
#...
def finish( self ):
#...
I mean - why do I need to use __init__ -> if I can just as easily add default variables to a class directly?
When you create variables in the Class, then they are Class variables (They are common to all the objects of the class), when you initialize the variables in __init__ with self.variable_name = value then they are created per instance and called instance variables.
For example,
class TestClass(object):
variable = 1
var_1, var_2 = TestClass(), TestClass()
print var_1.variable is var_2.variable
# True
print TestClass.variable is var_1.variable
# True
Since variable is a class variable, the is operator evaluates to True. But, in case of instance variables,
class TestClass(object):
def __init__(self, value):
self.variable = value
var_1, var_2 = TestClass(1), TestClass(2)
print var_1.variable is var_2.variable
# False
print TestClass.variable is var_1.variable
# AttributeError: type object 'TestClass' has no attribute 'variable'
And you cannot access an instance variable, with just the class name.
When you write this:
class Dawg:
previousWord = ""
root = DawgNode()
uncheckedNodes = []
minimizedNodes = {}
Those are not instance variables, they're class variables (meaning: the same variables with the same values are shared between all instances of the class.) On the other hand, this:
class Dawg:
def __init__(self):
self.previousWord = ""
self.root = DawgNode()
self.uncheckedNodes = []
self.minimizedNodes = {}
... Is declaring instance variables, meaning: the values are different for each instance of the class. As you see, each snippet means a completely different thing, and you have to pick the one that is appropriate for you. Hint: most of the time you're interested in instance variables, because class variables define a kind of shared global state for your objects, which is error prone.

Categories

Resources