diff --git a/skXCS/Classifier.py b/skXCS/Classifier.py
index 66cef152..a9965271 100644
--- a/skXCS/Classifier.py
+++ b/skXCS/Classifier.py
@@ -20,8 +20,6 @@ def __init__(self,xcs):
         self.initTimeStamp = xcs.iterationCount
         self.deletionProb = None
 
-        pass
-
     def initializeWithParentClassifier(self,classifier):
         self.specifiedAttList = copy.deepcopy(classifier.specifiedAttList)
         self.condition = copy.deepcopy(classifier.condition)
@@ -49,8 +47,6 @@ def match(self,state,xcs):
             else:
                 if instanceValue == self.condition[i]:
                     pass
-                elif instanceValue == None:
-                    return False
                 else:
                     return False
         return True
@@ -176,9 +172,7 @@ def uniformCrossover(self,classifier,xcs):
         p_cl_specifiedAttList = copy.deepcopy(classifier.specifiedAttList)
 
         # Make list of attribute references appearing in at least one of the parents.-----------------------------
-        comboAttList = []
-        for i in p_self_specifiedAttList:
-            comboAttList.append(i)
+        comboAttList = [i for i in p_self_specifiedAttList]
         for i in p_cl_specifiedAttList:
             if i not in comboAttList:
                 comboAttList.append(i)
@@ -235,12 +229,10 @@ def uniformCrossover(self,classifier,xcs):
                         if tempKey == 2:
                             self.condition[i_cl1] = [newMin, newMax]
                             classifier.condition.pop(i_cl2)
-
                             classifier.specifiedAttList.remove(attRef)
                         else:
                             classifier.condition[i_cl2] = [newMin, newMax]
                             self.condition.pop(i_cl1)
-
                             self.specifiedAttList.remove(attRef)
 
                 # Discrete Attribute
@@ -311,9 +303,8 @@ def mutateAction(self,xcs):
         return changed
 
     def getDelProp(self,meanFitness,xcs):
-        if self.fitness / self.numerosity >= xcs.delta * meanFitness or self.experience < xcs.theta_del:
+        if self.experience < xcs.theta_del or self.fitness / self.numerosity >= xcs.delta * meanFitness:
             deletionVote = self.actionSetSize * self.numerosity
-
         elif self.fitness == 0.0:
             deletionVote = self.actionSetSize * self.numerosity * meanFitness / (xcs.init_fit / self.numerosity)
         else:
diff --git a/skXCS/ClassifierSet.py b/skXCS/ClassifierSet.py
index 3bb6f5ec..2370044a 100644
--- a/skXCS/ClassifierSet.py
+++ b/skXCS/ClassifierSet.py
@@ -16,8 +16,7 @@ def createMatchSet(self,state,xcs):
         actionsNotCovered = copy.deepcopy(xcs.env.formatData.phenotypeList)
         totalNumActions = len(xcs.env.formatData.phenotypeList)
 
-        for i in range(len(self.popSet)):
-            classifier = self.popSet[i]
+        for i, classifier in enumerate(self.popSet):
             if classifier.match(state,xcs):
                 self.matchSet.append(i)
                 if classifier.action in actionsNotCovered:
@@ -35,7 +34,7 @@ def createMatchSet(self,state,xcs):
                 action = random.choice(copy.deepcopy(xcs.env.formatData.phenotypeList))
             coveredClassifier = Classifier(xcs)
             coveredClassifier.initializeWithMatchingStateAndGivenAction(1,state,action,xcs)
-            self.addClassifierToPopulation(xcs,coveredClassifier,True)
+            self.addClassifierToPopulation(coveredClassifier,True)
             self.matchSet.append(len(self.popSet)-1)
             if len(actionsNotCovered) != 0:
                 actionsNotCovered.remove(action)
@@ -47,16 +46,16 @@ def createMatchSet(self,state,xcs):
             self.popSet[ref].matchCount += 1
         xcs.timer.stopTimeMatching()
 
