在类属性更改上调用Python方法

时间:2018-01-22 23:23:59

标签: python oop

我正在编写解析Twitter机器人的API,对OOP来说是一个新手。我有一些现有的Python代码依赖于全局变量,并认为我可以借此机会学习。

我有以下Team类,在解析API时会更新,并且在类属性更改时能够调用完全不相关的(外部)方法。

class Team(object):
  def __init__(self, team_name, tri_code, goals, shots, goalie_pulled):
    self.team_name = team_name
    self.tri_code = tri_code
    self.goals = goals
    self.shots = shots
    self.goalie_pulled = goalie_pulled

goalie_pulled的现有实例更改Team时,我希望调用以下方法(伪代码):

def goalie_pulled_tweet(team):
  tweet = "{} has pulled their goalie with {} remaining!".format(team.team_name, game.period_remain)
  send_tweet(tweet)

两件事 -

  1. 一旦检测到goalie_pulled_tweet属性发生了变化,如何从我的Team课程中拨打goalie_pulled
  2. 我可以从任何地方访问我的Game对象的实例,还是需要将其传递给该变量?

2 个答案:

答案 0 :(得分:2)

你应该看一下property课程。基本上,它允许您封装行为和私有成员,而消费者甚至不会注意到它。

在您的示例中,您可能拥有goalie_pulled属性:

class Team(object):
    def __init__(self, team_name, tri_code, goals, shots, goalie_pulled):
        # Notice the identation here. This is very important.
        self.team_name = team_name
        self.tri_code = tri_code
        self.goals = goals
        self.shots = shots

        # Prefix your field with an underscore, this is Python standard way for defining private members
        self._goalie_pulled = goalie_pulled

    @property
    def goalie_pulled(self):
        return self._goalie_pulled

    @goalie_pulled.setter
    def goalie_pulled(self, new_value):
        self._goalie_pulled = new_value
        goalie_pulled_tweet(self) #self is the current Team instance

从消费者的角度来看:

team = create_team_instance()

# goalie_pulled_tweet is called
team.goalie_pulled = 'some_value'

我建议你尽可能地使用属性,因为它们是一种很好的抽象方式。

答案 1 :(得分:1)

从设计的角度来看,拥有/方法会更有意义。

类是创建更有意义的抽象的工具。拉守门员是一种行动。如果你认为pull_goalie代表了一支真实的球队,那么说#34;球队拉出他们的守门员更有意义!"而不是"球队将他们的守门员属性设置为X球员!"

Team

我打算推荐一个房产,但我认为如果不考虑更广泛的设计清晰度,这将解决眼前的问题。

注意:没有&#34;私人&#34; Python中的属性。有一个约定,以单个下划线(class Team(object): ... def pull_goalie(self, player): self.pulled_goalie = player tweet = '<your format string>'.format( self.pulled_goalie, # Yes, your Team *could* store a reference to the current game. # It's hard to tell if that makes sense in your program without more context. self.game.period_remaining ) )开头的属性被视为是私有的,但这只是为了让使用您的代码的人知道他们可以&#39;总是依靠这个价值做他们认为会做的事情。 (即,它不是代码的公共合同的一部分,您可以在不发出警告的情况下进行更改。)

编辑:要在self._pulled_goalie对象上创建register_team方法,您可能会执行以下操作:

Game

请注意,通过使用字典,可以多次调用class Game(object): def __init__(<stuff>): ... self.teams = {} ... def register_team(self, team): if len(self.teams) > 1: raise ValueError( "Too many teams! Cannot register {} for {}" .format(team, game) ) self.teams[team] = team team.game = self def unregister_team(self, team): try: del self.teams[team] except KeyError: pass team.game = None register_team而不会产生不良影响。