Прототип

описание
Прототип - это частично или полностью инициализированный объект, который вы копируете и используете. Он позволяет вам создавать копию существующего объекта и модернизировать его согласно вашим нуждам, вместо того, чтобы создавать объект заново.

При использовании прототипа необходимо клонировать объект-прототип и изменить его, для этого используется "глубокое копирование".
Пример
Опишем пример с отправлением посылки. На почте при заполнении полей "Пункт отправления" часто необходимо менять только часть адреса, так как посылки комплектуются на одном отделении.

При заполнении полей адреса нет необходимости заводить все поля, вместо этого делается копия ,базовой записи sender и вносятся изменения. Копирование делается методом deepcopy(), это позволяет проводить "глубокое копирование".

from copy import deepcopy
from dataclasses import dataclass


@dataclass
class Address:
    country: str
    city: str
    street_address: str

    def __str__(self):
        return f'Пункт отправления {self.street_address},' +\
               f'{self.city}, {self.country}'


@dataclass
class Package:
    sender: str
    address: Address

    def __str__(self):
        return f'Отправитель {self.sender} {self.address}'


if __name__ == '__main__':
    '''Базовая запись'''
    sender = Package("", Address("RU", "Екатеринбург", ""))

    '''Копирование базовой записи'''
    sender1 = deepcopy(sender)
    sender1.sender = "Андрей"
    sender1.address.street_address = "Маяковского 145"
    print(sender1)

    '''Копирование базовой записи'''
    sender2 = deepcopy(sender)
    sender2.sender = "Михаил"
    sender2.address.street_address = "Ленина 45"

    print(sender2)
    print(sender)

Создание фабрики прототипов
Рассмотрим пример создания фабрики прототипов. Нам необходимо сформировать объект, который хранит информацию о получателе посылки и почтамте приема Postamp.

Так как большинство данных почтамта известна заранее, опишем прототипы дынных объектов в виде фабрики PostampFactory.

Опишем методы, которые позволяют вносить изменения в прототипы объектов для удобного доступа при создании объектов.

from copy import deepcopy
from dataclasses import dataclass
from typing import ClassVar


@dataclass
class Address:
    country: str
    city: str
    street_address: str

    def __str__(self):
        return f'Пункт отправления {self.street_address},' +\
               f'{self.city}, {self.country}'


@dataclass
class Package:
    sender: str
    address: Address

    def __str__(self):
        return f'Отправитель {self.sender} {self.address}'


@dataclass
class Postamp:
    recipient: str
    postamp: str
    address: Address

    def __str__(self):
        return f'Получатель {self.recipient}, Почтамп: {self.postamp} ' +\
               f'{self.address}'


@dataclass
class PostampFactory():
    мoscow: ClassVar = Postamp('', 'Центральный', Address('RU', 'Москва', ''))
    vladivostok: ClassVar = Postamp('', 'Южный', Address('RU', 'Владивосток', ''))

    @staticmethod
    def __new_postman(proto, name):
        result = deepcopy(proto)
        result.recipient = name
        return result

    @staticmethod
    def moscow_postamp(name):
        return PostampFactory.__new_postman(PostampFactory.мoscow, name)

    @staticmethod
    def vladivostok_postamp(name):
        return PostampFactory.__new_postman(PostampFactory.vladivostok, name)


if __name__ == '__main__':
    recipient1 = PostampFactory.moscow_postamp('Иванов Иван')
    recipient2 = PostampFactory.vladivostok_postamp('Петров Петр')

    print(recipient1)
    print(recipient2)