-    def getIdenticalClassifier(self,xcs,newClassifier):
+    def getIdenticalClassifier(self,newClassifier):
         for classifier in self.popSet:
             if newClassifier.equals(classifier):
                 return classifier
         return None
 
-    def addClassifierToPopulation(self,xcs,classifier,isCovering):
+    def addClassifierToPopulation(self,classifier,isCovering):
         oldCl = None
         if not isCovering:
-            oldCl = self.getIdenticalClassifier(xcs,classifier)
+            oldCl = self.getIdenticalClassifier(classifier)
         if oldCl != None:
             oldCl.updateNumerosity(1)
             self.microPopSize += 1
@@ -96,18 +95,14 @@ def updateFitnessSet(self,xcs):
         accuracySum = 0
         accuracies = []
 
-        i = 0
-        for clRef in self.actionSet:
+        for i, clRef in enumerate(self.actionSet):
             classifier = self.popSet[clRef]
             accuracies.append(classifier.getAccuracy(xcs))
             accuracySum = accuracySum + accuracies[i]*classifier.numerosity
-            i+=1
 
-        i = 0
-        for clRef in self.actionSet:
+        for i, clRef in enumerate(self.actionSet):
             classifier = self.popSet[clRef]
             classifier.updateFitness(accuracySum,accuracies[i],xcs)
-            i+=1
 
     ####Action Set Subsumption####
     def do_action_set_subsumption(self,xcs):
@@ -203,9 +198,9 @@ def insertDiscoveredClassifiers(self,child1,child2,parent1,parent2,xcs):
             xcs.timer.stopTimeSubsumption()
         else:
             if len(child1.specifiedAttList) > 0:
-                self.addClassifierToPopulation(xcs, child1, False)
+                self.addClassifierToPopulation(child1, False)
             if len(child2.specifiedAttList) > 0:
-                self.addClassifierToPopulation(xcs, child2, False)
+                self.addClassifierToPopulation(child2, False)
 
     def subsumeClassifier(self,child,parent1,parent2,xcs):
         if parent1.subsumes(child,xcs):
@@ -218,7 +213,7 @@ def subsumeClassifier(self,child,parent1,parent2,xcs):
             xcs.trackingObj.subsumptionCount += 1
         else: #No additional [A] subsumption w/ offspring rules
             if len(child.specifiedAttList) > 0:
-                self.addClassifierToPopulation(xcs, child, False)
+                self.addClassifierToPopulation(child, False)
 
     def getIterStampAverage(self): #Average GA Timestamp
         sumCl = 0
@@ -278,17 +273,15 @@ def deleteFromPopulation(self,xcs):
             vote = classifier.getDelProp(meanFitness,xcs)
             deletionProbSum += vote
             voteList.append(vote)
-        i = 0
-        for classifier in self.popSet:
+        for i, classifier in enumerate(self.popSet):
             classifier.deletionProb = voteList[i]/deletionProbSum
-            i+=1
 
         choicePoint = deletionProbSum * random.random()
         newSum = 0
-        for i in range(len(voteList)):
-            classifier = self.popSet[i]
-            newSum = newSum + voteList[i]
+        for i, vote in enumerate(voteList):
+            newSum += vote
             if newSum > choicePoint:
+                classifier = self.popSet[i]
                 classifier.updateNumerosity(-1)
                 self.microPopSize -= 1
                 if classifier.numerosity < 1:
@@ -300,10 +293,7 @@ def deleteFromPopulation(self,xcs):
         return
 
     def getFitnessSum(self):
-        sum = 0
-        for classifier in self.popSet:
-            sum += classifier.fitness
-        return sum
+        return sum(classifier.fitness for classifier in self.popSet)
 
     ####Clear Sets####
     def clearSets(self):
@@ -326,22 +316,17 @@ def getAveGenerality(self,xcs):
             aveGenerality = 0
         else:
             aveGenerality = generalitySum/self.microPopSize
