Чтобы получить представление о том, как структурировать ваш код, вы могли бы подумать с точки зрения композиции, агрегации, ассоциации.
В чем разница между объединением, агрегацией и составом?
https://www.visual-paradigm.com/guide/uml-unified-modeling-language/uml-aggregation-vs-composition/
Тем не менее есть несколько возможностей, вам нужно решить, какой из них самый важный (у владельца есть оружие, у оружия есть владелец).
Скажем, у каждого оружия есть только один владелец за раз, как вы хотите получить доступ к оружию?
owner.weapon
-> тогда вы знаете владельца
Или вы можете оставить ссылку на владельца в качестве атрибута оружия:
weapon.owned_by
-> возможно использовать id
здесь не ссылка на реальный класс, это ваша текущая проблема, верно?
Существует ли оружие без владельца? Затем посмотрите на Композиция :
Композиция подразумевает отношения, в которых ребенок не может существовать независимо от родителя.
Пример композиции: Дом (родитель) и Комната (ребенок). Комнаты не существуют без дома.
Пример не композиции: Автомобиль и Шина. Шины существуют без автомобилей.
Общая тема о том, почему лучше избегать циклических ссылок: https://softwareengineering.stackexchange.com/questions/11856/whats-wrong-with-circular-references
Вы также можете попробовать рассмотреть инверсию зависимости ( Принцип впрыска) (см. здесь или здесь ). Я думаю, что вы уже попробовали это при первом подходе (передача экземпляра оружия в Animal). Идея была прекрасной, но, возможно, вам нужен еще один промежуточный слой.
Еще одна вещь, исходя из Java, вы привыкли к геттерам и сеттерам. Это не так популярно в Python, (но вы могли бы это сделать).
Ваш подход:
class Weapon(ABC):
def set_wielder(wielder: Animal) -> None:
self.wielder = wielder
Больше Pythoni c, используйте Свойства ("дескрипторы"):
class Weapon(ABC):
def __init__(self):
# notice the underscore, it indicates "treat as non-public"
# but in Python there is no such thing
self._wielder = None
@property #this makes it work like a getter
def wielder(self) -> Animal: # not sure about the annotation syntax
return self._wielder
@wielder.setter
def wielder(wielder: Animal) -> None:
self._wielder = wielder
Вы можете прочитать о дескрипторах здесь , здесь и с немного большей теорией здесь .