为了账号安全,请及时绑定邮箱和手机立即绑定

如何从父实例调用子类中的方法?

如何从父实例调用子类中的方法?

神不在的星期二 2022-08-25 15:33:33
如何在 中创建的实例并调用方法?如下图所示:StatsGameStatsclass Stats():    """Object to instansiate a league and season pair     Args:        league(str): league_id        season(str): season_id    """    fb = Football()    dir = Directory()    def __init__(self, league='EN_PR', season='2019/2020'):        self.pool = multiprocessing.cpu_count()        self.league = league        self.season = season    def load_season_fixture(self):        """Loads the fixtures for a league-season,        calls api_scraper.py methods        """        self.fb.load_leagues()        self.fb.leagues[self.league].load_seasons()        return self.fb.leagues[self.league].seasons[self.season].load_played_fixtures()    def load_season_players(self):        """Loads the players for a league-season,        calls api_scraper.py methods        """        player_id = []        self.fb.load_leagues()        self.fb.leagues[self.league].load_seasons()        teams = self.fb.leagues[self.league].seasons[self.season].load_teams()        for team in tqdm(teams.values()):            players = self.fb.leagues[self.league].seasons['2019/2020'].teams[team['shortName']].load_players()        for player in players.keys():            player_id.append(player)        return player_id    def load_season_teams(self):        """Loads the teams for a league-season,        calls api_scraper.py methods        """        player_id = []        self.fb.load_leagues()        self.fb.leagues[self.league].load_seasons()        return self.fb.leagues[self.league].seasons[self.season].load_teams()class GameStats(Stats):    def __init__(self, *args, **kwargs):        super().__init__()        self.fixture_id = [fix['id'] for fix in self.load_season_fixture().values()]
查看完整描述

3 回答

?
慕莱坞森

TA贡献1810条经验 获得超4个赞

“简单胜于复杂”和“实用性胜过纯度”-- PEP 20

#What I want to do

d.Stats()

d.team_standings()

d.player_stats()

d.fixture_stats()

你的例子都是在一个赛季的背景下。因此,我只需将其作为一个包含您要使用的所有方法的类即可。这也清楚地表明,这些方法仅限于该单一季节。SeasonStats


class SeasonStats:

    ...

    def __init__(self, league='EN_PR', season='2019/2020'):

        ...


        ### Included from '__init__'s of previous subclasses ###

        self.fixture_ids = [fix['id'] for fix in self.load_season_fixture().values()]

        self.team_ids = [team['id'] for team in self.load_season_teams().values()]

        self.player_ids = self.load_season_players()


    def load_season_fixture(self):

        ...

    def load_season_players(self):

        ...

    def load_season_teams(self):

        ...

    def fixture_stats_singel(self, fixture):

        ...

    def fixture_stats(self):

        ...

    def player_stats_singel(self, player):

        ...

    def player_stats(self):

        ...

    def team_standings_singel(self, team_id):

        ...

    def team_standings(self):

        ...

请注意,我已经巧妙地更改了从以前的子类中包含的变量名称__init__


然后确实只是将其用作:


season_19_20 = SeasonStats(season='2019/2020')

season_19_20.team_standings()

season_19_20.player_stats()

season_19_20.fixture_stats()

一些变量命名建议

d, ,ef

我建议不要使用 、 、 等...内存很便宜,屏幕足够大:不要害怕使用有意义的名称,例如.abcseason


列表是复数

在谈论ID列表时,您自然已经使用了复数“ID”。通过这样命名变量,您可以轻松区分事物列表和单个事物。这也使得在例如 -loop 中使用非常自然:for


team_ids = [team['id'] for team in ...]

for team_id in team_ids:

    do_something_with(team_id)


查看完整回答
反对 回复 2022-08-25
?
当年话下

TA贡献1890条经验 获得超9个赞

从评论中获得更多上下文:

所以。。。你不想有一个子对象,你只是想在原来的类中有更多的方法吗?但是,如果不将这些方法放在原始类中呢?

@h4ze听起来没错!我想要碎片化

如果显式指定类名,则可以将任何内容作为 传递。self

d = Stats()
GameStats.fixture_stats(d)

它被称为鸭子打字 - 我们不关心物体的实际类型,我们关心它的作用:“如果它像鸭子一样游泳,像鸭子一样嘎嘎叫,它就是鸭子”。

这允许您将任何对象传递到任何地方...但这也意味着物体需要像最初期望的物体一样“游泳”和“庸医”,对吧?

我们知道所有对象都是对象(因为继承),但不是相反。- 这意味着你的方法只能使用有的东西。GameStatsStatsGameStatsStats


但是,仅仅因为你可以做某事并不意味着你应该这样做。你不能利用你的孩子类的潜力 - 你基本上只是使用类作为不同类的方法的存储!


更好的主意是以另一种方式进行 - 使用多重继承。每个父类都将具有执行其操作所需的内容(当然,您将在子 init 中设置所有这些部分)和这些操作 - 从而最大限度地减少在子类中覆盖方法的需求。

把它想象成其他语言的接口,但是已经实现的方法(通常你必须实现接口 - 导致类中有更多的东西)。


或者只是做普通的函数,记录(在文档字符串中)他们应该接受给定的对象,并使用它。您可以将这些函数存储在不同的模块中,从而为它们提供不同的命名空间 - 提供所需的“碎片”。


查看完整回答
反对 回复 2022-08-25
?
临摹微笑

TA贡献1982条经验 获得超2个赞

这是一个糟糕的设计。所以我的答案是你不应该那样做。


这很危险,因为来自子类的方法需要一个可能具有其他属性的子类对象。在基类对象上调用这些方法可能会中断。在您的示例中,只有真正的对象才会初始化GameStatsfixture_id


好吧,如果你仔细地写,它会起作用,但它需要用红色闪烁的字体注释,以防止未来的维护者不要破坏它,因为你愿意滥用类层次结构。


如果要构建基类对象,并且以后使用子类中的方法,则可以使用可接受的设计:


确保所有子类都可以从基类对象初始化,然后执行以下操作:


d = Stats()

# additional Stats operation on d...

(GameStats(d)).fixture_stats()

使用将从其他混炼中加载方法(手动等效于上述设计)__getattr__


class Base:

    def set_mixin(self, mixin):

        self.mixin = mixin

    def __getattr__(self, attr):

        return functools.partial(getattr(self.mixin, attr), self)


class M1:

    """Mixin for class Base: only contains methods that apply on Base objects"""

    def __init__(self, *args, **kwargs):

        raise TypeError("Cannot create M1 objects")

    def foo(self, x):

        print(x, 'on', self)


b = Base()

b.set_mixin(M1)

b.foo('x')

会打印


x on <__main__.Base object at 0x...>

但恕我直言,这是一个有问题的设计,应该只用于特殊用例。


查看完整回答
反对 回复 2022-08-25
  • 3 回答
  • 0 关注
  • 89 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信