You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何合理处理拥有大量属性的类?

如何合理处理拥有大量属性的类?

朋友,遇到这种属性超多的类确实头大,不过你这个场景其实挺典型的——体育比赛数据本来就是成对的主场/客场统计,咱们可以从结构优化和代码简化两个方向来解决问题,具体给你几个实用方案:

一、按逻辑分组封装属性

把主场和客场的统计数据单独抽成一个子结构,比如一个TeamStats类,这样原有的Statistics类只需要维护match_id、home_stats、away_stats三个核心属性就行。不仅代码结构更清晰,后续维护分组统计字段也更方便,不管是存数据库还是做数学模型计算,都能很直观地拿到某一队的完整数据。

示例代码:

class TeamStats:
    def __init__(self, ball_possession=None, goal_attempts=None, 
                 shots_on_goal=None, shots_off_goal=None, blocked_shots=None,
                 free_kicks=None, corner_kicks=None, offsides=None, throw_ins=None,
                 goalkeeper_saves=None, fouls=None, red_cards=None, yellow_cards=None,
                 total_passes=None, completed_passes=None, tackles=None, attacks=None,
                 dangerous_attacks=None):
        self.ball_possession = ball_possession
        self.goal_attempts = goal_attempts
        self.shots_on_goal = shots_on_goal
        # 其他属性依次赋值...(可结合下面的dataclass进一步简化)

class Statistics:
    def __init__(self, match_id, home_stats=None, away_stats=None):
        self.match_id = match_id
        # 为空时自动初始化空的TeamStats,避免后续访问报错
        self.home_stats = home_stats or TeamStats()
        self.away_stats = away_stats or TeamStats()

之后访问属性就变成了stats.home_stats.ball_possession,比原来的长名字更规整,也不容易搞混主场客场的字段。

二、用数据类简化冗余代码

如果你用的是Python 3.7+,强烈推荐用dataclasses来替代手动写__init__方法,它能自动帮你生成属性赋值、__repr__、__eq__等通用方法,代码量能减少一大半,同时还保留类属性的清晰访问优势。

示例代码:

from dataclasses import dataclass

@dataclass
class TeamStats:
    ball_possession: float | None = None
    goal_attempts: int | None = None
    shots_on_goal: int | None = None
    shots_off_goal: int | None = None
    blocked_shots: int | None = None
    free_kicks: int | None = None
    corner_kicks: int | None = None
    offsides: int | None = None
    throw_ins: int | None = None
    goalkeeper_saves: int | None = None
    fouls: int | None = None
    red_cards: int | None = None
    yellow_cards: int | None = None
    total_passes: int | None = None
    completed_passes: int | None = None
    tackles: int | None = None
    attacks: int | None = None
    dangerous_attacks: int | None = None

@dataclass
class Statistics:
    match_id: int
    home_stats: TeamStats | None = None
    away_stats: TeamStats | None = None

这样写出来的代码简洁干净,还自带类型提示,IDE能自动补全属性名,不管是写数据库操作还是数学模型计算,都能减少拼写错误,调试也更方便。

三、如果不想改结构,优化初始化逻辑

要是你暂时不想调整类的结构,也可以通过循环来简化__init__里大量重复的赋值代码,避免手动写几十行self.xxx = xxx。

示例代码:

class Statistics:
    # 把所有单队的统计字段存成列表
    _TEAM_STAT_FIELDS = [
        'ball_possession', 'goal_attempts', 'shots_on_goal', 
        'shots_off_goal', 'blocked_shots', 'free_kicks', 
        'corner_kicks', 'offsides', 'throw_ins', 'goalkeeper_saves',
        'fouls', 'red_cards', 'yellow_cards', 'total_passes',
        'completed_passes', 'tackles', 'attacks', 'dangerous_attacks'
    ]

    def __init__(self, match_id, **kwargs):
        self.match_id = match_id
        # 循环处理主场属性
        for field in self._TEAM_STAT_FIELDS:
            setattr(self, f'home_{field}', kwargs.get(f'home_{field}'))
        # 循环处理客场属性
        for field in self._TEAM_STAT_FIELDS:
            setattr(self, f'away_{field}', kwargs.get(f'away_{field}'))

以后要是需要新增统计字段,只需要在_TEAM_STAT_FIELDS里加个名字就行,不用再重复写两遍赋值代码,维护起来省心很多。

最后聊聊你纠结的字典vs类的问题

字典虽然灵活,但类的优势在你的场景里太明显了:

  • 类型提示与代码补全:IDE能自动提示属性名,减少拼写错误,写代码效率更高;
  • 结构清晰:类的结构是固定的,能明确知道有哪些字段,不像字典可能出现键名混乱的情况;
  • 可扩展性:以后要加属性校验、自定义方法(比如计算主场客场的差值),类的方式比字典方便太多。

所以完全不用放弃类的优势,通过上面的优化方案就能解决属性过多的问题。

备注:内容来源于stack exchange,提问作者Kajander

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.21 08:19:35