What is the ‘correct’ or ‘right’ way to handle classes with many attributes? I have a class with 37 attributes and it seems quite excessive and not practical.
This class is going to be used to handle inserting this data to a database, retrieve that information from a database and its also going to be used to run some mathematic models.
I thought about putting all that information to a dictionary but accessing these attributes might be easier and clearer if they are attributes rather than if they would be in a dictionary.
What are your thoughts on this? Down below is the class and its init method.
class Statistics: def __init__(self, match_id, home_ball_possession = None, away_ball_possession = None, home_goal_attempts = None, away_goal_attempts = None, home_shots_on_goal = None, away_shots_on_goal = None, home_shots_off_goal = None, away_shots_off_goal = None, home_blocked_shots = None, away_blocked_shots = None, home_free_kicks = None, away_free_kicks = None, home_corner_kicks = None, away_corner_kicks = None, home_offsides = None, away_offsides = None, home_throw_ins = None, away_throw_ins = None, home_goalkeeper_saves = None, away_goalkeeper_saves = None, home_fouls = None, away_fouls = None, home_red_cards = None, away_red_cards = None, home_yellow_cards = None, away_yellow_cards = None, home_total_passes = None, away_total_passes = None, home_completed_passes = None, away_completed_passes = None, home_tackles = None, away_tackles = None, home_attacks = None, away_attacks = None, home_dangerous_attacks = None, away_dangerous_attacks = None ) -> None: self.match_id = match_id self.home_ball_possession = home_ball_possession self.away_ball_possession = away_ball_possession self.home_goal_attempts = home_goal_attempts self.away_goal_attempts = away_goal_attempts self.home_shots_on_goal = home_shots_on_goal self.away_shots_on_goal = away_shots_on_goal self.home_shots_off_goal = home_shots_off_goal self.away_shots_off_goal = away_shots_off_goal self.home_blocked_shots = home_blocked_shots self.away_blocked_shots = away_blocked_shots self.home_free_kicks = home_free_kicks self.away_free_kicks = away_free_kicks self.home_corner_kicks = home_corner_kicks self.away_corner_kicks = away_corner_kicks self.home_offsides = home_offsides self.away_offsides = away_offsides self.home_throw_ins = home_throw_ins self.away_throw_ins = away_throw_ins self.home_goalkeeper_saves = home_goalkeeper_saves self.away_goalkeeper_saves = away_goalkeeper_saves self.home_fouls = home_fouls self.away_fouls = away_fouls self.home_red_cards = home_red_cards self.away_red_cards = away_red_cards self.home_yellow_cards = home_yellow_cards self.away_yellow_cards = away_yellow_cards self.home_total_passes = home_total_passes self.away_total_passes = away_total_passes self.home_completed_passes = home_completed_passes self.away_completed_passes = away_completed_passes self.home_tackles = home_tackles self.away_tackles = away_tackles self.home_attacks = home_attacks self.away_attacks = away_attacks self.home_dangerous_attacks = home_dangerous_attacks self.away_dangerous_attacks = away_dangerous_attacks
Edit: changed attribute names from camelCase to lowercase, with words separated by underscores
import dataclasses @dataclasses.dataclass class Statistics: matchId: X homeBallPossession: X awayBallPossession: X ...
X‘s with type names, e.g.
typing.Optional[int], and so on.
This way, you don’t have to write out a constructor at all, so you don’t have to repeat every single field three times (once as the parameter and two more times in the assignment):
dataclasses does all the boilerplate for you.
You can then use the constructor as you’d expect, with keyword-arguments for each field, as well as assign to (and read) each field in the normal way:
stats = Statistics(matchId=someMatchId, ...) ... stats.homeBallPossession = someValue ...