python 3.9
Господа питонисты, поймал странный(?) кейс. Объясните пожалуйста причину явления, описаного в кейсе ниже. Спасибо за ранее.
Кейс:
Есть базовый класс сервис (BaseService), реализующий два метода (
add(self, collection: BaseCollection)
и
add_one(self, entity: BaseEntity)
):
class BaseEntity:
pass
class BaseCollection:
items = []
def __init__(self, items: list = []):
self.items = items
class CollectionsFactory:
@staticmethod
def create(name: str, items: list = []) -> BaseCollection:
if name == Enums.CONTACT:
return CollectionsFactory.create_contacts_collection(items)
# ...
@staticmethod
def create_contacts_collection(items: list = []) -> ContactsCollection:
return ContactsCollection(items)
class BaseService:
def add(self, collection: BaseCollection):
# ... какие то действия (запросы в бд/апи/и тд)
# создание новой коллекции (для моего метода
# add новая коллекция нужна, но не стал добавлять
# реализации, потому что иначе придется углубляться в
# иерархию других классов, это лишнее, в кейсе важен лишь
# факт создания еще одной коллекции внутри метода add)
response_collection = CollectionsFactory.create(self.get_entity_name())
# далее какая то обработка и возврат результата в response_collection
def add_one(self, entity: BaseEntity):
items = [entity]
# self.get_entity_name(self, name: str) -> BaseCollection:
# определяется в конкретном классе, то есть он абстрактный
collection = CollectionsFactory.create(self.get_entity_name(), items)
return self.add(collection)
Код выше это каркас для определения конкретных реализаций, например, Users-(Entity, Collection,Service), Posts-(Entity, Collection,Service) и так далее. Далее код для конкретной реализации:
class ContactEntity(BaseEntity):
pass
class ContactsCollection(BaseCollection):
pass
class ContactsService(BaseService):
def get_entity_name() -> str:
return Enums.Contact
Теперь о самом странном артефакте, нас интересует метод BaseService.add(), в нем есть создание response_collection и аргумент collection. Почему то collection.items попадают в response_collection.items при использовании фабрики. Вот и весь артефакт, не понимаю почему так происходит... То есть если внутри метода вывести список элементов обоих коллекций (collection и response_collection):
...
def add(self, collection: BaseCollection):
# ... какие то действия (запросы в бд/апи/и тд)
response_collection = CollectionsFactory.create(self.get_entity_name())
print(collection.items)
print(response_collection.items)
# то результат будет таким
# два одинаковых объекта в разных инстансах коллекции ContactsCollection ...
# Как так?
# [<src.models.contacts.Contact object at 0x7f09ac384a00>]
# [<src.models.contacts.Contact object at 0x7f09ac384a00>]
...