diff --git a/programing/intro_to_classes.ipynb b/programing/intro_to_classes.ipynb
new file mode 100644
index 0000000..7b7e657
--- /dev/null
+++ b/programing/intro_to_classes.ipynb
@@ -0,0 +1,720 @@
+{
+ "cells": [
+  {
+   "cell_type": "code",
+   "execution_count": 19,
+   "metadata": {
+    "collapsed": true,
+    "deletable": true,
+    "editable": true
+   },
+   "outputs": [],
+   "source": [
+    "from __future__ import print_function"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
+   "source": [
+    "# Introduction to Classes/Object Oriented Programing (in Python!)\n",
+    "\n",
+    "Here we present a few simple classes to help explain what a class is.\n",
+    "\n",
+    "Let say we work in a pet hotel and we want to keep track of information about all the pets currently staying in our hotel. Each pet would have different information say\n",
+    "* Name\n",
+    "* Species\n",
+    "* What Room they are in\n",
+    "* Weight\n",
+    "* etc\n",
+    "\n",
+    "One Way to store this information would be to have a list for each pet like the following:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 20,
+   "metadata": {
+    "collapsed": true,
+    "deletable": true,
+    "editable": true,
+    "scrolled": true
+   },
+   "outputs": [],
+   "source": [
+    "# [Name, Species, Room Number]\n",
+    "Frank = ['Frank', 'dog',  'A4']\n",
+    "Kevin = ['Kevin', 'cat',  'C1']\n",
+    "Steve = ['Steve', 'fish', 'T3']\n",
+    "        \n",
+    "pets = [Frank, Kevin, Steve]"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
+   "source": [
+    "Then you could reference the information about the pets by looking at the different indices of each list."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 21,
+   "metadata": {
+    "collapsed": false,
+    "deletable": true,
+    "editable": true,
+    "scrolled": true
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Frank is a dog and is in room A4\n",
+      "Kevin is a cat and is in room C1\n",
+      "Steve is a fish and is in room T3\n"
+     ]
+    }
+   ],
+   "source": [
+    "def pet_print(pet):\n",
+    "    info_str = \"{} is a {} and is in room {}\"\n",
+    "    print(info_str.format(pet[0],pet[1],pet[2]))\n",
+    "\n",
+    "for p in pets:\n",
+    "    pet_print(p)\n",
+    "    "
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
+   "source": [
+    "But this is unintuitive and requires you to remember which index is which pet and which index is which quantity. This also leaves very little flexibility for changing the order. What if some one else wanted to use your code?"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 22,
+   "metadata": {
+    "collapsed": false,
+    "deletable": true,
+    "editable": true,
+    "scrolled": true
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Lilly is a C2 and is in room Lizard\n"
+     ]
+    }
+   ],
+   "source": [
+    "# [Name, Room Number, Species]\n",
+    "Lilly = ['Lilly', 'C2','Lizard']\n",
+    "\n",
+    "pet_print(Lilly)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
+   "source": [
+    "This makes no sense, and it would require the person who is trying to enter Lilly into the system to remember that the list order is Name, room number, species, and then weight.\n",
+    "### A note about classes and instances\n",
+    "A class is essentially the set of of code that you run to create an object. It is an abstract set of of instruction. An instance is a particular instance of the class, i.e. when you run the code and declare a variable with its own unique information, that variable is an instance of a class. A more simple example is the list in python is the list (which is a class in its own right). The list (`[]`) is a class, it can hold information, it has its own methods that can operate on the data it contains (`[].append()`, or `[].pop()`). However we can have as many different lists as we want, and each can contain different thing:\n",
+    "```python\n",
+    "list1 = [1, 2, 3, 4]\n",
+    "list2 = ['a', 'b', 'c']\n",
+    "list3 = [1.45, 'python!', [1,2,3]]\n",
+    "```\n",
+    "Each of these items is a list, they all behave like a list would, but they are all different, each one of these is an _instance_ of the list class. In our example, Pet is the object, and Frank is the instance of the Pet class.\n",
+    "\n",
+    "## Classes and solve this problem (and do a lot more). \n",
+    "We can create our own data structure that is specifically suited for our pets."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {
+    "collapsed": true
+   },
+   "outputs": [],
+   "source": []
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 23,
+   "metadata": {
+    "collapsed": true,
+    "deletable": true,
+    "editable": true,
+    "scrolled": true
+   },
+   "outputs": [],
+   "source": [
+    "class Pet(object):\n",
+    "    \"\"\" A simple class that keeps track of info for a pet\n",
+    "    \"\"\"\n",
+    "    \n",
+    "    def __init__(self, name, species, room_num):\n",
+    "        self.name = name\n",
+    "        self.species = species\n",
+    "        self.room_num = room_num\n",
+    "        \n",
+    "    def get_name(self):\n",
+    "        return self.name        \n",
+    "\n",
+    "    def get_species(self):\n",
+    "        return self.species\n",
+    "    \n",
+    "    def get_room_num(self):\n",
+    "        return self.room_num"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
+   "source": [
+    "Great! We have just created our own class that will let up keep track of info about our pets! Let's see if we can understand all of what we just did.\n",
+    "\n",
+    "```python\n",
+    "    class Pet(object):\n",
+    "```\n",
+    "This line indicates that we are creating a class. Everything below this line and indented is part of this class. The class is called Pet and we will call Pet() to create an instance of this class (We will discuss what an instance is in one minute). We will also come back and explain why we have included object after we have talked about inheritance\n",
+    "\n",
+    "```python\n",
+    "    def __init__(self, name, species, room_num):\n",
+    "```\n",
+    "\n",
+    "This is the init class method and it is a special method because it is automatically called when you create a pet object. We create a pet object by using the following command:\n",
+    "```python\n",
+    "Frank = Pet('Frank', 'dog', 'A4')\n",
+    "```\n",
+    "When this is called, python finds the Pet class and then calls the `__init__` method and passes the arguments `'Frank'`, `'dog'` and `'A4'`. Now you might say, __but Colby, init takes 4 arguments not 3! This program will crash!__, but `self` is a special variable that is the first argument of _most_ class methods and `self` is essential a reference to the current instance of the class. `self` allows the code contained within the class to call different attributes or methods associated with that class. So then the code below `__init__` creates and sets the name, species and room_num data attributes.\n",
+    "\n",
+    "```python\n",
+    "    def get_name(self):\n",
+    "        return self.name        \n",
+    "\n",
+    "    def get_species(self):\n",
+    "        return self.species\n",
+    "    \n",
+    "    def get_room_num(self):\n",
+    "        return self.room_num\n",
+    "```\n",
+    "These are a set of methods called \"getter\" methods. Each of these methods accesses data attributes associated with the particular instance.\n",
+    "\n",
+    "Lets try this out and see what happens."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 26,
+   "metadata": {
+    "collapsed": false,
+    "deletable": true,
+    "editable": true,
+    "scrolled": true
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Name is  Frank\n",
+      "Species is  dog\n",
+      "Room Number is A4\n"
+     ]
+    }
+   ],
+   "source": [
+    "Frank = Pet('Frank', 'dog', 'A4')\n",
+    "print('Name is ', Frank.get_name())\n",
+    "print('Species is ', Frank.get_species())\n",
+    "print('Room Number is', Frank.room_num)\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
+   "source": [
+    "Now let's make some more instances!"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 30,
+   "metadata": {
+    "collapsed": false,
+    "deletable": true,
+    "editable": true,
+    "scrolled": true
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Frank is a dog and is in room A4\n",
+      "Kevin is a cat and is in room C1\n",
+      "Steve is a fish and is in room T3\n"
+     ]
+    }
+   ],
+   "source": [
+    "Kevin = Pet('Kevin', 'cat', 'C1')\n",
+    "Steve = Pet('Steve', 'fish', 'T3')\n",
+    "\n",
+    "pets = [Frank, Kevin, Steve]\n",
+    "\n",
+    "def pet_print(pet):\n",
+    "    info_str = \"{} is a {} and is in room {}\"\n",
+    "    return info_str.format(pet.get_name(),\n",
+    "                           pet.get_species(),\n",
+    "                           pet.get_room_num())\n",
+    "    \n",
+    "for p in pets:\n",
+    "    print(pet_print(p))"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {
+    "collapsed": true,
+    "deletable": true,
+    "editable": true
+   },
+   "source": [
+    "Now if someone using your code wants to add a pet to your hotel all they need to do is:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 41,
+   "metadata": {
+    "collapsed": false,
+    "deletable": true,
+    "editable": true,
+    "scrolled": false
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Lilly is a Lizard and is in room C2\n",
+      "Lilly is a Lizard and is in room C2\n",
+      "Lilly == Lilly2? False\n",
+      "<__main__.Pet object at 0x110519050>\n",
+      "<__main__.Pet object at 0x110369290>\n"
+     ]
+    }
+   ],
+   "source": [
+    "Lilly = Pet('Lilly', 'Lizard', 'C2')\n",
+    "print(pet_print(Lilly))\n",
+    "\n",
+    "# Note an alterntive way to do this\n",
+    "Lilly2 = Pet(name='Lilly', room_num='C2', species='Lizard')\n",
+    "print(pet_print(Lilly2))\n",
+    "\n",
+    "#print(Lilly.get_room_num() == Lilly2.get_room_num())\n",
+    "# But note somthing about different instances with idential information\n",
+    "print('Lilly == Lilly2?', Lilly == Lilly2)\n",
+    "print(Lilly)\n",
+    "print(Lilly2)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 39,
+   "metadata": {
+    "collapsed": false
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "True\n"
+     ]
+    }
+   ],
+   "source": []
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
+   "source": [
+    "### Calling a class method vs calling an instance method\n",
+    "We talked about how when we call `Frank.get_name()`, we don't have to pass any arguments because the class realizes that we are asking for get_name of Frank, we could get at this the same way, but calling the class method get_name and passing `Frank` as the argument as `self`:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 48,
+   "metadata": {
+    "collapsed": false,
+    "deletable": true,
+    "editable": true,
+    "scrolled": true
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Frank\n",
+      "Frank\n"
+     ]
+    },
+    {
+     "ename": "TypeError",
+     "evalue": "unbound method get_name() must be called with Pet instance as first argument (got nothing instead)",
+     "output_type": "error",
+     "traceback": [
+      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+      "\u001b[0;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
+      "\u001b[0;32m<ipython-input-48-0b33b582e9ed>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      3\u001b[0m \u001b[0;32mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mPet\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_name\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mFrank\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      4\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 5\u001b[0;31m \u001b[0;32mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mPet\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_name\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
+      "\u001b[0;31mTypeError\u001b[0m: unbound method get_name() must be called with Pet instance as first argument (got nothing instead)"
+     ]
+    }
+   ],
+   "source": [
+    "print(Frank.get_name())\n",
+    "\n",
+    "print(Pet.get_name(Frank))\n",
+    "\n",
+    "print(Pet.get_name())\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
+   "source": [
+    "### Another special class method\n",
+    "Before we saw the `__init__` method do somthing unique when we instansiated (or initalized (get it?)) the object. Another suck method is the `__str__` method. This method defines what should be returned when you try to convert (sometimes called cast) the object to a string."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 49,
+   "metadata": {
+    "collapsed": false
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "<__main__.Pet object at 0x1103a3ed0>\n"
+     ]
+    }
+   ],
+   "source": [
+    "print(Frank)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 50,
+   "metadata": {
+    "collapsed": false,
+    "deletable": true,
+    "editable": true,
+    "scrolled": true
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Frank is a dog and is in room A4\n"
+     ]
+    }
+   ],
+   "source": [
+    " class Pet(object):\n",
+    "    \"\"\" A simple class that keeps track of info for a pet\n",
+    "    \"\"\"\n",
+    "    \n",
+    "    def __init__(self, name, species, room_num):\n",
+    "        self.name = name\n",
+    "        self.species = species\n",
+    "        self.room_num = room_num\n",
+    "        \n",
+    "    def get_name(self):\n",
+    "        return self.name        \n",
+    "\n",
+    "    def get_species(self):\n",
+    "        return self.species\n",
+    "    \n",
+    "    def get_room_num(self):\n",
+    "        return self.room_num\n",
+    "    \n",
+    "    def __str__(self):\n",
+    "        info_str = \"{} is a {} and is in room {}\"\n",
+    "        return info_str.format(self.name, self.species, self.room_num)\n",
+    "\n",
+    "Frank = Pet('Frank', 'dog', 'A4')\n",
+    "\n",
+    "print(Frank)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
+   "source": [
+    "### Accessing data attributes in python\n",
+    "In python all attributes are public\\*, and you can directly get and set attributes of an instance by simply doing the following:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 51,
+   "metadata": {
+    "collapsed": false,
+    "deletable": true,
+    "editable": true,
+    "scrolled": true
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Frank is a dog and is in room A4\n"
+     ]
+    }
+   ],
+   "source": [
+    "print(Frank.name + ' is a ' + Frank.species + ' and is in room ' + Frank.room_num)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 52,
+   "metadata": {
+    "collapsed": false,
+    "deletable": true,
+    "editable": true,
+    "scrolled": true
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Frank is a dog and is in room C1\n"
+     ]
+    }
+   ],
+   "source": [
+    "Frank.room_num = 'C1'\n",
+    "print(Frank)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {
+    "collapsed": true,
+    "deletable": true,
+    "editable": true
+   },
+   "source": [
+    "\\*You can 'hide' class attributes from people using your code, but it does not stop them from accessing them.\n",
+    "\n",
+    "## Subclasses!\n",
+    "Now lets say we have our class that describes animals, but lets say we need to keep track of species specific information. For example lets say we need to keep track if a dog and do tricks, or if a cat is declawed, or if a fish is fresh water or salt water. We could go through and write a `Dog` class that would be identical to the `Pet` class but would have one extra method `get_tricks()`. But this is redundant, so what we can do is use subclasses."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 54,
+   "metadata": {
+    "collapsed": false
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Colby is a fish and is in room F3\n"
+     ]
+    }
+   ],
+   "source": [
+    "class Fish(Pet):\n",
+    "    pass\n",
+    "\n",
+    "Colby = Fish('Colby','fish','F3')\n",
+    "print(Colby)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 55,
+   "metadata": {
+    "collapsed": false,
+    "deletable": true,
+    "editable": true,
+    "scrolled": true
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Frank is a Dog and is in room A4 who can ['sit', 'stay', 'beg']\n",
+      "Luna is a Dog and is in room A5\n"
+     ]
+    }
+   ],
+   "source": [
+    "class Dog(Pet):\n",
+    "    \"\"\" A simple class that keeps track dogs\n",
+    "    \"\"\"\n",
+    "    \n",
+    "    def __init__(self, name, room_num, tricks=None):\n",
+    "        Pet.__init__(self, name, 'Dog', room_num)\n",
+    "        self.tricks = tricks\n",
+    "        \n",
+    "    def get_tricks(self):\n",
+    "        return tricks\n",
+    "\n",
+    "    def __str__(self):\n",
+    "        if self.tricks is not None:\n",
+    "            return Pet.__str__(self) + ' who can ' + str(self.tricks)\n",
+    "        else:\n",
+    "            return Pet.__str__(self)\n",
+    "        \n",
+    "Frank = Dog('Frank', 'A4', ['sit', 'stay', 'beg'])\n",
+    "print(Frank)\n",
+    "\n",
+    "Luna =  Dog('Luna', 'A5')\n",
+    "print(Luna)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {
+    "collapsed": true,
+    "deletable": true,
+    "editable": true
+   },
+   "source": [
+    "We can do the same thing for a cat!"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 57,
+   "metadata": {
+    "collapsed": false,
+    "deletable": true,
+    "editable": true,
+    "scrolled": true
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Kevin is a Cat and is in room C1 and is decalwed\n",
+      "Tilly is a Cat and is in room C2 and is not declawed\n"
+     ]
+    }
+   ],
+   "source": [
+    "class Cat(Pet):\n",
+    "    \"\"\" A simple class that keeps track cats\n",
+    "    \"\"\"\n",
+    "    \n",
+    "    def __init__(self, name, room_num, has_claws):\n",
+    "        Pet.__init__(self, name, 'Cat', room_num)\n",
+    "        self.has_claws = has_claws\n",
+    "        \n",
+    "    def is_declawed(self):\n",
+    "        return not self.has_claws\n",
+    "\n",
+    "     \n",
+    "def cat_print(c):\n",
+    "    if c.is_declawed():    \n",
+    "        print(c, 'and is decalwed')\n",
+    "    else:\n",
+    "        print(c, 'and is not declawed')\n",
+    "        \n",
+    "Kevin = Cat('Kevin', 'C1', has_claws=False)\n",
+    "Tilly = Cat('Tilly', 'C2', has_claws=True)\n",
+    "\n",
+    "cat_print(Kevin)\n",
+    "cat_print(Tilly)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {
+    "collapsed": true,
+    "deletable": true,
+    "editable": true,
+    "scrolled": true
+   },
+   "outputs": [],
+   "source": []
+  }
+ ],
+ "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.10"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}