В языках, которые поддерживают частные конструкторы (C #, Dart, Scala и т. Д.), Фабричные методы обеспечивают надежное решение этой проблемы.
Однако в Python конструкторы классов всегда доступны, и поэтому пользовательвашего класса может легко забыть фабричный метод и напрямую вызвать конструктор, создавая дубликаты копий объектов, которые должны быть уникальными.
Надежное решение этой проблемы может быть достигнуто с помощью метакласса.В приведенном ниже примере предполагается, что нулевой аргумент конструктора может использоваться для уникальной идентификации каждого экземпляра:
class Unique(type):
def __call__(cls, *args, **kwargs):
if args[0] not in cls._cache:
self = cls.__new__(cls, *args, **kwargs)
cls.__init__(self, *args, **kwargs)
cls._cache[args[0]] = self
return cls._cache[args[0]]
def __init__(cls, name, bases, attributes):
super().__init__(name, bases, attributes)
cls._cache = {}
. Он может использоваться следующим образом:
class Country(metaclass=Unique):
def __init__(self, name: str, population: float, nationalDish: str):
self.name = name
self.population = population
self.nationalDish = nationalDish
placeA = Country("Netherlands", 16.8e6, "Stamppot")
placeB = Country("Yemen", 24.41e6, "Saltah")
placeC = Country("Netherlands", 11, "Children's tears")
print(placeA is placeB) # -> False
print(placeA is placeC) # -> True
print(placeC.nationalDish) # -> Stamppot
В целом, этот подход полезенесли вы хотите создать набор уникальных объектов во время выполнения (возможно, используя данные, в которых записи могут повторяться).