-
         return aveGenerality
 
     def getAttributeSpecificityList(self,xcs): #To be changed for XCS
-        attributeSpecList = []
-        for i in range(xcs.env.formatData.numAttributes):
-            attributeSpecList.append(0)
+        attributeSpecList = [0] * xcs.env.formatData.numAttributes
         for cl in self.popSet:
             for ref in cl.specifiedAttList:
                 attributeSpecList[ref] += cl.numerosity
         return attributeSpecList
 
     def getAttributeAccuracyList(self,xcs): #To be changed for XCS
-        attributeAccList = []
-        for i in range(xcs.env.formatData.numAttributes):
-            attributeAccList.append(0.0)
+        attributeAccList = [0.0] * xcs.env.formatData.numAttributes
         for cl in self.popSet:
             for ref in cl.specifiedAttList:
                 attributeAccList[ref] += cl.numerosity * cl.getAccuracy(xcs)
diff --git a/skXCS/XCS.py b/skXCS/XCS.py
index f5f795f9..9673502d 100644
--- a/skXCS/XCS.py
+++ b/skXCS/XCS.py
@@ -21,7 +21,7 @@ def __init__(self,learning_iterations=10000,N=1000,p_general=0.5,beta=0.2,alpha=
                  random_state=None,prediction_error_reduction=0.25,fitness_reduction=0.1,reboot_filename=None):
 
             '''
-            :param learning_iterations:          Must be nonnegative integer. The number of explore or exploit learning iterations to run
+            :param learning_iterations:         Must be nonnegative integer. The number of explore or exploit learning iterations to run
             :param N:                           Must be nonnegative integer. Maximum micropopulation size
             :param p_general:                   Must be float from 0 - 1. Probability of generalizing an allele during covering
             :param beta:                        Must be float. Learning Rate for updating statistics
@@ -38,22 +38,22 @@ def __init__(self,learning_iterations=10000,N=1000,p_general=0.5,beta=0.2,alpha=
             :param init_fitness:                Must be float. The initial prediction value when generating a new classifier (e.g in covering)
             :param p_explore:                   Must be float from 0 - 1. Probability of doing an explore cycle instead of an exploit cycle
             :param theta_matching:              Must be nonnegative integer. Number of unique actions that must be represented in the match set (otherwise, covering)
-            :param do_GA_subsumption:             Must be boolean. Do subsumption in GA
-            :param do_action_set_subsumption:      Must be boolean. Do subsumption in [A]
-            :param max_payoff:                   Must be float. For single step problems, what the maximum reward for correctness
+            :param do_GA_subsumption:           Must be boolean. Do subsumption in GA
+            :param do_action_set_subsumption:   Must be boolean. Do subsumption in [A]
+            :param max_payoff:                  Must be float. For single step problems, what the maximum reward for correctness
             :param theta_sub:                   Must be nonnegative integer. The experience of a classifier required to be a subsumer
             :param theta_select:                Must be float from 0 - 1. The fraction of the action set to be included in tournament selection
-            :param discrete_attribute_limit:      Must be nonnegative integer OR "c" OR "d". Multipurpose param. If it is a nonnegative integer, discrete_attribute_limit determines the threshold that determines
+            :param discrete_attribute_limit:    Must be nonnegative integer OR "c" OR "d". Multipurpose param. If it is a nonnegative integer, discrete_attribute_limit determines the threshold that determines
                                                 if an attribute will be treated as a continuous or discrete attribute. For example, if discrete_attribute_limit == 10, if an attribute has more than 10 unique
                                                 values in the dataset, the attribute will be continuous. If the attribute has 10 or less unique values, it will be discrete. Alternatively,
                                                 discrete_attribute_limit can take the value of "c" or "d". See next param for this
-            :param specified_attributes:         Must be an ndarray type of nonnegative integer attributeIndices (zero indexed).
+            :param specified_attributes:        Must be an ndarray type of nonnegative integer attributeIndices (zero indexed).
                                                 If "c", attributes specified by index in this param will be continuous and the rest will be discrete. If "d", attributes specified by index in this
                                                 param will be discrete and the rest will be continuous.
-            :param random_state:                  Must be an integer or None. Set a constant random seed value to some integer (in order to obtain reproducible results). Put None if none (for pseudo-random algorithm runs)
-            :param prediction_error_reduction:    Must be float. The reduction of the prediction error when generating an offspring classifier
-            :param fitness_reduction:            Must be float. The reduction of the fitness when generating an offspring classifier
-            :param reboot_filename:    Must be String or None. Filename of model to be rebooted
+            :param random_state:                Must be an integer or None. Set a constant random seed value to some integer (in order to obtain reproducible results). Put None if none (for pseudo-random algorithm runs)
+            :param prediction_error_reduction:  Must be float. The reduction of the prediction error when generating an offspring classifier
+            :param fitness_reduction:           Must be float. The reduction of the fitness when generating an offspring classifier
+            :param reboot_filename:             Must be String or None. Filename of model to be rebooted
             '''
 
             #learning_iterations
