Reputation: 119
I´m writing a program where you can put in home team, away team, and the result of a game. I want to make the data of the teams to change according to this and most of it does. But I can´t make the "points", "goal difference" and "played"(games) to change! This is the code i wrote so far:
class team:
def __init__(self, name, wins, drawn, losses, goals_for, goals_against):
self.name = name
self.wins = int(wins)
self.drawn = int(drawn)
self.losses = int(losses)
self.goals_for = int(goals_for)
self.goals_against = int(goals_against)
self.goals_difference = (self.goals_for - self.goals_against)
self.points = ((self.wins * 3) + self.drawn)
self.played = (self.wins + self.drawn + self.losses)
def __repr__(self):
return 'Name:{} P:{} W:{} D:{} L:{} GF:{} GA:{} GD:{} PTS:{}'.format(self.name, self.played, self.wins, self.drawn, self.losses, self.goals_for, self.goals_against, self.goals_difference, self.points)
detroit_red_wings = team("Detroit", 1, 0, 3, 4, 5)
los_angeles_kings = team("LA", 0, 1, 4, 3, 7)
toronto_maple_leafs = team("Toronto", 1, 2, 2, 3, 6)
teamlist = [detroit_red_wings, los_angeles_kings, toronto_maple_leafs]
print(teamlist)
class data_input:
def home_team_input(self):
home_team = input("Type in the home team: ")
for i in teamlist:
if i.name == home_team:
return i
def away_team_input(self):
away_team = input("Type in the away team: ")
for t in teamlist:
if t.name == away_team:
return t
def result_input(self):
goals_home_team = int(input("Type in the number of goals made by the home team: "))
goals_away_team = int(input("Type in the number of goals made by the away team: "))
return (goals_home_team, goals_away_team)
def adding_result():
home_team = data_input.home_team_input()
away_team = data_input.away_team_input()
goals_home_team, goals_away_team = data_input.result_input()
home_team.goals_for += goals_home_team
home_team.goals_against += goals_away_team
away_team.goals_for += goals_away_team
away_team.goals_against += goals_home_team
if goals_home_team > goals_away_team:
home_team.wins += 1
away_team.losses += 1
if goals_home_team < goals_away_team:
away_team.wins += 1
home_team.losses += 1
if goals_home_team == goals_away_team:
home_team.drawn += 1
away_team.drawn += 1
data_input = data_input()
adding_result()
print(teamlist)
I wrote the directions for the attributes in the __init__
method of the class team
and as you can see the points depends on the wins
. This all works when i create the objects but when I put in the result of the new game the points
doesn't change(neither does the played
or goals_difference
). This surprises me because the other attributes changes when I type in result of the game in the input
function.
Upvotes: 1
Views: 60
Reputation: 29720
points
, goals_difference
, and played
don't update because your __init__
method isn't run once again once you update the other properties - you are simply updating the other properties explicitly with their new value. Note that these properties that aren't updating are assigned by value and not by reference, there is no way for your object to know that these properties should be updated unless you do so explicitly.
There are several things you could do - a simple option could be to provide a method to update the aggregating properties, that you can call after explicitly changing the other properties. I would take all of the properties that are simply a mathematical formulation of other properties (so points
, goals_difference
, and played
), and remove them from your initialization method. Instead call a little method like update_aggregates
if you really need these properties that could look like this
def update_aggregates(self):
self.goals_difference = (self.goals_for - self.goals_against)
self.points = ((self.wins * 3) + self.drawn)
self.played = (self.wins + self.drawn + self.losses)
Edit: ignoring my attempt at simplicity, the solution proposed by Steve Cohen is by all means better - using @property ensures your values will be updated appropriately at all times without the need for a manual call.
Upvotes: 0
Reputation: 712
If you update your team
class to make the calculated fields properties, then the property functions will always return the correct result. You will also get an error if you try to set those properties, as they are not settable, i.e., they are the result of a calculation on other set data.
class team:
def __init__(self, name, wins, drawn, losses, goals_for, goals_against):
self.name = name
self.wins = int(wins)
self.drawn = int(drawn)
self.losses = int(losses)
self.goals_for = int(goals_for)
self.goals_against = int(goals_against)
@property
def goals_difference(self):
return self.goals_for - self.goals_against
@property
def points(self):
return self.wins * 3 + self.drawn
@property
def played(self):
return self.wins + self.drawn + self.losses
def __repr__(self):
return 'Name:{} P:{} W:{} D:{} L:{} GF:{} GA:{} GD:{} PTS:{}'.format(
self.name, self.played, self.wins, self.drawn, self.losses,
self.goals_for, self.goals_against, self.goals_difference,
self.points)
I would also consider making the W/L/D and GF/GA initializers tupples or dictionaries rather than passing 5 variables to the initializer.
Upvotes: 3