The model in DEAP is to use functions for crossover, mutation, and evaluation, not class methods. An individual is not responsible for mating or mutating itself. But, your mutation, crossover, and evaluation functions can rely on specific attributes to perform their task. This would result in something like
# Container module: utils.py
Class MyContainer(object):
# This class does not require the fitness attribute
# it will be added later by the creator
def __init__(self, attributes):
# Some initialisation with received values
self.attr1 = attributes[0]
def initIndividual(ind_class, size):
# ind_class will receive a class inheriting from MyContainer
ind = ind_class(random.random() for _ in range(size))
return ind
def mutation(individual):
individual.attr1 += 42
return (individual,)
# ...
# Execution module: main.py
import utils
creator.create("FitnessMin", base.Fitness, weights=(-1.0, -1.0))
creator.create("Individual", utils.MyContainer, fitness=creator.Fitness)
toolbox = base.Toolbox()
toolbox.register("individual", utils.initIndividual, creator.Individual, size=8)
toolbox.register("mutate", utils.mutation)
test_ind = toolbox.individual()
issubclass(type(test_ind), utils.MyContainer)
test_ind.fitness.values = 4, 5
toolbox.mutate(test_ind)
#...
With this intialization the creator is still responsible to add a fitness to your individuals (so it can be switched easily in the main module) and your container can be anything with your crossover, mutation, and evaluation functions applying on it.
Using a similar initialisation you can fill your individual with precomputed data instead of relying on a random number generator.
I hope this is useful,
Have fun with DEAP,
François-Michel