Producing a sorted football league table in Python
<p>I have created a program which simulates an entire football season between teams. The user inputs the teams' names and their skill ratings. It then uses the Poisson distribution to compare their skill ratings and calculate the result between the two teams. After each match, the relevant lists are updated: the winning teams gains 3 points (so if it is the third team that has won then the value at index [2] increases by 3). I have a separate list for points, goals scored, goals conceded, games won, games drawn, and games lost (side note - is there a more efficient way of doing this?)
The problem I have comes at the end of the season: each team is outputted with their data in the order that the teams were originally input. This is done using the fact that a team's name in the 'names' list is the same index as their points in the 'points' list. So the issue is, if I order the 'points' list then they will be out of sync with their names. I hope this makes sense but here is an example output for a season:</p>

<pre><code>Enter number of teams in league: 4
Enter team 1 name: a
Enter team 2 name: b
Enter team 3 name: c
Enter team 4 name: d
Enter a skill: 1
Enter b skill: 3
Enter c skill: 5
Enter d skill: 8
===========================================
a's home games: 
===========================================

a 2 - 0 b 

a 0 - 2 c 

a 0 - 0 d 

===========================================
b's home games: 
===========================================

b 2 - 3 a 

b 1 - 0 c 

b 0 - 0 d 

===========================================
c's home games: 
===========================================

c 1 - 0 a 

c 1 - 0 b 

c 0 - 1 d 

===========================================
d's home games: 
===========================================

d 4 - 0 a 

d 2 - 0 b 

d 0 - 0 c 

Final table: 
a               Skill: 1     Points: 7     For: 5     Against: 9     Goal difference: -4    Wins: 2     Draws: 1     Losses: 3    
b               Skill: 3     Points: 4     For: 3     Against: 8     Goal difference: -5    Wins: 1     Draws: 1     Losses: 4    
c               Skill: 5     Points: 10    For: 4     Against: 2    Goal difference: 2     Wins: 3     Draws: 1     Losses: 2    
d               Skill: 8     Points: 12    For: 7     Against: 0    Goal difference: 7     Wins: 3     Draws: 3     Losses: 0    
[4, 7, 10, 12]
</code></pre>

<p>So what I would now like to do is to be able to print a final league table in descending points order, rather than the way it prints now just in index order.</p>

<p>Sorry if this is poorly worded - the code for my program might be more useful so here it is:</p>

<pre><code>import math
import random
#Lambda value in Poisson distribution for higher rated team
lambOne = 1.148698355
#Lambda value for lower rated team
lambTwo = 0.8705505633

#Poisson distribution calculating goals scored by the home team
def homeMatch(homeRating,awayRating):
    global lambOne
    global x
    global y
    if x == y:
        raise ValueError
    else:
        lamb = lambOne**(int(homeRating)-int(awayRating))
        homeScore = 0
        z = random.random()    
        while z &gt; 0:
            z = z - ((lamb**homeScore * math.exp(lamb * -1))/(math.factorial(homeScore)))
            homeScore += 1
        return (homeScore-1)

#Poisson distribution calculating goals scored by away team
def awayMatch(homeRating,awayRating):
    global lambTwo
    global x
    global y
    #This check is to stop a team playing itself
    if x == y:
        raise ValueError
    else:
        lamb = lambTwo**(int(homeRating)-int(awayRating))
        awayScore = 0
        z = random.random()    
        while z &gt; 0:
            z = z - ((lamb**awayScore * math.exp(lamb * -1))/(math.factorial(awayScore)))
            awayScore += 1
        return (awayScore-1)

#Selecting number of teams in league
leagueSize = int(input("Enter number of teams in league: "))

#Initialising empty lists
teamNames = []
teamSkill = []
teamPoints = []
teamFor = []
teamAgainst = []
teamWins = []
teamDraws = []
teamLosses = []

#Populating lists with number of zeroes equal to the number of teams (one zero for each)
for x in range(leagueSize):
    teamPoints += [0]
    teamFor += [0]
    teamAgainst += [0]
    teamWins += [0]
    teamDraws += [0]
    teamLosses += [0]

#Entering names and skill ratings for each team
for i in range(leagueSize):
    teamNames += [input("Enter team "+str(i+1)+" name: ")]
for j in range(leagueSize):
    teamSkill += [input("Enter "+teamNames[j]+" skill: ")]

#Initialising variables
homeScore = 0
awayScore = 0

