Reputation: 665
I have a class called EventManager, and am calling this class in each module I have. I thought of creating a single instance of the EventManager in the main file, and use that instance in each module. My questions are:
Upvotes: 7
Views: 7081
Reputation: 277
This question is old but it was the first that came up for me, so I think it might be good to mention for others that there is a lot of talk about singletons being antipatterns, not pythonic etc.
After searching for a while, I think the best method is to use a metaclass:
In general, it makes sense to use a metaclass to implement a singleton. A singleton is special because is created only once, and a metaclass is the way you customize the creation of a class. Using a metaclass gives you more control in case you need to customize the singleton class definitions in other ways.
Upvotes: 0
Reputation: 13423
You could use a singleton. Here is a simple example:
def singleton(cls):
return cls()
@singleton
class EventManager:
def __init__(self):
self.events = []
def add_event(self, event):
self.events.append(event)
def print_events(self):
print("Events : {}".format(self.events))
EventManager.add_event(0)
EventManager.add_event(1)
EventManager.add_event(2)
EventManager.print_events()
Output:
Events : [0, 1, 2]
Note that everything still works as expected when the singleton is imported and used in other modules.
EDIT
You asked :
The thing is that I initialize the class with a variable like EventManager(var), what shall I do in this case?
The class will be instantiated right after its definition, i.e. the first time the module containing EventManager
is imported. Since EventManager
is a singleton, I don't think there is a point initializing the singleton with a variable. Even though it is possible:
def singleton_with_args(*args, **kwargs):
def wrapper(cls):
return cls(*args, **kwargs)
return wrapper
@singleton_with_args(0)
class EventManager:
def __init__(self, first_event):
self.events = [first_event]
def add_event(self, event):
self.events.append(event)
def print_events(self):
print("Events : {}".format(self.events))
EventManager.add_event(1)
EventManager.add_event(2)
EventManager.add_event(3)
EventManager.print_events()
Output:
Events : [0, 1, 2, 3]
It works but as I said, I don't think it's useful. You could as well use methods or module variables to initialize your singleton.
Upvotes: 10