"MathChallenge" game for sums with 4 operators I am trying to start learning Python using Learn Python the Hard Way. I wrote my first game that works as far as tested. It was done as an exercise for this.

Please give me some constructive criticism on this program on sections and areas where I can improve. I realise that my object-oriented programming specifically, and my programming in general, still needs lots of work:

"""
MathChallenge:
A game randomly creating and testing math sums with 4 operators: addition, subtraction, multiplication and division.
Difficulty levels are incremented after each correct answer.
No more than 3 incorrect answers are accepted.
"""

from random import randint, choice

class Math(object):
    """Class to generate different math sums based on operator and difficulty levels"""

    def __init__(self):
        """To initialise difficulty on each run"""
        self.difficulty = 1

    def addition(self, a, b):
        """To return 'addition', '+' sign , and answer of operation"""
        return ('addition', '+', a+b)

    def subtraction(self, a, b): 
        """To return 'subtraction', '-' sign , and answer of operation"""
        return ('subtraction', '-', a-b)

    def multiplication(self, a, b): 
        """To return 'multiplication', '*' sign , and answer of operation"""
        return ('multiplication', '*', a*b)

    def division(self, a, b):
        """To return 'division', '/' sign , and answer of operation""" 
        return ('division', '/', a/b)

    def mathsum(self, difficulty):
        """Function that generates random operator and math sum checks against your answer"""

        print "Difficulty level %d." % difficulty

        #let's initialize some random digits for the sum
        a = randint(1,5)*difficulty
        b = randint(1,5)*difficulty

        #Now let's choose a random operator
        op = choice(self.operator)(a, b)

        print "Now lets do a %s calculation and see how clever you are." % op[0]
        print "So what is %d %s %d?" % (a, op[1], b)

        correct = False
        incorrect_count = 0                         #No more than 3 incorrect answers
        while not correct and incorrect_count&lt;3:
            ans = int(raw_input("&gt;"))

            if ans == op[2]: 
                correct = True
                print "Correct!"
                self.difficulty += 1
                self.mathsum(self.difficulty)       #Restart the function with higher difficulty

            else:
                incorrect_count += 1
                if incorrect_count == 3: print "That's 3 incorrect answers.  The end."
                else: print "That's not right.  Try again."



class Engine(Math):
    """Game engine"""

    def __init__(self):
        """To initialise certain variables and function-lists"""

        #Initialise list of math functions inherited to randomly call from list        
        self.operator = [
            self.addition,
            self.subtraction,
            self.multiplication,
            self.division
            ]

        #Initialise difficulty level
        self.difficulty = 1

        print "Welcome to the MathChallenge game. I hope you enjoy!"

    def play(self):
        """To start game"""

        #start game
        self.mathsum(self.difficulty)

        #print returned difficulty level achieved
        print "Difficulty level achieved: ", self.difficulty


# Start game            
game = Engine()
game.play()
Some notes:


You took a OOP approach. I won't say that's wrong (maybe it was even encouraged by that guide), but when learning a language like Python, where OOP is not compulsory, I'd say it preferable to take a non-OOP approach first.
return ('addition', '+', a+b). Those 4 operations are pretty uniform, why don't you use a data structure instead? (a list, a dictionary). Use module operator.
You code is for version 2.x. Unless you have some good reason, it's better to use Python 3.x, you won't lose a second re-learning things later on.
op[0], op[1], op[2]. If I had to highlight one single aspect of good programming practices, this would be: be declarative! If your code does not look as if you are writing pseudocode (specially if you are using a high-level language), then you're doing something wrong. What's op[1]? No idea, we'd have to look at the function. So destructure the result giving meaningful names to the variables: op_name, op_symbol, op_function = choice(self.operator)(a, b).
I'd take a more functional approach, try to organize code so there are as few in-place updates of variables as possible (not always feasible or idiomatic in an imperative language like Python).


I'd write:

import operator
import random

operations = {
    "addition": ("+", operator.add),
    "substraction": ("-", operator.sub),
    "multiplication": ("*", operator.mul),
    "division": ("/", operator.floordiv),
}

def ask_operation(difficulty, maxtries=3):
    maxvalue = 5 * difficulty
    x = random.randint(1, maxvalue)
    y = random.randint(1, maxvalue)
    op_name, (op_symbol, op_fun) = random.choice(list(operations.items()))
    result = op_fun(x, y)

    print("Difficulty level %d" % difficulty)
    print("Now lets do a %s calculation and see how clever you are." % op_name)
    print("So what is %d %s %d?" % (x, op_symbol, y))

    for ntry in range(1, 1+maxtries):
        answer = int(input("&gt;"))
        if answer == result:
            print("Correct!")
            return True
        elif ntry == maxtries:
            print("That's %s incorrect answers.  The end." % maxtries)
        else:
            print("That's not right.  Try again.")
    return False

def play(difficulty):
    while ask_operation(difficulty):
        difficulty += 1
    print("Difficulty level achieved: %d" % difficulty)

play(1)