Skip to content

Instantly share code, notes, and snippets.

@rebeccabilbro
Last active February 6, 2016 18:44
Show Gist options
  • Save rebeccabilbro/3275b4091c8c7c382afe to your computer and use it in GitHub Desktop.
Save rebeccabilbro/3275b4091c8c7c382afe to your computer and use it in GitHub Desktop.
A quick introduction to object-oriented programming in Python, including building modules and packages.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Object-Oriented Python\n",
"\n",
"Object-oriented programming (OOP) is a way of writing programs that represent real-world problem spaces (in terms of objects, functions, classes, attributes, methods, and inheritance). As Allen Downey explains in [__Think Python__](http://www.greenteapress.com/thinkpython/html/thinkpython018.html), in object-oriented programming, we shift away from framing the *function* as the active agent and toward seeing the *object* as the active agent.\n",
"\n",
"In this workshop, we are going to create a class that represents the rational numbers. This tutorial is adapted from content in Anand Chitipothu's [__Python Practice Book__](http://anandology.com/python-practice-book/index.html).\n",
"\n",
"## Part 1: Classes, methods, modules, and packages.\n",
"\n",
"#### Pair Programming: Partner up with the person sitting next to you\n",
"\n",
"Copy the code below into a file called RatNum.py in your code editor or [clone it from here](https://github.com/rebeccabilbro/Tutorials/blob/master/OOP/OOP_Workshop.ipynb). \n",
"\n",
"It may help to review [built-ins in Python](https://docs.python.org/2/library/functions.html) and the [Python data model](https://docs.python.org/2/reference/datamodel.html)."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The first number is 1/2\n",
"The second number is 3/2\n",
"Their sum is 8/4\n",
"Their product is None\n",
"Their difference is None\n",
"Their quotient is None\n"
]
}
],
"source": [
"class RationalNumber:\n",
" \"\"\"Any number that can be expressed as the quotient or fraction p/q \n",
" of two integers, p and q, with the denominator q not equal to zero. \n",
" \n",
" Since q may be equal to 1, every integer is a rational number.\n",
" \"\"\"\n",
" \n",
" def __init__(self, numerator, denominator=1):\n",
" self.n = numerator\n",
" self.d = denominator\n",
"\n",
" def __add__(self, other):\n",
" # Write a function that allows for the addition of two rational numbers.\n",
" # I did this one for you :D\n",
" if not isinstance(other, RationalNumber):\n",
" other = RationalNumber(other)\n",
"\n",
" n = self.n * other.d + self.d * other.n\n",
" d = self.d * other.d\n",
" return RationalNumber(n, d)\n",
" \n",
" def __sub__(self, other):\n",
" # Write a function that allows for the subtraction of two rational numbers.\n",
" pass\n",
"\n",
" \n",
" \n",
" def __mul__(self, other):\n",
" # Write a function that allows for the multiplication of two rational numbers.\n",
" pass\n",
"\n",
" \n",
" \n",
" def __div__(self, other):\n",
" # Write a function that allows for the division of two rational numbers.\n",
" pass\n",
"\n",
" \n",
" def __str__(self):\n",
" return \"%s/%s\" % (self.n, self.d)\n",
"\n",
" __repr__ = __str__\n",
" \n",
" \n",
" \n",
"if __name__ == \"__main__\":\n",
" x = RationalNumber(1,2)\n",
" y = RationalNumber(3,2)\n",
" print \"The first number is %s\" %x\n",
" print \"The second number is %s\" %y\n",
" print \"Their sum is %s\" %(x+y)\n",
" print \"Their product is %s\" %(x*y)\n",
" print \"Their difference is %s\" %(x-y)\n",
" print \"Their quotient is %s\" %(x/y)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Once you've saved the code as a python file, you should be able to run it on your terminal like this:\n",
"\n",
" python RatNum.py\n",
" \n",
"You should get a print-out that looks something like\n",
"\n",
" The first number is 1/2\n",
" The second number is 3/2\n",
" Their sum is 8/4\n",
" Their product is None\n",
" Their difference is None\n",
" Their quotient is None\n",
" \n",
"As you fill in the methods for subtraction, multiplication, and division in RatNum.py, you can check how well they are working by running:\n",
"\n",
" python RatNum.py\n",
"\n",
"in your terminal again."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"(hint) \n",
"\n",
"|Operation |Method |\n",
"|---------------|----------------------------|\n",
"|Addition |(a/b) + (c/d) = (ad + bc)/bd|\n",
"|Subtraction |(a/b) - (c/d) = (ad - bc)/bd|\n",
"|Multiplication |(a/b) x (c/d) = ac/bd |\n",
"|Division |(a/b) / (c/d) = ad/bc |"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now that you've finished writing the methods that capture the behavior of the rational numbers, let's turn your script into a **module**.\n",
"\n",
"\n",
"## What is a Module? \n",
"\n",
"Modules are reusable libraries of code. Many libraries come standard with Python. You can import them into a program using the *import* statement. For example:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The first few digits of pi are 3.141593...\n"
]
}
],
"source": [
"import math\n",
"print \"The first few digits of pi are %f...\" %math.pi"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The math module implements many functions for complex mathematical operations using floating point values, including logarithms, trigonometric operations, and irrational numbers like π. \n",
"\n",
"#### As an exercise, we'll encapsulate your rational numbers script into a module and then import it.\n",
"Save the RatNum.py file you've been working in. Open your terminal and navigate whereever you have the file saved. \n",
"\n",
"Type: \n",
"\n",
" python \n",
"\n",
"When you're inside the Python interpreter, enter:\n",
"\n",
" from RatNum import RationalNumber\n",
" a = RationalNumber(1,3)\n",
" b = RationalNumber(2,3)\n",
" print a*b\n",
"\n",
"Success! You have just made a module.\n",
"\n",
"Now let's turn your module into a **package**. \n",
"\n",
"## What is a package?\n",
"\n",
"A package is a directory of modules. For example, we could make a big package by bundling together modules with classes for natural numbers, integers, irrational numbers, and real numbers. \n",
"\n",
"The Python Package Index, or \"PyPI\", is the official third-party software repository for the Python programming language. It is a comprehensive catalog of all open source Python packages and is maintained by the Python Software Foundation. You can download packages from PyPI with the *pip* command in your terminal.\n",
"\n",
"PyPI packages are uploaded by individual package maintainers. That means you can write and contribute your own Python packages!\n",
"\n",
"#### Now let's turn your module into a package called Mathy.\n",
"\n",
"1. Create a folder called Mathy, and add your RatNum.py file to the folder.\n",
"2. Add an empty file to the folder called \\_\\_init\\_\\_.py.\n",
"3. Create a third file in that folder called MathQuiz.py that imports RationalNumber from RatNum... \n",
"4. ...and uses the RationalNumbers class from RatNum. For example: "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" #MathQuiz.py\n",
" \n",
" from RatNum import RationalNumber\n",
"\n",
" print \"Pop quiz! Find the sum, product, difference, and quotient for the following rational numbers:\"\n",
" \n",
" a = RationalNumber(1,3)\n",
" b = RationalNumber(2,3)\n",
"\n",
" print \"The first number is: %s\" %a\n",
" print \"The second number is: %s\" %b\n",
" print \"The sum is: %s\" %(a+b)\n",
" print \"The product is: %s\" %(a*b)\n",
" print \"The difference is: %s\" %(a-b)\n",
" print \"The quotient is: %s\" %(a/b) "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### In the terminal, navigate to the Mathy folder. When you are inside the folder, type:\n",
"\n",
" python MathQuiz.py\n",
"\n",
"Congrats! You have just made a Python package! \n",
"\n",
"#### Now type: \n",
"\n",
" python RatNum.py \n",
" \n",
"What did you get this time? Is it different from the answer you got for the previous command? Why??\n",
"\n",
"Once you've completed this exercise, move on to Part 2.\n",
"\n",
"## Part 2: Inheritance \n",
"\n",
"Suppose we were to write out another class for another set of numbers, say the integers. What are the rules for addition, subtraction, multiplication, and division? If we can identify shared properties between integers and rational numbers, we could use that information to write a integer class that 'inherits' properties from our rational number class.\n",
"\n",
"#### Let's add an integer class to our RatNum.py file that inherits all the properties of our RationalNumber class."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"class Integer(RationalNumber):\n",
" #What should we add here?\n",
" pass"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Now update your \\_\\_name\\_\\_ == \"\\_\\_main\\_\\_\" statement at the end of RatNum.py to read:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"5/1 is an integer expressed as a rational number\n",
"So is 6/1\n",
"When you add them you get 11/1\n",
"When you multiply them you get None\n",
"When you subtract them you get None\n",
"When you divide them you get None\n"
]
}
],
"source": [
"if __name__ == \"__main__\":\n",
" q = Integer(5)\n",
" r = Integer(6)\n",
" print \"%s is an integer expressed as a rational number\" %q\n",
" print \"So is %s\" %r\n",
" print \"When you add them you get %s\" %(q+r)\n",
" print \"When you multiply them you get %s\" %(q*r)\n",
" print \"When you subtract them you get %s\" %(q-r)\n",
" print \"When you divide them you get %s\" %(q/r)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Did it work? \n",
"\n",
"Nice job! "
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 2",
"language": "python",
"name": "python2"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.9"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment