Python has an official style-guide, PEP8. It recommends using PascalCase
for classes, so your class should be called Candidate
. It also recommends using spaces after a ,
when passing multiple arguments to a function.
The creation of the candidates is as simple as this:
candidate_list = [Candidate() for _ in range(20000)]
Note that the starting index of range
is 0
by default and that I used the customary variable name _
for the unused loop variable.
This also removes having to clear
the candidates list, since it is being created anew every time you call the select
function.
To get the candidate with the largest score, just use:
best_candidate = max(candidate_list, key=lambda c: c.total_score)
This does not allow you to easily remove them from the list of candidates, though. For this you can use enumerate
:
index, candidate = max(enumerate(candidate_list), key=lambda t: t[1].total_score)
However, since you are running a not quite small numerical simulation, you might want to look into using numpy
, which would greatly speed up the calculations. Instead of having a Candidate
class, just create arrays. Generating random numbers in bulk is vastly faster than doing it one at a time as well:
import numpy as np
iterations = 100
candidates = 20000
top_ten_luck = []
for _ in range(iterations):
scores = np.random.randint(0, 99, size=(candidates, 3))
luck = np.random.randint(0, 100, size=candidates)
total_score = 0.95 * scores.mean(axis=1) + 0.05 * luck
top_ten = np.argpartition(-total_score, 10)[:10]
top_ten_luck.extend(luck[top_ten])
print(np.mean(top_ten))
This runs in less than a second (132ms on my machine, to be exact). The for
loop can also be vectorized, but at that point you might run into memory constraints.
Note that I used numpy.argpartition
to get the indicies of the top ten candidates, in order to only partially sort the data as much as needed and not further. We need to use -total_score
because it only gives you minimal values. This should be both faster than pop
ing the maximum value ten times as well as completely sorting the list.