I’m writing an API parsing Twitter bot and am very new to OOP. I have some existing Python code that relies on global variables and figured I could take this opportunity to learn.
I have the following Team class that gets updated when the API is parsed and is like to be able to call a totally unrelated (external) method when a class attribute changes.
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
When goalie_pulled
is changed for an existing instance of Team
I’d like the following method to be called (pseudo code):
def goalie_pulled_tweet(team):
tweet = "{} has pulled their goalie with {} remaining!".format(team.team_name, game.period_remain)
send_tweet(tweet)
Two things –
- How do I call
goalie_pulled_tweet
from within myTeam
class once I detect thatgoalie_pulled
attribute has changed? - Can I access an instance of my
Game
object from anywhere or does it need to be passed to that variable as well?
2
Answers
You should take a look at the property class. Basically, it lets you encapsulate behaviour and private members without the consumer even noticing it.
In your example, you may have a
goalie_pulled
property:From the consumer’s point of view:
I’d recommend you to use properties whenever you can (and must), as they are a nice way of abstraction.
From a design standpoint, it would make more sense to have a
pull_goalie
method.Classes are a tool to create more meaningful abstractions. Pulling a goalie is an action. If you think of
Team
as representing a real-life team, it makes more sense to say “The team pulled their goalie!” rather than “The team set their pulled-goalie attribute to X player!”I was going to recommend a property, but I think that would solve the immediate problem without considering broader design clarity.
NOTE: There is no such thing as a “private” attribute in Python. There is a convention that attributes beginning with a single underscore (
self._pulled_goalie
) is treated as private, but that’s just so that people using your code know that they can’t depend on that value always doing what they think it will. (i.e., it’s not part of the public contract of your code, and you can change it without warning.)EDIT: To create a
register_team
method on aGame
object, you might do something like this:Note that by using a dictionary,
register_team
andunregiser_team
can be called multiple times without ill effect.