У меня есть класс, который по дизайну должен соответствовать шаблону singleton. Поэтому я пошел дальше и реализовал его с использованием метакласса . Все работало хорошо, пока не сообщалось об ошибке, которая, в общем, говорила, что deepcopy
-описанные экземпляры моего singleton не были теми же экземплярами.deepcopy не уважает метакласс
я могу обойти эту ошибку путем наследования от базового одноплодной типа класса, но я скорее не хотел, по причинам, указанный в this question.
рабочий пример этой проблемы представлен ниже:
class SingletonMeta(type):
def __init__(cls, name, bases, dict):
super(SingletonMeta, cls).__init__(name, bases, dict)
cls.instance = None
def __call__(cls,*args,**kw):
print "SingletonMeta __call__ was called"
if cls.instance is None:
cls.instance = super(SingletonMeta, cls).__call__(*args, **kw)
return cls.instance
class MyClass1(object):
__metaclass__ = SingletonMeta
class SingletonBase(object):
_instance = None
def __new__(class_, *args, **kwargs):
print "SingletonBase __new__ was called"
if not isinstance(class_._instance, class_):
class_._instance = object.__new__(class_, *args, **kwargs)
return class_._instance
class MyClass2(SingletonBase):
pass
from copy import deepcopy as dcp
mm1 = MyClass1()
mm2 = dcp(mm1)
print "mm1 is mm2:", mm1 is mm2
mb1 = MyClass2()
mb2 = dcp(mb1)
print "mb1 is mb2:", mb1 is mb2
Выход:
SingletonMeta __call__ was called
mm1 is mm2: False
SingletonBase __new__ was called
SingletonBase __new__ was called
mb1 is mb2: True
Можете ли вы дать мне какие-либо указатели о том, как нужно решить эту проблему? Я бегу на Python 2.7.x
Единственная проблема с этим решением (а также с @AKX, так как эти два эквивалентны) заключается в том, что если пользователю метакласса «SingletonMeta» нужна пользовательская реализация '__deepcopy__', она будет перезаписана (если я правильно понимаю). Разве это не так? –
@ dare2be Имеет ли смысл иметь пользовательский '__deepcopy__' на одноэлементном? Синглтон означает, что копия никогда не должна быть. Поэтому '__deepcopy__' всегда должна быть функцией идентификации. – agf
Думаю, ты прав. И если кому-то нужно настраивать '__deepcopy__', они не должны использовать синглтон в первую очередь. Поскольку ваши ответы и ответы AKX почти одинаковы, я выберу AKX для того, чтобы быть «первым». И для RTFM. : P Спасибо вам все равно! –