Это у вас вышел совсем плохой варант.
Классы ради классов. Вообще в первую очередь нужно решать задачу, а не придумывать как бы применить тут наследование или полморфизм.
В вашем случае лишне сложности ни к чему. Они только добавляют проблем, но ни одной не решают.
Сделайте карту универсальной, сделайте ее на основе typing.NnamedTuple.
Пусть у каждой карты будет весь набор атрбутов, но только один какой-то будет ненулевым. Не нужно тут наследования, ведь у вас не используется полиморфизм.
В вашей реализации не получится сделать две колоды или больше. Колода у вас - это синглтон получается. Такое себе решение.
На сколько я понмаю предметную область, в колоде важна обычно не столько группировка карт, сколько их порядок. Так и храните карты в инкапсулированном списке.
Порядок карт не атрибут карт, он должен храниться в колоде.
Вполне можно держать в инстансе колоды в качестве индекса для быстрой группировки специальный словарь, но это сомнительная оптимизация на таком этапе. Сколько будет в вашей колоде? Является ли вообще бутылочным гордышком проблема группировки? Почему нельзя ее решать на даном этапе просто понятной фильтрацией?
В общем старайтесь применять новые изученные фичи аккуратно и тоько там, где это на самом деле решает проблемы.
Интересное упражнение - придумывать пример, где изученная концепция дейтсивтельно к месту. Нследование - это не про ваш вот этот пример с картами. По крайней мере на текущем уровне постановки задачи
Вот пример:
import datetime
import itertools
from typing import NamedTuple
class Card(NamedTuple):
name: str = None
phys_damage: int = 0
hp: int = 0
mage_damage: int = 0
armor: int = 0
add_hp: int = 0
def __repr__(self):
"""repr у нас будет показывать только аргументы, которые отличаются от умолчательных"""
defaults = type(self)._field_defaults
params = ', '.join(
f'{k}={v!r}'
for k, v in self._asdict().items()
if k in defaults and v != defaults[k]
)
return f'{type(self).__name__}({params})'
def __str__(self):
return f'<{self.name}#{id(self)}>'
@property
def total_hp(self):
return self.hp + self.add_hp
@property
def group(self):
return max(
(self.mage_damage, 'Intelegence'),
(self.add_hp, 'Strength'),
(self.armor, 'Agility'),
)[1]
class Deck():
def __init__(self, deck_name="Колода", date=None, cards=None):
self.deck_name = deck_name
self.date = date or datetime.now()
self.cards = cards or []
def __iter__(self):
return iter(self.cards)
def by_group(self):
return itertools.groupby(self, lambda card: card.group)
my_deck = Deck("Моя колода", "24.05.2022", [
Card("Течис", phys_damage=32, hp=600, mage_damage=100),
Card("Земеля", phys_damage=40, hp=600, mage_damage=60),
Card("Рудге", phys_damage=80, hp=600, add_hp=150),
Card("Крип", phys_damage=60, hp=600, armor=10),
])
for group, cards in my_deck.by_group():
print(f'# {group}:')
for card in cards:
print(f'\t{card!r}')