Reputation: 139
I was making a Singleton design pattern and everything goes fine.
Look at the code below:
class Singleton():
def __new__(cls):
if not hasattr(cls, 'instance'):
cls.instance = super().__new__(cls)
return cls.instance
s1 = Singleton()
s2 = Singleton()
print(s1 is s2)
# True
But this is not Singleton because user can use delattr(Singleton,'instance')
between creating s1
and s2
and with this simple function s1 is s2
returns False
So I decided to change instance
to __instance
(to stop user using delattr(Singleton,'instance')
) but when I do that I get False when printing s1 is s2
(My new code (__instance))
class Singleton():
def __new__(cls):
if not hasattr(cls, '__instance'):
cls.__instance = super().__new__(cls)
return cls.__instance
s1 = Singleton()
s2 = Singleton()
print(s1 is s2)
# False
But where is the problem?
Why when I change instance
to __instance
the result I get is False?
(I know other methods of creating Singleton I Just want to know what is different in instance
and __instance
when I'm in the class and __instance
is not private for myself)
Upvotes: 1
Views: 136
Reputation: 77357
Python name mangles the variable. Its called "_Singleton__instance" in the class __dict__
. You could use that name instead or use an exception handler for the assignment. In that case, python does the mangling for you and it would work for subclasses of Singleton also.
class Singleton():
def __new__(cls):
# could do this ....
#if not hasattr(cls, '_Singleton__instance'):
# cls.__instance = super().__new__(cls)
#return cls.__instance
try:
return cls.__instance
except AttributeError:
cls.__instance = super().__new__(cls)
return cls.__instance
s1 = Singleton()
s2 = Singleton()
print(s1 is s2)
Of course its still easily defeated
delattr(Singleton, "_Singleton__instance")
s3 = Singleton()
print(s1 is s3)
Python is a very dynamic language and if someone wants to hurt themself, then have at it!
Upvotes: 1