Module #11

In this module you will learn to create a class based off of another class through inheritance.


Inheritance

Imagine that you have a class, Sprite, that represents a generic object in game. It may have properties like it's x and y position on screen, and it may have methods to move it to another position or two draw it on to the screen. Now, what if you want a specific object in the game, like a player. A player may have properties like name and score, but it would also share many properties and methods with an instance of Sprite. It wouldn't make sense to reimplement all of the methods that Sprite has in Player since they've already been created. Wouldn't it be easier to just use the ones already defined in Sprite?

This can be done with a language feature called inheritance. Inheritance allows one class to be based off of another class.

  • the parent or base class is the class whose properties and methods are being inherited from
  • the child or subclass is the new class that is reusing the properties and methods from the base class

Extending an Existing Class

The term extends describes the situation where one class inherits from another class. The child class extends the parent class. When extending a class...

  • instances of the subclass have access to the methods of the parten class
  • shared properties can be set via the __init__ method
  • if any properties or methods of the parent class need to be changed or customized by the child class, the child class can override those methods or properties...
  • overriding a method / property is done be redefining the method / property in the child class

The syntax for inheritance is as follows:

  1. after the class definition class SomeClassName
  2. follow with parentheses and the class being extended
  3. for example, class Player(Sprite):

Below is an example of one class extending another. As you can see, methods in the base class, Ghost, can be called from instances of the sub class, FriendlyGhost even though they're not directly defined in FriendlyGhotst.

Sample Program: FriendlyGhost does not have a make_noise method explicitly defined, yet it can be called on an instance of FriendlyGhost because it FriendlyGhost inherits make_noise from the parent class, Ghost.



Overriding Methods

It sometimes useful to change the behavior of an inherited method.

  • changing the behavior of an inherited method is called overriding a method
  • this can be done by create a method of the same name of the inherited method within the child class
  • every instance of the child class will now call the child class implementation of the overridden method

Sample Program: FriendlyGhost overrides the make_noise method so that it prints out hi there! instead of boo!



Calling Super

Finally, it may be helpful to call methods from the super class.

  • this is possible by calling the built-in super() method
  • this gives back a proxy object allowing the invocation of methods from the parent class
  • for example, to call the parent class __init__ method, use: super().__init__()

⚠️ this method of calling super class methods works with "single" inheritance

You can see a full example of inheritance, overriding methods, and calling super in the video below.


Automated Testing

Python offers a module that helps create tests for checking your code. The process of testing individual functions in your code is called unit testing.

The module for helping with creating unit tests is called (not surprisingly!) unittest. The unittest framework can be used to:

  • create a class representing a suite of tests
  • with each method of the class being a specific test case

Using unitteset

To test a function that you've created in a separate module:

  1. import the unittest module: import unittest
  2. bring in the module that contains the function you're testing: import mymodule
  3. create a class that extends unittest.TestCase: class TestMyModule(unittest.TestCase)
  4. for every case that you'd like test, you must write a method prefixed with test: def test_some_case(self)
  5. each of these methods must call an assertion method on the instance of the class:
    • see a list of these methods here
    • for example: self.assertEquals(observed, expected)
    • ... where observed may be calling the original function itself, and expected being the expected return value
    • self.assertEquals(mymodule.function(some_arg), some_expected_value)
  6. if the assertion within the method fails, then the test fails
  7. if the assertion within the method passes, then the teset passes
  8. finally, to run the tests, you can use unittest.main()

unittest Output

The output of the test starts with as series of characters composed of F and ., where every F signifies a test failure, and . signififes a passing test:

...FF.

The output above shows that two out of 6 tests fail.

After that, details of each failing test will be printed out.

Examples

Here's what an example function to be tested and accompanying test code may look like:

In mymodule.py:

def increment(n):
    return n + 1

In test_mymodule.py:

import unittest
from mymodule import increment

class TestIncrement(unittest.TestCase):
    def test_adds_one(self):
        self.assertEquals(increment(2), 3)

if __name__ == '__main__':
    unittest.main()

Finally, here's an example of test driven development where tests are written first prior to the actual implementation of the module / function.


Quiz

Now that you've completed this module, please visit our NYU Classes site and take the corresponding quiz for this module. These quizzes are worth 5% of your total grade and are a great way to test your Python skills! You may also use the following scratch space to test out any code you want.

Feedback

Tell us what you thought about this module (it's anonymous).
How helpful did you find this module on a scale of 1-5:
Very unhappy face
Unhappy face
Neutral face
Happy face
Very happy face
Which resource(s) in this module did you find the most helpful (check all that apply):

Copyright 2014-2018