You could hold the instance you work with in a class attribute.
Whenever you want to reset the class, reassign a new instance to that attribute.
Here is how I would implement this approach:
class Foo:
instance = None # The single instance
def __init__(self, ...):
# Initialize the instance if Foo.instance does not exist, else fail
if type(self).instance is None:
# Initialization
type(self).instance = self
else:
raise RuntimeError("Only one instance of 'Foo' can exist at a time")
@classmethod
def reset(cls):
cls.instance = None # First clear Foo.instance so that __init__ does not fail
cls.instance = Foo(...) # Now the initialization can be called
Then, you can access the instance by simply referring to Foo.instance
.
I chose to have the reset
as a class method, thus decorated by @classmethod
.
With this decorator, the instance can be reset by calling Foo.reset()
, and the cls
parameter will be passed automatically to the method.
I prefer this approach (which is more or less a singleton pattern) over those you suggest, because in your situation, it appears logical to have a single instance of Foo
, since you want to reset it.
Therefore, I find it rather intuitive to "force" the use of a single instance.
On the other hand, you could have an instance outside of the class, and use a reset
instance method, defined:
def reset(self):
self.__init__()
But this might not work so well.
Say you want to set attributes outside of the __init__
method.
Calling __init__
will not reset those attributes.
Therefore, your instance will not be reset as expected.
Now if you hold a single instance and reassign it to a brand new one, you're certain that it will be absolutely clean.
Regarding what you call "creating a new instance", that's more or less what I chose, but the question is where to store it.
I think it makes sense to keep it warm in the class itself.
By the way, there shouldn't be any performance issue (as in "memory leak") with this solution, since only one Foo
instance is referenced at a time, and creating a new one will de-reference the previous one.
__new__
method). Just create a new instance - if there are no other references to the previous instance, it will be discarded naturally. In other words: normal code does not call__init__
"manually" - just create a new instance and allow the language do that. – Discobolusself
in the reset method would be bad if you have a class variable that is changed with the init. Let us say the class keeps track of how many objects have been created withnum
and in__init__()
you add1
tonum
, then logically resetting isn't the same as creating. – Vehiclefoo.reset()
to reset all variables (but not the constant parameters) is a convenient and common use case (i.m.o.). – Mylonite.clear()
vs creating a new dict: just see how often each gets used in normal code. – Discobolus