#The season begins - each team plays all of its home games in one go
for x in range(leagueSize):
    #input("Press enter to continue ")
    print("===========================================")
    print(teamNames[x]+"'s home games: ")
    print("===========================================\n")
    for y in range(leagueSize):
        error = 0
        try:
            homeScore = homeMatch(teamSkill[x],teamSkill[y])
        #Skipping a game to stop a team playing itself
        except ValueError:
            pass
            error += 1
        try:
            awayScore = awayMatch(teamSkill[x],teamSkill[y])
        except ValueError:
            pass
        if error == 0:
            #Updating lists
            print(teamNames[x],homeScore,"-",awayScore,teamNames[y],"\n")
            teamFor[x] += homeScore
            teamFor[y] += awayScore
            teamAgainst[x] += awayScore
            teamAgainst[y] += homeScore
            if homeScore &gt; awayScore:
                teamWins[x] += 1
                teamLosses[y] += 1
                teamPoints[x] += 3
            elif homeScore == awayScore:
                teamDraws[x] += 1
                teamDraws[y] += 1
                teamPoints[x] += 1
                teamPoints[y] += 1
            else:
                teamWins[y] += 1
                teamLosses[x] += 1
                teamPoints[y] += 3
        else:
            pass

#Printing table (unsorted)
print("Final table: ")
for x in range(leagueSize):
    #Lots of formatting
    print(teamNames[x]+(15-len(teamNames[x]))*" "+" Skill: "+str(teamSkill[x])+(5-len(str(teamSkill[x])))*" "+" Points: "+str(teamPoints[x])+(5-len(str(teamPoints[x])))*" "+" For: "+str(teamFor[x])+(5-len(str(teamFor[x])))*" "+" Against: "+str(teamAgainst[x])+(5-len(str(teamPoints[x])))*" "+" Goal difference: "+str(teamFor[x]-teamAgainst[x])+(5-len(str(teamFor[x]-teamAgainst[x])))*" "+" Wins: "+str(teamWins[x])+(5-len(str(teamWins[x])))*" "+" Draws: "+str(teamDraws[x])+(5-len(str(teamDraws[x])))*" "+" Losses: "+str(teamLosses[x])+(5-len(str(teamLosses[x])))*" ")
teamPoints.sort()
print(teamPoints)
</code></pre>

<p>Sorry that this is very long and likely poorly worded and inefficient but I hope someone will be able to help me! Thank you very much :)</p>

<p>While your current approach is (barely) workable, it makes it very difficult to (for example) change the information you want to store about each team. You might consider defining a Team class instead, each instance of which stores all the information about a specific team.</p>

<pre><code>class Team:
    def __init__(self, name, skill):
        self.name = name
        self.skill = skill
        self.points = self.goals_for = self.goals_against = \
                     self.wins = self.draws = self.losses = 0
</code></pre>

<p>This lets you create a new team object by passing a name and a skill level, in this way:</p>

<pre><code>t1 = Team("Bradford City", 3)
</code></pre>

<p>t1 now has attributes <code>name</code> and <code>skill</code> with the given values, as well as a number of others (<code>points</code>, <code>goals_for</code>, and so on) whose values are all zero.</p>

<p>Then you can initialise the league quite easily:</p>

<pre><code>league_size = 4
teams = []
for _ in range(league_size):
    teams.append(Team(input("Name of team "+str(_)+": "),
                      int(input("Team "+str(_)+"'s skill level: ")))
</code></pre>

<p>Then to print the skill level of each team you can loop over the list:</p>

<pre><code>for team in teams:
    print(team.name, team.skill)
</code></pre>

<p>I hope this gives you some idea how your approach can be simplified. Your functions to play the matches can also take teams as arguments now, and modify the team objects directly according to the computed outcomes.</p>

<p>To get to the answer you want, once you have a list of teams you can print them out sorted by the number of points they hold quite easily:</p>

<pre><code>for team in sorted(teams, key=lambda t: t.points):
    print(team.name, team.skill, team.points, ...)
</code></pre>

<p>As far as I can see, none of your <code>global</code> declarations were necessary (if a name isn't defined locally Python will look for a global name to satisfy a reference). Besides which, inputs to a function should usually be passed as arguments, it's rather bad practice just to grab things from the environment!</p>

<p>I hope this is sufficient for you to rework your program to be more tractable. As a beginner I'd say you have done extremely well to get this far. The next steps are going to be exciting for you!</p>

<p><strong>Added later</strong>: Your all-play-all could be easier to program as a result:</p>

<pre><code>for home in teams:
    for away in teams:
        if home is away: # Teams don't play themselves
            continue
        play_match(home, away)
</code></pre>

<p>The <code>play_match</code> function would simulate the match and adjust each team's statistics. Of course you could simulate the away matches with another line reading</p>

<pre><code>         play_match(away, home)
</code></pre>

<p>though I'm not sure your algorithm is symmetrical for that.</p>

python list sorting