@@ -261,7 +261,7 @@ def __init__(self,learning_iterations=10000,N=1000,p_general=0.5,beta=0.2,alpha=
 
     def checkIsInt(self, num):
         try:
-            n = float(num)
+            float(num)   # this unnecessary float cast improves performance!
             if num - int(num) == 0:
                 return True
             else:
@@ -271,7 +271,7 @@ def checkIsInt(self, num):
 
     def checkIsFloat(self,num):
         try:
-            n = float(num)
+            float(num)
             return True
         except:
             return False
@@ -357,23 +357,19 @@ def fit(self,X,y):
     def runIteration(self,state):
         self.trackingObj.resetAll()
         shouldExplore = random.random() < self.p_explore
+        self.population.createMatchSet(state,self)
+        predictionArray = PredictionArray(self.population,self)         
         if shouldExplore:
-            self.population.createMatchSet(state,self)
-            predictionArray = PredictionArray(self.population,self)
             actionWinner = predictionArray.randomActionWinner()
             self.population.createActionSet(actionWinner)
             reward = self.env.executeAction(actionWinner)
             self.population.updateActionSet(reward,self)
             self.population.runGA(state,self)
-            self.population.deletion(self)
         else:
-            self.population.createMatchSet(state, self)
-            predictionArray = PredictionArray(self.population, self)
             actionWinner = predictionArray.bestActionWinner()
             self.population.createActionSet(actionWinner)
             reward = self.env.executeAction(actionWinner)
             self.population.updateActionSet(reward, self)
-            self.population.deletion(self)
 
             if reward == self.max_payoff:
                 if len(self.trackedAccuracy) == self.movingAvgCount:
@@ -383,7 +379,7 @@ def runIteration(self,state):
                 if len(self.trackedAccuracy) == self.movingAvgCount:
                     del self.trackedAccuracy[0]
                 self.trackedAccuracy.append(0)
-
+        self.population.deletion(self)
         self.trackingObj.avgIterAge = self.iterationCount - self.population.getInitStampAverage()
         self.trackingObj.macroPopSize = len(self.population.popSet)
         self.trackingObj.microPopSize = self.population.microPopSize
@@ -659,16 +655,7 @@ def get_final_attribute_accuracy_list(self):
 class TempTrackingObj():
     #Tracks stats of every iteration (except accuracy, avg generality, and times)
     def __init__(self):
-        self.macroPopSize = 0
-        self.microPopSize = 0
-        self.matchSetSize = 0
-        self.correctSetSize = 0
-        self.avgIterAge = 0
-        self.subsumptionCount = 0
-        self.crossOverCount = 0
-        self.mutationCount = 0
-        self.coveringCount = 0
-        self.deletionCount = 0
+        self.resetAll()
 
     def resetAll(self):
         self.macroPopSize = 0