Этот шаблон не может быть выполнен разумно с __init__
, потому что __init__
только инициализирует уже существующий объект, и вы не можете изменить то, что получит вызывающий (вы можете выполнить повторную привязку * 1005) *, но это просто отсекает вас от создаваемого объекта, вызывающая сторона имеет свой собственный отдельный псевдоним, который не изменяется).
Правильный способ сделать это - переопределить фактический конструктор , __new__
, что позволяет возвращать новый экземпляр, который вы можете или не можете создать:
class Processo:
def __new__(cls, name, ...): # ... for simplicity
try:
# Try to return existing instance from storage
return getfromStorage(name)
except KeyError:
pass
# No instance existed, so create new object
self = super().__new__(cls) # Calls parent __new__ to make empty object
# Assign attributes as normal
self.processoname = name
# Return newly constructed object
return self
Чтобы уменьшить накладные расходы, я слегка переписал getfromStorage
, поэтому просто берет имя и выполняет поиск, позволяя исключению всплыть в случае сбоя:
def getfromStorage(processoname):
return process_storage[processoname]
, что означает, что при использовании кэшированного экземпляра не требуется заново создавать ненужный объект self
.
Примечание. Если вы это сделаете, обычно лучше вообще не определять __init__
; построение объекта выполняется путем вызова класса __new__
, а затем неявным образом вызова __init__
результата. Для кэшированных экземпляров вы не хотите, чтобы они были повторно инициализированы, поэтому вам нужен пустой __init__
(поэтому кэшированный экземпляр не изменяется в силу того, что он извлекается из кэша). Поместите все __init__
-подобное поведение в код, который создает и возвращает новый объект внутри __new__
, и выполняйте его только для новых объектов, чтобы избежать этой проблемы.