# How to Create a Simple Simulation in Python – Numeric Data

See Python: Tips and Tricks for similar articles.

In this article, I show how to create a simple `Simulation` class in Python. The purpose of the class is to run a simulation many times and then return stats (e.g., mean, median, etc.) on the results of the simulation.

Let’s start with a simple `Die` class that has a `roll()` method that returns an integer between 1 and 6 (inclusive):

``````import random

class Die:
def __init__(self, sides=6):
self.sides = sides

def roll(self):
return random.randint(1, self.sides)
``````

We want our `Simulation` class to take two arguments: a function to run and the number of times to run it (`n`) and then to run the function `n` times and return a report like this:

```Number of Simulations: 1,000
Max: 6
Min: 1
Mean: 3.522
Median: 4.0
Mode: 4
Standard Deviation: 1.7018849586304041
Variance: 2.8964124124124124```

Here is the `Simulation` class that does just this:

``````import statistics as stats

class SimulationNumeric:
"""Runs a function that returns a number n times and prints stats

Args:
fnct_to_run (function): The function to run
iterations (integer): The number of times to run it"""

def __init__(self, fnct_to_run, iterations):
self._fnct_to_run = fnct_to_run
self._iterations = iterations
self._results = []
self.run()

@property
def mode(self):
try:
return stats.mode(self._results)
except:
return None

def run(self):
for i in range(self._iterations):
result = self._fnct_to_run()
self._results.append(result)

self.report()

def report(self):
max_num = max(self._results)
min_num = min(self._results)
mean = stats.mean(self._results)
median = stats.median(self._results)
mode = self.mode
std_dev = stats.stdev(self._results)
variance = stats.variance(self._results)
print(
f"""Number of Simulations: {self._iterations:,}
Max: {max_num}
Min: {min_num}
Mean: {mean}
Median: {median}
Mode: {mode}
Standard Deviation: {std_dev}
Variance: {variance}"""
)

die = Die()
sim = SimulationNumeric(die.roll, 1000)
``````

This class should work fine with an function that returns a number.

Note that the reason `mode` is written as a property is that not all result sets will have a mode. If, for example, two numbers are rolled the same number of times and both those numbers are rolled more often than any other number, then there will be no mode. In that case, `stats.mode(self._results)` will error. Our code catches that error and returns `None` for mode in that case.