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)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.