Saturday, November 9, 2013

PyTutorial: Real Programmers Pack

And by that, I mean, they use packages, of course. :)

This is the 9th in a series of posts.  If you want to go the the start, go here.

What if I asked you to write a program that fetches some information from the internet?  Say, the main page of python.org.  How would you go about doing that?

You may start learning all about programming for the internet: sockets, DNS, HTTP and what not.  A pretty tough task.  Not impossible, but definitely tough.  There are some big & heavy books on the subjects that you can spend an eternity reading.  Some people like that sort of thing.  That, or you can do something like this instead:

Packages (a.k.a libraries) are other people's code that help you achieve specific tasks.  You can imagine that there are lots of different things that a programmer would like to achieve, and, this being the case, there are lots of packages available out there to help you do what you want to do.  Python has quite a few packages that come pre-installed when you install Python, and thus they're called "built-in" packages.  But for every package that comes pre-installed with Python, there are hundreds if not thousands of packages out there that you can get (almost always for free, but sometimes for a price), install, and then use to help you in your programming adventures!

One of the advantages of using a package is that you get code that you would have to work very long and hard to write, well, instantly!  Not only that, many of these packages are well tested and many of its bugs have been fixed, thus not only do you get complicated code easily, you get pretty good code at that!

Of course, packages also have their disadvantages:  because someone else wrote them, they work the way they wanted it to work.  Good packages are pretty easy to work with, but some, even if they're good, may not "fit" the way you want to work with the code.  Just something to keep in mind.  Another problem that comes up is that sometimes packages do have bugs, and if one of these bugs affects you, well, you may have to wait some time until it's fixed.  In this regard, open-source packages are less of a problem: since the code is available, if there is a serious bug, at least there is a chance for you to fix it on your own.

Having said all that, packages are usually simply great to work with.  I highly recommend looking for a package before deciding to write some code yourself.  The time it will save you will be significant.  That, and the quality of your code will improve as well.  As a rule, try and concentrate on the part of the program that only you are willing to write.  Why work to build something that others have already built and made available for you to use?

Going back to the teaser at the start:

Try it!  Pretty neat, huh? I find it pretty amazing that it's so easy to achieve something as complicated as getting information from the web.  You can imagine that not a small amount of things have to happen behind the scene for this to work.  The beauty of using packages is just that: you can let the boring things happen behind the scene, freeing you to concentrate on what matters to you!

Now, let's go a little bit about how this works.  The line, "import urllib2" tells Python that you want to use the package urllib2.  If this package isn't installed on your computer, you will get some error message (duh!). But because urllib2 is a built-in package, well, it should be available for you to use!

Now, every package has its own way that it lets you work with it.  In tech-speak, this is called the package's interface.  An interface is usually just a bunch of functions (and classes) that the package made available for you to use.  Sometimes it may be some pieces of information as well.  For instance, the math package has a variable called pi, which, as you probably have guessed, contains an approximation of pi!  These variables aren't meant to be changed, and therefore are usually called constants.  Pi is pi, and that's that.

In our example, we want to use the "urlopen" function that urllib2 has to offer.  To do that, we just type in the name of the package, then a dot, then the name of the function that we want to use.  Pretty straight forward.
Calling urllib2.urlopen returns an object, with a method named read that you can use to actually get the content of the web page.  Of course, urllib2 has plenty more things that you can do with it, which you can read about here.  When reading such documentations, many time I prefer to scroll down to the bottom and quickly glance at the examples that are provided.  Usually, you can get a good feel for what the package does in a few minutes without having to read a whole bunch of boring documentation.

There are plenty more built-in packages that are available to you.  Python has a quick overview as well as a  comprehensive list of all of them.  I highly recommend that you take the time now to browse through the packages and see what Python has to offer.  Keep in mind that you're using Python 2.7 when looking for packages, as packages in Python 3.3 are slightly different.
Assignment 9.1: go through Python "quick overview" of packages and play around with the examples to see what Python has to offer.  You will notice that Python even has some built-in packages that help you test your code!  That's a good attitude. :)
Assignment 9.2: go through the "comprehensive list" of Python packages.  Just read the table of contents to see what's offered.  I want you to be impressed by all the code that other people wrote that you can so easily use.  If something strikes you as particularly interesting, clear on it and explore.  You don't need to memorize anything here, just enjoy all the power you now can wield. :)
Pretty exciting stuff, huh?  Did you notice all the things that you can do with numbers and strings? How about the wealth of data types (beyond numbers, strings, lists, and maps) that are readily available for you (particularly dates and sets)?  There's also that neat little package, pickle, that lets you save your Python data to disk and later read them again!

There are also packages that help you test and troubleshoot your code.  The logging package is a great way to write logs.  There are also lots of development as well as debugging and profiling tools that you can use (profiling being tech-speak for finding which parts of your code run fast, and which run slow.)

More ways than one
Python offers 4 ways of using packages.  The first is as I showed you:
>>> import urllib2
>>> x = urllib2.urlopen(...)

Another way of achieving the same thing is:
>>> from urllib2 import urlopen
>>> x = urlopen(...)

This approach has the advantage of less typing, but the disadvantage of making it less clear where functions come from.  A slight variation of the above is:
>>> from urllib2 import urlopen as foo
>>> x = foo(...)

This approach can be rather confusing, so use it scarcely (if at all.)

Finally, there's the wildcard approach:
>>> from urllib2 import *
>>> x = urlopen(...)

I tend to dislike this style, because it makes all the functions in urllib2 available.  This is the most confusing, because then there is very little clue where a function comes from, especially if you do a wildcard import from more than one package!

Even more packages

If you think that there are lots of built-in packages, well, you'll be shocked by the sheer number of packages that are available for you!  If you go to PyPI (Python's Package Index), you'll be able to find about 36 thousand packages that are ready for you to install and use!!  These aren't official Python packages, and some of them are better maintained than others.  But they're there, and easy to download and start using!

To start using packages from PyPI, the easiest thing to do is to first download PIP.  If you're using Windows, it means downloading a little program from here.

If you're running Ubuntu, then all you need to do is run the following:
# apt-get -q -y install python-pip python-dev build-essential
# pip install --upgrade pip

Then, to install a package, you first need to know the name of the package that you want.  The package name is the part without the version number.  For instance, having randomly clicked on pw:

You can see that the package name is simply "pw".  Scroll down to the bottom of the page, you should see something like this:

It's important to see whether or not the package is compatible with Python 2.7.  Most are.  In fact, more are compatible with Python 2 than with Python 3.

Now, just for exercise, let's find some package to install.  Just to make things a bit interesting, I went to:
http://pypi-ranking.info/alltime, a website that shows you popular PyPI packages. On it, I found the "requests" package (8th most popular PyPI package of all time) which seems to be a popular alternative to Python's urllib2.  To install it, all you have to do is run the command:
pip install requests
On Windows, it looks something like this:

And on Ubuntu, well, like this:
# pip install requests

Now, you can use the requests package in your python code:

It doesn't get much easier than this.
Assignment 9.3: install the requests package using pip.  Then try to run the above code and see how it works!
To upgrade the package, all you need to do is run:
pip install --upgrade requests 
And if you no longer want the package installed on your system anymore, all you have to do is run:
pip uninstall requests
Of course, there are plenty more Python packages that you can use that for one reason or another can't be found on PyPI.  Some of them are really happening, actually.

BTW, I'm not really sure why this package exists, and what its advantages are over Python's built-in urllib2 package.  But if it's interesting to you, I'm sure you can read about it on countless blogs.  Searching for "python urllib2 vs requests" I found quite a few sites that discuss exactly that.

Which bring me to a few important points regarding packages:

Think about what you need.
Before jumping into a package, it's a good habit to think a little about what you want done. What would the "ideal" package contain?  How would you want to use it?  etc. etc. etc.

Don't use the first package you see.
Look around at Python's built-in packages, but also look for other packages.  Say you wanted to find alternatives for urllib2, you can search for "python alternatives for urllib2" or simply "urllib2 vs".  The requests package (and others) would show up...

Now you should do your homework: see what problems they are trying to solve, and how close are they to what you want done.

  • Many times, you will discover that different packages go about solving the same problem in vastly different ways.
  • Some packages are better maintained than others.  See how many downloads there are, as well as how often it gets updated.
  • Some packages are more extensive than others.  Bigger isn't always better.  Some packages try to solve many problems, while others concentrate on a simple task at hand.  See which package best meets your needs.
  • Some packages are better documented, and easier to use than others.


Discover more about what you really need.
As you browse through a package documentation, you may end up learning more about the topic at hand.  You may discover, for instance, that getting documents off the internet is more complicated than initially imagined, and thus your initial requirements of an "ideal" package will change.

By learning about competing packages, you will better learn about the concepts and limitations of whatever it is that you're trying to accomplish.

Be reasonable about this.
As you can see, there are tens of thousands of packages around on PyPI alone!  You can spend many lifetimes going through them, comparing them, analyzing them, etc etc.  Don't go nuts with this!

If you're trying to just do something quickly, you can probably use any package you want! But if your program will depend heavily on a particular package, and this program is dearly important to you, well, then it's probably worth it to invest a little of your time.

Life is a work in progress.  You will never find the perfect package.  You will never write the perfect program.  Try to enjoy the ride.
Wow factor
Just to impress you with some of the amazing things out there, check out these insanely fascinating packages (in no particular order):
  • NLTK: an amazing package to help you work with natural language, that is, figure out what people mean when they write stuff in English, or some other human lanaguage. 
  • SQLAlchemy: a sophisticated package to help you manage the data that you want to save.
  • SciPy.org: a collection of packages that let you perform complicated math and scientific calculations fast.
  • mlpy: a Machine Learning (a.k.a Artificial Intelligence) package for Python
  • flask, and django: two packages (among many) with a very different take on how to build web applications in Python.  They're both amazing in their own way.
  • kivy: a relatively new package that lets you write Android & iPhone apps using Python.
  • matplotlib: lets you generate wonderful graphs and charts and other figures using Python.
  • arrow: not so much "wow", as much as making dealing with dates nicer.
And there are more.  Much more.  All you have to do is look around a bit...

Writing your own modules

When writing a large piece of software, you may want to break up your code into modules and packages.  Some advantages in writing your own modules / packages are:
  1. It gets you thinking abstractly about the problem.  A module does something generic, thus now you're trying to solve a generic problem.  This will get you thinking of how to solve that problem, as opposed to the specific coding problem at hand.  Thinking abstractly may help you better understand the requirements of whatever it is that you're trying to achieve.
  2. Easier to test.  Having a generic module is easier to test than some functions that are deeply integrated inside your code.  Easier to test means better tested.  Better tested means better code.
  3. Code reuse.  This is usually highlighted as #1, but for me, it's nowhere near as important as the above two.  Sure, code reuse is great, if you ever end up reusing it.  But most likely, you'll never really need to. :)  
You can think of modules as a small package, or of a package as a collection of modules.  At any case, writing your own module is very simple.

A module is basically just a regular python file, one with functions and classes, but one that doesn't actually call any of it's code.  If you try running it, it doesn't do anything!   Seems rather useless, doesn't it? :)

But, if you import the file (aka module) from another file, then that file can use any of the functions / classes in the module file.  See?

For example, say you had a file, file1.py: (that's your module file)

And another, file2.py: (that's the file using your module file)

Try running file2.py and see what happens.  Pretty neat, huh?  Did you notice that the import doesn't include the .py extension?  Great! :)

I recommend that you read more about the modules here.
Assignment 9.4: write a module that contains a function that prints a random number to the screen.  Call that function from another file.
Assignment 9.5: add to the module file a class that does something silly.  Use that class in another file. 
On the other hand, writing your own packages is a bit more complicated.   The biggest complication with packages is the way python figures out where they exist in your file-system.   This is a bit out of the scope of this tutorial, but you can learn more about packages here.  If you choose to write your own packages, then you may want to know about how to set the environment variable PYTHONPATH, as well as about relative imports.  Finally, if you want to make a package that can be installed using pip, then you should check out this tutorial.  At any case, writing modules is probably all you'll really need (at least for a while) so don't worry about all that.

Assert This!

Although a bit on a tangent: you should really know about the assert keyword.  It's a great way to make sure that your code is working as expected.  To use it, you just write:
>>> assert x == 3, "expecting x to be 3, but got %d instead" % (x,)

or:
>>> assert len(list) > 0, "expected something in this list!"

or, if you're really laze, just something like this will work too:
>>> assert len(list) > 0

etc. etc.  You get the point.  The key idea here is that if your assertion fails, an exception is raised. 

You should use them to test your most basic assumptions about what is going on in your code.  If they fail, you know something major is wrong, and you don't have to wait until some visible symptoms appear (and they will appear whenever it is least convenient for you, of course).  You should read this short little tutorial about using asserts here.

Minesweeper

In this lesson, we covered a few packages, can you think of using some of them in your Minesweeper code?
You're already using the random package in there, but what else can you use?

Here are some simple suggestions:
  • Use the logging package to add troubleshooting information to your code.
  • Use the pickle package to save and load "high scores" between games.
  • You can use the date object from the datetime package to add a date to the "high scores" board.
A nice thing that you can do is to separate the logic of the game from the user-interface part of the game by putting it in a separate module.  For instance, you can put things like cell & grid calculations into a separate file called logic.py.  Then, import that module from the part that actually plays the game and does all the user input and output.  Sometimes it may not be 100% certain where a function or a class should go, well, that's fine.  You can either just arbitrarily chose a place for it, or perhaps it's a sign that you should modify that piece of code in a way that better separates between the "logic" of the game and the "user interface" part.

Another thing that you should do is find a good way to test your code!!  Read about the built-in doctest and unittest packages, but also look around for alternatives.  Perhaps nose is a good alternative?  What are the differences between them?  Which one do you like the most?  Whichever package you like the most, great.  Now use it to test your Minesweeper code.

While you're looking into unit-testing modules, you should also add a bunch of assert statements to verify that your code is working more-or-less as expected.  As a little bonus, most unit-testing packages out there figure out that when an assert fails, the test failed as well.  But assertions are great to have even without any unit-testing.

Finally, go ahead and break your code into a few separate modules.  Perhaps you can have one module that contains the code for the logic of the game.  Perhaps another that contains the UI (User Interface, that is, the printing to the screen and input from the keyboard) that you have in the game.  Then, you can have your main minesweeper game import and use these modules.

Great news!
We've come a long way with our Minesweeper game.  But are we satisfied with it?  Never!!!

In the next lesson, we'll take the game to the next level.  And by that, I mean adding neat little graphics and even sounds!   As you can probably imagine, that will require using a package.  Of course, I already have a package in mind that I will want you to use, but as an extra credit:
Assignment 9.6: look for some nice packages that we can use to add graphics for our little Minesweeper game.  What are our requirements?  What are the alternatives?  Seen anything you like? :)
Brace yourself, the next lesson will be more fun than a basket full of barking frogs. :)


Saturday, November 2, 2013

PyTutorial: More on classes

This is the 8th in a series of posts.  If you want to go the the start, go here.

In the previous lesson, you got your first introduction to classes.  As I mentioned then, classes are a way to describe relationships between information and actions.  Exactly how to determine the best way to relate various pieces of information and actions together is more of an art than science (although there is some science to it).  I'll go into some of the science (and science-fiction) of writing classes in a future tutorial on design patterns,  but at this point, your most important friend when trying to figure out which classes to create is elegance:
Write your classes in such a way as to make your coding tasks simpler, easier to understand, and less difficult to test.
The more programming experience you have under the belt, the easier it will become for you to get a sense for a clean, simple design.

In this lesson, I want to expand on the ideas of the previous tutorial and show you some more interesting things that can be done with classes.  Hold on tight! ;)

A Family Tree

One powerful thing that you can do when creating classes is to "steal" the code of one class and expand on it to create another one.  For example, say you had an "Car" class that deals with miles per gallon, number of passengers, safety ratings and whatever else you may have it do.  And then, you want to create another class, called "Taxi", that can do everything that a Car can do, but more!  For instance, as Taxi may have a license number, a rate per mile, and a phone number that it can be reached at.  Of course, a Taxi still has all the properties that a Car has: miles per gallon, number of passengers, etc.  

How would you code these classes?

One thing you can do is "copy and paste" all the code you have for Car, rename it "Taxi", and then add all the properties for Taxi.  This is evil.  :)  In general, if you find yourself copy-pasting too much code, you're probably doing something wrong.  The reason is that when you copy-paste code, you end up with similar or identical code spreading about your program, and if you discover a bug in one place, you have to look for all the other places that you may have to fix.   This is hell on earth.


Another option is to add all the properties that you want for Taxi straight into the Car class.  With this approach, you have one class that contains all the properties for both Car and Taxi.  This is another evil.  The problem with this approach is that you end up polluting the very idea behind a class: namely, that it should contain information and actions that relate to each other!  Now, when you want a Car (and not a Taxi), you end up with all the code for Taxi in there anyways!  This is stinky, and brings you a step closer to what is known in the profession as "spaghetti code":  code that is so confusing and messy that it looks like a pile of spaghetti.  Another hell on earth. :)

What is a nice programmer to do? :)

Related Classes

Lucky for us, there is an elegant way to solve the above problem.  We can keep the Car class clean and simple, and then create a new class, Taxi, that magically gets all the information and actions from the Car class, while adding its own information and actions that are specific to taxis.  In tech-speak, this is classed inheritance, and conceptually, it looks something like this:

Isn't this beautiful?  I thought you'd like! ;)

With this approach, if you create an object of type Taxi, it will automatically have access to all the information and actions that an object of type Car would have, without having to nastify your code.

Now, let's take a look at how inheritance is achieved in Python:

Can you figure out what it does?  Type it in and see what happens! :)

The key things to notice are:
  1. The Car class is completely "normal".  There is nothing new here.
  2. When creating the Taxi class, the Car class is mentioned in parenthesis.  This tells Python that you want the Taxi class to inherit all the properties (information and actions) from the Car class.  In tech-speak, the Taxi class is derived from its base class, Car.
  3. The Taxi class has access to all the methods and data-members in the Car class.  Note that Pick_Up_Client() is accessing self.num_passengers and self.Go_Somewhere() as if they're directly a part of the Taxi class.
  4. The Taxi class's constructor (__init__ method) needs to explicitly call the constructor of its parent (base) class.  If it didn't do it, the Taxi objects wouldn't be created properly (they wouldn't get all the data-members from the Car class.)  Try commenting out the explicit call to Car.__init__() and see what happens.
  5. Objects of type Taxi can access the methods and data members from the Car class as if they're directly defined in the Taxi class.  Notice the call to taxi1.Fill_Up_Gas().
Pretty neat, huh?  Can you think of other situations in which inheritance can make your code more elegant?

How about a FoodItem class that contains nutritional information about anything edible.  You can then have another class, ManufacturedFoodItem that inherits from FoodItem and has information about who are its manufacturers, as well as what are its key ingredients.
Assignment 8.1: draw up a class diagram for both the FoodItem class as well as the ManufacturedFoodItem class.
Assignment 8.2: write up the code that implements the above two classes.
A nice thing about inheritance is that more than one class can inherit from any given base class.  For instance, you can also have a Produce class that inherits from FoodItem and contains information about foods that actually grow.  This information can include geographical location that it grows best in, and months of years that it bears its fruits.
Assignment 8.3: draw up the class diagram for the Produce class as described above.
Assignment 8.4: Implement the code for the Produce class.
Sometimes, deciding between creating a sub-class (thus using inheritance), or just adding more information to an existing class can be confusing.  For instance, say you had a Balloon class,  and you wanted to add a color attribute, should you add it to the Balloon class, or create more classes, such as GreenBalloon, RedBalloon, etc?

Well, I have two "rules of thumb".  The first goes back to the taxi example above, and is basically that:
If you're considering adding an attribute of a function that is only relevant to a few of the objects of that class, you may want to create a sub-class for it.
In the Car / Taxi example, adding a Taxi License attribute is only relevant for taxis, and thus shouldn't be added into the car class.  On the other hand, every balloon has a color, thus the color attribute should just be added to the balloon class.

But even before this rule of thumb, you were probably getting a strange sense of a stomach ache when I was bringing up the option for a GreenBalloon, RedBalloon classes, etc.  Something inside you was cringing, telling you that this is just plain wrong.  Which brings me to the other rule of thumb for you:
If you're about to do something that makes you want to vomit, most likely, you're doing it wrong.  Take a step back and think of how you can do things differently.
BTW, the above rule applies for many aspects of life, not just class inheritance.  You're welcome!

Endless Fun

You may be wondering if you can inherit from a class that already inherits.  Well, you don't have to wonder much longer!  The answer is a definite yes! :)  How exciting?!!

Say, for the sake of example, that taxicabs on our beloved moon are significantly different from our early kind.  Lunar cabs require a purple elephant assigned one for each cab!  In that case, you may want to inherit from the Taxi class to create a LunarTaxi class, perhaps do something like this:

Enjoy!

Assignment 8.5: Remember our Produce class?  Good.  Now, I'm not a great farmer, not by any standard.  But just follow me here and let's assume that there are three different kinds of produce: land produce, water produce, and air produce.  And they're all radically different from each other.  Well, at least different enough to warrant different classes.  For instance, we can assume that earth produce require certain amount of earth to grow.  They may also require a certain type of earth.  On the other hand, wa

Can you square the rectangle?

Here's a riddle for ya: say you have a Shape class.  From it, derive three classes: CircleRectangle, and Square.  Something like this:

As a reminder, because all three are inherited from Shape, all three have the color attribute, as well as the draw_on_screen method.  And the riddle is: what's wrong with this picture?  Do you sense a problem?  Is anything wrong?

Well, don't pull all  your hair out.  Save some for the next riddle. ;)  The problem lies in the fact that a square is a type of rectangle.  On the face of it, it doesn't seem like a big deal, in fact, there may be some advantages to this: the Square class gets to have only a "side length" attribute, while the rectangle needs both "width" and "height".

But the main problem here is that a square is indeed a type of rectangle!  Meaning, you now have two distinct ways of describe the same thing!  To draw a square, you can either use a Square class, or use a Rectangle class in which the width equals the height.  

Now, if you wanted to compare various shapes, to see if any are the same, you would have to complicate your code.  Instead of just comparing circles with circles, squares with squares, and rectangles rectangles, you would also have to compare squares to rectangles, to see if by any chance, your rectangle is really a square in disguise!  Perhaps not the end of the world, but a lesson to be learned:
Try not to have different ways of representing the same information in your code.  But, if for some hellish reason you must, then at the very least keep this problem in mind.
Now that I got you all nervous, pop quiz! (a.k.a assignment 8.6)

I'm going to give you two types of information, and my question for you is how should I structure the classes?  You have four possible answers that you can give me:

  1. Place both pieces of information into one class (like our green and red balloon example)
  2. Use two completely separate classes (like how our balloon and car classes have nothing to do with each other)
  3. Use two classes, but have one derive from another (like our car and taxi example)
  4. Use two classes, having both of them derive from a third, more abstract class.  (like our food item, produce, and manufactured food item classes)
You'll also have to elaborate on your answer. Got it? Good. BTW, there may be more than one good answer, you just need to have a good explanation.  Don't you just hate that? Let's go:
  1. A male soccer player and a female soccer player.
  2. A bird and a frog.
  3. A car and a piece of toast.
  4. A pager (what's that, you ask?) and a phone.
  5. A land-line phone (what's that, you ask?) and a cellular phone.
  6. A car and a Volvo.
  7. A car and a motorcycle.
  8. A pancake and maple syrup.
  9. A strawberry and a grape.
  10. An airplane and a pair of shoes.
  11. An employee and an employer.
  12. A nurse and a doctor.
  13. A purse and a wallet.
  14. A curse and a blessing.
Whew!  I hope that this was as hard for you as it was for me! :)

Multiple Inheritance

There is a hell on our programming earth known as multiple-inheritance.  Basically, it's a way for one class to inherit the attributes and methods of two or more unrelated classes.  For instance, you can have a class, called, Monster, that inherits from both the Car class and the Balloon class.

As expected, this can make for quite the mess, especially if some of these classes share a an attribute or method of the same name!

The good news, is that in Python, you don't really need to use multiple-inheritance. Therefore, I won't waste your time teaching it to you. :)  In languages like C++ and Java, multiple-inheritance makes more sense in some situations , and I may go into that in some future lesson.  For now, just know that it's possible, and that it's hell.  Avoid.

Interfaces / Polymorphism / Abstract Virtual Methods / Method Override!

Holy cow!  In a language like C++ or Java, all of the above can mean rather complicated things.  But in Python, they're basically short (or long) for having two classes with the same method name, that do the same thing, yet slightly differently.

For instance, if you go back to our Shape/Circle/Square/Rectangle class diagram above, there is one more little thing that makes no sense.  Which brings me back to my other riddle:  besides the square being a rectangle, what's wrong with that class diagram?

You may have noticed, that the Draw_on_screen method is only defined in Shape!  This means that it will be available for all the shapes that inherit from it, but it will do the same thing!  This doesn't really make sense on two levels:

  1. How can we draw an abstract shape?  What does it look like?  It looks like an error message to me. :)
  2. When drawing a circle, we want it to look different than a square.  Thus the Draw_on_screen method, although essentially doing the same thing for a circle as well as a square, will have to do it a little differently in each case.  In the circle's case, it will have to draw a circle, and in the square's case, it will have to draw a square.

Perhaps a better way to think of it is thus:

Thus the method, Draw_On_Screen is implemented in each class slightly differently.  In essence, this is a description of an interface, that is, every class that inherits from Shape needs to implement, at the very least, the method Draw_On_Screen in order to work as expected.

In Python, there's no explicit way to force a programmer to write a particular method in all the classes that inherit from a given class.  You just have to make it clear in the code that this is what's expected.  For instance, one can add a little comment in the main class that this needs to be done.  In other words, it would look something like this:

Type it in and see what happens!   Now, having the method, Draw_On_Screen() have the same name across different classes let's you treat the different classes, at least on some level, as being the same.  Basically, you can assume that every class that is derived from Shape() will have the method Draw_On_Screen().  Thus, you can have a list of different shapes, and then go through the list and draw them all, like this:

That is true beauty.  You can actually call the method Draw_On_Screen() on any instance of a class that is derived from Shape(), without even knowing which class it is!  It may draw a circle, or it may draw a rectangle.  You don't know, and frankly, you don't care!  You just want to draw all the shapes on the screen, it doesn't matter to you which shapes they are!

Wow! :)
Assignment 8.7: create a class, Triangle, and have it derive from the Shape() class.  Of course, have it implement the Draw_On_Screen() method.  Add a triangle to the my_shapes list above, and see what happens!
 Keep in mind that you should only be doing this when the different classes actually need to do things differently.  The shapes example is great, because one simply can't draw a shape without knowing which shape it is that is being drawn!  Yet, every shape can be drawn.

Generally, any time you need to manage a bunch of related classes (the all inherit from the same class), you probably will need to act on the objects in some sort of unified way.  When this happens, you'll find yourself wanting to implement similar methods across the different classes.
Assignment 8.8: think of a situation in which you need to implement identical methods across different classes.  Then go ahead and write the code for it, just to test it out! :)

If all fails, try and try again...

Now I'm going to take you on a slight tangent.  It still has to do with classes, but in a very different way.


Remember how back in Lesson 6 I showed you how you can use the built-in function, raw_input to get numbers from the user?  It went something like this:
>>> a = raw_input("Type in a number:")
>>> num_a = int(a)
>>> print num_a

Now this works nice as well, so long as the player is playing nice and actually types in a number... But what happens when the player types in something besides a number?  Say, she types in "howdy"?

Try it!

Did you get a big old error message in red that caused your entire program to quit?
Traceback (most recent call last):
  File "<pyshell#7>", line 1, in <module>
    int(num_a)
ValueError: invalid literal for int() with base 10: 'howdy'

What this error message tells you is that you can't convert "howdy" into a number.  Duh?! :)

In tech-speak, these sort of errors are called exceptions, probably because they represent special, unexpected scenarios.  And the reason that I'm bringing this up here (in a lesson on classes), is that in Python, exceptions are implemented using classes.  But more on this in a bit.

The problem in our example, of course, is that you don't want someone who is actually using your program to see this!  You want to be able to handle such errors gracefully.  In this case, it probably means asking the user to type in a number again... :)

Well, you're in luck!  Python provides you with a simple, yet powerful way to handle such exceptions. Check this out:
Can you figure out what happens here?  Type it in and try it out! :)

Basically, we have a "try-except" clause, which is sort of like our "if-else" clause, but different.  In the "try-except" clause, Python tries to run the code that's after the "try" statement.  If all goes well, good for you!  But, if there's some sort of exception, the code after the "except" statement gets run!  The key here is that the code after the "try" runs as usual, while the code after the "except" only runs if the code after the "try" fails!  That is, the code after the "try" has raised an exception.

BTW, the "try-except" clause doesn't have to be inside a while loop.  It's just that in the above example, it seemed to have made sense to put it inside one.

Believe it or not, but there's a hidden problem with the above code.  Can you guess what it is?  No? :)  Ok, I'll just tell you what it is.  :)

The "except" clause, as we have it, actually catches any and every kind of exception.  Even python syntax errors!! (Syntax errors is tech-speak for writing code that doesn't even make sense to the computer.  Yea, it's that bad.)  For instance:
What on earth is alsdfjalsdfj??? I don't know, and Python sure as hell doesn't know either!  Yet, because of our little "except" clause, you don't get to see that Python is very confused.  In fact, you get the "I said *number*... :)" printed on the screen instead.  Even when the user typed in a number!!  If you get rid of the "if-except" clauses, you would be able to see that this exception is raised:
NameError: name 'alsdfjalsdfj' is not defined
Basically, what happened is that even though you wanted to catch that the user didn't type in a number as expected, what you actually caught was your (or my, actually) programming mistake!

To avoid this mess, the better approach would be to do something like this:

Now, we're explicitly telling Python to only catch ValueError exceptions!  But, what is this thing, called "ValueError", you ask?  Well, you may have guessed that it's a name of a class!  And if that's what you guessed, well, you guessed right!  :)  Woohoo!

Assignment 8.9: write program that asks the user to type in a salary amount in dollars (int), and a tax rate (float) and prints out how much money she will have left over after taxes.  [Hint: A salary of $500 and a tax rate of 30.7% should leave you with 500 * (1 - 30.7 / 100) = $346.5]

Python gives you even more tools when handling exceptions, can you figure out what the following code does?

Type it in and play around with it a bit... See if you can get a feel for it.
Basically:

  • You can have more than one "except" clause, catching different exceptions.  In my example, I'm catching both ValueError and NameError exceptions.
  • except ... as... lets you actually get access to the object that is associated with the exception.  In our case, the class of exception caught is NameError, and the object with the actual error message is called e.  You can read more on this here.
  • raise is the way to generate exceptions.  In our case, we're just raising the same exception that we got!  Not very useful, since all we're doing is mocking the programmer.  Perhaps not useful, but definitely fun! :)  Again you can read on it more in here.
  • else can also be used with a try-except clause (that is, without an if!)  The code after the "else" only gets run if no exception was caught!
  • finally is used to run code at the very end, no matter if an exception was caught or not!  It's useful in order to perform "clean-up" tasks of sorts.  In our example, it was pretty much useless.
That's a lot of information all in one place!  I do recommend that you read more on exceptions here.  I just wanted to give you a taste for them.  In most cases, just using try and except is all you really need.

Out with the old, in with the new...

This is a bit random, but Python actually has two kinds of classes.  It's usually not very important, but I'm only telling you this just in case you bump into it one day.  The old classes is what I've been teaching you (sorry.)  The new classes are just like the old classes, but they derive from a class called "object" (or from another class that derives from object, etc. etc.), like this:

Fascinating.  I don't want to go into why this happened or why this is important. Most likely, it will never matter to you.  I just want you to be aware of this little issue.  But if you really care, you can read more about it here. Enjoy! :)

Minesweeper time!

Ok, so going back to your minesweeper game...  Is there anything from this lesson that you can incorporate into it?

The most obvious thing is the exception handling.  You definitely don't want the program to end just because the user had a typo.  So fix that.

But what about the whole inheritance business?  Mostly likely it will just add unnecessary complexity to your code.  Remember that keeping you code elegant is more important than making it fancy.  But, if in your mind using inheritance in Minesweeper can actually simplify your life, then go ahead and do it!  But don't feel that you must use inheritance in every programming project.  Heck, you don't even need to use classes, but it's more likely that you'll want to. :)

In the next lesson I'll talk about packages.  Packages are pretty easy to learn (at least in theory), and are a boat-load of fun!  They give you, the programmer, some real power to do some real things (like get stuff from the web.)  And in Python, it's all good and fun!  It's going to be an adventure, I promise! :)  Hold on tight...












Monday, July 15, 2013

PyTutorial: It's All About Class

This is the 7th in a series of posts.  If you want to go the the start, go here.

Classes are a great tool that help you organize your program better.  While functions helped you break up your program into goals and subgoals, classes help you break up your program into relationships.  Romantic, isn't it?

At its core, a class puts together pieces of information that relate to one another, as well as functions that act on that information.  BTW, for some reason, in tech-speak, functions that are part of classes are called methods.  The pieces of information that are contained in classes are called data members (and sometimes called attributes as well).

Let's take a look at some example classes:

The above four classes are independent of one another.  As you can see, each class contains some pieces of information, as well as some actions that the class can perform.  Of course, I just made these up off the top of my head, and clearly you can think of more information and actions that can belong in each class.
Assignment 7.1: Think of some more pieces of information and actions that the above classes can have.
Have you noticed an odd-ball in the crowed?  While Person, Car, and Bird contain very concrete information (first name, fuel capacity, color, etc.) the Game class contains abstract pieces of information (rules, board...).  At this point, abstract information isn't going to be very useful for us, but in the next lesson, I'll show you how abstraction can be very useful for classes.  For now, let's concentrate on the more concrete pieces of information.  Although Python doesn't let you explicitly state the types of variables, in a diagram like the one above we can specify the types of each information (just for clarity).  We can also give some more information on some of the class methods:

As you can see, "First Name" in the Person class is of type "str", while fuel efficiency is "float".  Also, Person's calculate Age method returns an 'int'.  Again, this isn't meant to be complete, just to give you a better idea of how classes organize information and actions.
Assignment 7.2: what are the relevant data types of the new information and actions that you came up with earlier?
Assignment 7.3: similar to the above examples, figure out what information and actions a "Bank Account" class could have. 
Assignment 7.4: can you think of any other classes?  What information would they have? What actions? 
One of the amazing things about classes is that they are, in essence, new data types!  While up to now, you were limited to working with integers, strings, lists, and maps, now you can create new data types (such as Person, Car, Bird, Game, etc.)  You can say that a variable, say, x, is a Person!  In tech-speak, you would say that x is an object of type Person.  But an object is just a fancy name for a variable.  Nothing more, nothing less.

Let's dive in!

Now that you have some background as to what classes are, let's take a look at how to use classes in Python:

Try taking a look at the code to figure out what it does.. And then, of course, type it in and see what happens!  :)

In this example, we've created a Person class, similar to the one in the examples above, but one that only has data-members (information).  Later on, I'll show you how to add methods (actions) to it as well.

So what's going on here? At first, we're defining a new "Person" class.  Similar to functions, when you define a class, nothing actually happens.  With functions, you have to call it in order to make it run, where as with classes, you have to instantiate it.  To instantiate is just tech-speak for creating an instance, or an actual copy with the relevant information, of that class.  BTW, in tech-speak, an instantiated container is called an instance or an object.  I'll use both terms here interchangeably. As a side-note, this is why working with classes is often called object-oriented programming.

In our example, such information includes "First_Name", "Last_Name", "Year_Of_Birth" and "Gender".  In order to tell Python that every Person object needs to have these four data members, we needed to write a special method called "__init__" (that's two underscores, "init", followed by two more underscores.)  Every class, no matter what it's called, should have such an "__init__" method.  The __init__ method tells Python how to construct a new Person object.  It is called whenever a new Person object is created.  Because it is used to construct new objects, in tech-speak, the __init__ method is also called the class's "constructor."

In our example, all the constructor does is create four variables, assigning None to each of them.   This isn't a requirement, of course.  You can have it start you with any values you wish!  To make these variables "belong" to the new object, you must prefix them with "self." (that's a "self" followed by a dot.)  But more on this later.  For now, just keep in mind that you need an __init__ method to create new objects.

You'll soon see how powerful and flexible classes actually are!  But first, I want you to notice that we actually created two instances (a.k.a. objects) of the class Person!  The first is p1, and the other is p2.  Both of them contain the same data members (i.e. First_Name, Last_Name, Year_Of_Birth, and Gender), but each contains different values for those data members.  Can you see that?

BTW, after running the above script, you can do stuff like this and see what happens:
>>> type(Person)
>>> type(p1)
>>> type(p2)
>>> print p1
>>> print p2
>>> id(p1)
>>> id(p2)

If you want to get rid of an object that you've created, just use the del keyword, which is the same way that you would get rid of any variable that you have:
>>> del p1
>>> print p1    # now you would get an error message, because p1 no longer exists!

I find it a bit strange that Person is of type "classobj", but such is life.  Don't be confused by it.  As I mentioned above, In tech-speak, classes are the general definitions, or "concepts", of how data-members and methods relate to one another, while objects are actual manifestations (with real information) of such general definitions.  In our example, the class is "Person", where as the objects are "p1" and "p2".

Of course, just like any other pieces of data, you can put objects inside lists and maps, like so:
>>> x = [3, "hi", Person()]
>>> x.append(p1)
>>> y = {"hi": p2}

etc, etc.  Pretty neat, eh? Play around a bit with classes, see what you can do.
Assignment 7.5: Similar to the Person class, implement the "Car" class.  At this point, as with the Person class, only write the code for the data members (forget the methods for now.)  Play with it a little, creating objects, and reading / writing values from their data members.
Assignment 7.6: Do the same for the "Bird" class.
Assignment 7.7: Also for the "BankAccount" class, and for the other classes that you came up with. 

Classes can contain objects

Now that you've seen how classes can group together pieces of information, you may wonder: is it possible to have one class contain objects of another class?  For instance, in the above sample classes, we have a Car class.  What if we want a Car to have an owner?  More specifically,  we may want that owner to be a an instance of the Person class!

Well, of course it's possible!  :) Not only that, it's possible for a class to contain instances of the same class!  For example, we may want a Person object to have a parent, which would also be an instance of a Person class!  Take a look:

 I've extended the above diagram to include in my classes references to other classes!  Specifically:

  • The Person class has parents and children (which is a list of Person objects), as well as a list of pet Bird instances.
  • The Car class has a Person owner, as well as a driver and passengers.
  • The Bird class can now poop on a Car class as well as on a Person class. :)
  • The Game class has a player of type Person. 
In Python, using instances of classes within a class is just like using any other variable:

Do you see how in my class definition, a person can have at most two parents, but an arbitrary number of children?  This has been a design choice, instead of having Parent1 and Parent2, I could have just as well had a list called Parents.
Assignment 7.8: change the Person class to have a list of Parents instead of Parent1 and Parent2.
Assignment 7.9: change the Car class to include Owner, Driver, and Passengers.
Assignment 7.10: modify the BankAccount class as well as any other class you came up with to include references to other objects.
Assignment 7.11: change the BankAccount class to support multiple owners (perhaps a list of such owners?)
Pretty neat, huh? :)

Python trusts you

Note that Python is very flexible in how it lets you write your code!  Nowhere in the code did I say that Parent1 must contain a Person object.  I just assigned it "None" at first, and later on, had the line:
>>> p3.Parent1 = p1

And since P1 was a Person object, all works as expected.  I could have wrote
>>> p3.Parent1 = "Dr. Doom"
or
>>> p3.Parent1 = 27

And Python would not have complained.  Python trusts you, the programmer, to know what you're doing. :)  Don't let it down. ;)
Assignment 7.12: Play around with the above example, mess around, go wild!
In fact, you can create data-members on-the-fly.  Just like when creating a new variable, all you need to do is assign a value to it.  Thus to create a new variable all you do is this:
>>> x = 37

The same goes for new data-members.  You can do something like this:
>>> p3.GrandMa = "Queen Elizabeth"

And later:
>>> print p3.GrandMa

Of course, if you never actually created the GrandMa data member, Python would give you an error message.  Try that as well.  Try something like "print p3.SomethingOrOther".

The main reason that I'm telling you all this is that with Python, you need to be very careful of typos.  For instance, if I did something like this:
>>> p1 = Person()
>>> p1.FirstName = "George"
>>> print p1.First_Name

I wouldn't get any error message, but "None" would get printed as the first name! (Instead of "George").  This is because of the typo that I have, inwhich I forgot to type in the underscore between "First" and "Name" in "First_Name".  Do you see that? Gotta watch out for stuff like this.  Python's incredible flexibiliy comes at a cost: you gotta make sure to tell it to do the correct thing!

Let's do stuff already 

OK! OK!  So far you saw the different ways that classes deal with information: that is, its data-members.  But remember that at the start of this tutorial I mentioned that classes also define the functions (a.k.a methods), that act on this information?!  Well, let's dive in!

Previously, we printed out the information about each Person object like this:
>>> print p1.First_Name, p1.Last_Name, p1.Year_Of_Birth

But say we wanted to write a "standard" way to print a Person object to the screen, we could do something like this:

There are a few key things that are going on here.  First, there's the method (basically a function) called PrintMe.  Notice that it's indented inside the Person class definition.  This makes it a part of the definition of the Person class.  Thus now PrintMe relates to the Person class.

Another key concept here is that the first parameter to any class method, in our case PrintMe, is always "self".  This is just a Python convention.  It could work just as well if instead of "self" you called it "this" (as is the case in the C++ programming language, btw) or "me", or "whatnot".  But please do the world a favor and stick with "self". :)   Did you notice that while we defined PrintMe to require 2 parameters (including self), when we called it, we only passed it 1 parameters?!  This is because "self" gets passed automatically, and is basically a reference to the actual object that PrintMe was called for. Thus in our example, when we run:
>>> p1.PrintMe("What")

"self" refers to "p1".  But, if later you do:
>>> p2.PrintMe("Not")

Then "self" refers to "p2".  Do you see that?

But why do we need this "self" parameter, anyways?  Well, using "self" lets your class method access the data members that belong to the object that its being asked to work on!  While in PrintMe we only accessed self.First_name once, when PrintMe() was called by "p1.PrintMe(...)", it accessed p1's data members.  But later, when it was called by "p2.PrintMe(...)", it accessed p2's data members.  That's what I mean by classes letting you write functions that act on its related information. 

This hidden parameter "self" is what makes class methods different from regular functions.  Every time a class method is invoked (gets called), Python passes to it as a first parameter the reference to the object that called it!

Because a class method always gets the "self" parameter as its first input parameter, even if you want to write a class method that doesn't require any input parameters, when you define it, you still need to include the "self" parameter.  For instance, if you wanted to modify PrintMe() so it doesn't need a title, you can do something like this:
Now you can call it without passing it any input parameters, like this:
>>> p1.PrintMe()

Do you see that?  Try it!
Assignment 7.13: add a class method to Person that only prints the first and last name of the object.  Call it, PrintName.
So far, we only read the values of the data members from within the class methods.  But what if we want to change them?   Well, that's really simple:

Assigning a value to self.Last_Name changes the value of the object's (the one that "self" refers to) "Last_Name" data member.  Thus we can do something like this now:
>>> p1.ChangeLastName("Kennedy")
>>> p1.PrintMe()

Nice! :)
Assignment 7.14: add a class method to Person that changes the person's first name. Call it, say... ChangeFirstName.  :)
Assignment 7.15: modify ChangeFirstName so that it prints to the screen the previous first name as well as the new one.  It should print something like: "Changing the first name from xxx to yyy".
Assignment 7.16: modify ChangeFirstName yet again to check to see whether or not the new first name is any different from the one at hand.  If it's the same, it should print a message such as "New first name is the same as the old, not changing anything".  If it's different, then it should print what you printed before:  "Changing the first name from xxx to yyy"
Just like regular functions, class methods can return values using the "return" keyword.
Assignment 7.17: write a class method, "GetYOB" for the Person class, that returns the Year_Of_Birth of the particular object.
Were you able to figure it out? It's pretty straight forward.  Well <SPOILER ALERT>, in case you didn't, it should look something like this:

Pretty simple, huh?  And to use it, all you need to do is something like this:
>>> print p1.GetYOB()

That's all there's to it, really!  Now it's your turn:
Assignment 7.18: add a class method, call it "GetAge", that returns that person's age.  (You can assume that today is 2013, or whatever this year is...)
Very good.

Why so special?

Remember our little constructor, __init__?  Let's get back to it now.

One of the first things that you want to do with a new object (of just about any class) is actually give it some information to work with.  In our Person example, we did stuff like this:
>>> p1 = Person()
>>> p1.First_Name = "Elvis"

But this is a bit problematic.  Why?  Well, working this way leaves the p1 object in an incomplete state.  At first (right after the p1 = Person() line), all its data members are "None".  What kind of person is that? Doesn't make much sense to me either.   But even after the next line, we get a Person object with partial information: it only contains a first name, and nothing else!

This is considered bad style, because it leaves your objects in confusing states.  Wouldn't it be nice if we could give all the required information right when we instantiate our object?  How about something like this:
>>> p1 = Person("Elvis", "Gato", 1987)

Well, as you have probably expected, classes let us do exactly that! :)  Check this out:

There are a few key things that are going on here.  First, there's our special method (basically a function) called __init__.  What makes__init__ so special is that unlike regular class methods, this one isn't called directly!  Nowhere in the code do you see something like this:
>>> p1.__init__("Jonathan", "Gandi", 2002)

Instead, it gets called behind the scenes whenever you create a new object, like this:
>>> p1 = Person("Jonathan", "Gandi", 2002)    # actually calls __init__!!!

As with any class method, the first parameter to __init__ is always "self".   And as usual, I hope that you noticed that while we defined __init__ to require 4 parameters (including self), when we created a new object, we only passed it 3 parameters?!  As before, this is because "self" gets passed automatically, and is basically a reference to the actual object that is being created.  Thus in our example, when we run:
>>> p1 = Person("a", "b", 2)
"self" is the new object that is being created, and is later assigned to "p1".  But if later you do:

>>> p2 = Person("c", "d", 7)
Then "self" is another object being created, and gets assigned to "p2".  Do you see that?


Note that I have the arrow pointing from self to p1.  This is because self is first created right before the constructor gets run (behind the scenes).  Also note that the constructor doesn't "return" anything, yet p1 gets the value of self (the new object.)  This is another special feature of the constructor: it never returns anything, yet a new object is returned!

For the record, the parameter names "fn", "ln", and "yob" are completely arbitrary.  In fact, you can have them have the same names as the class's data member, and it would still work just fine:

Try it!  As usual, Python can figure out what you want to do based on the "self" parameter.  It knows that when you do something like "self.First_Name" you want to access the object's "First_Name" data member, while if you just do plain "First_Name", you want to access whatever variable (in our case, it's the function's input parameter) is named "First_Name".  Do you see that?  Play around with the above example and see what happens.
Assignment 7.19: modify the above program to print the id of self, and compare it with the id of p1.  Do you see how they're the same?
Also, try running something like this now:
>>> p2 = Person()

You should get an error because now that you defined __init__, creating a Person object requires that you pass it the required parameters.   As mentioned earlier, besides the hidden "self" parameter, class methods are just like any old function, and thus can be defined with default argument values or keyword arguments.

In a nutshell, default arguments let you specify default values for function parameters.  For example, if you had a function:
>>> def myfunc (a, b, c):
...

and you wanted c to be 42 by default, you can define it like so:
>>> def myfunc (a, b, c=42):
...

now, the caller can call myfunc with or without providing a value for c:
>>> myfunc(1, 2, 3)    # c gets the value 3
>>> myfunc(1, 2)        # c gets the value 42

Keyword arguments let you be more explicit when you call a function, especially if it has many default arguments.  Instead of relying on the parameter position in that function's definition to pass in a value, you tell Python explicitly which parameter gets the value by giving its name. With myfunc as defined just above (with the default argument for c), you can do:

>>> myfunc(1, 2, c=3)    # being explicit that c gets 3
>>> myfunc(a=1, b=2, c=3)  # explicit about all of them
>>> myfunc(1, b=2, c=3)   # explicit only about b & c
>>> myfunc(c=3, a=1, b=2)   # with keyword arguments, the order doesn't matter.

Typically, though, keyword arguments are only used with parameters that have default values, as they are not always required.  Look over the Python docs again to review both default arguments as well as keyword arguments.  See how they work for regular functions, and then apply them to your Person class.
Assignment 7.20: change Person's __init__ method so that "yob" can be an optional parameter, that it, it has some default value.  HINT: its default value should be "None".  Now try calling it with no year of birth, or with one as a keyword parameter.  
That was fun, wasn't it?

A nice trick that you can do with classes is define another special method: "__str__".  Doing this lets your code become a little more elegant when printing the object to the screen.  For instance, wouldn't it be nice to be able to do something like this:
>>> print "person 1=", p1

Well, you can already do that!  Try it!  The problem is that you get something UGLY.  And of course, we want something pretty! :)  So let's define __str__() to help us:

Now you can do something like "print p1" and it should have nice results!  (Try it!)

If you want to make it print something even fancier, you can have it take advantage of the GetAge() method that you wrote as an exercise:

Do you see how here, we're using self to call another method of the same class?  That is, the line:
age = self.GetAge()
Calls GetAge() on the object that self is referring to.  Thus if we're doing "print p1", then it calls the GetAge() on p1's information.

Here's a little challenge:
Assignment 7.21: add a method to Person, call it "SetAge", that given the age (not birth year) of a person, it modifies the Year_Of_Birth.  (Again, you can assume that this is 2013 or something).

Sometimes it's better to work a little harder...

Say you wanted to change the first name of p1.  You can easily achieve this by assigning a value directly, like this:
>>> p1.First_Name = "Foozie"

That's all good and fun, so long as you know what you're doing.  But what if you wanted to have better control in your object?  Say you only wanted to allow a name that is made of all letters?  Or you wanted to make sure that the first character is capitalized?  In that case, you need to have greater control over how First_Name is assigned a value.  That is normally achieved by writing a simple "helper" method that sets the value appropriately.  In the most simple case, we would write:
class Person:
    ...
    def SetFirstName(self, new_value):
        self.First_Name = new_value
    ... 
On the one hand, this may seem like useless extra-code.  But the moment you want to place certain checks and limitations on First_Name, this function becomes quite handy.  Because now all you have to do is change this function to make sure that First_Name only gets assigned appropriate values (for instance, that the first letter is capitalized, etc.)  If you're used to directly assigning values to the data members, you may have a harder time fixing your code. 
Assignment 7.22: add a SetFirstName() method to Person that takes in a string as an input parameter (as well as self, of course), and sets the First_Name to that value.  No special check. Hint: that's pretty much what I just showed you... :)
And now comes the fun part:
Assignment 7.23: modify SetFirstName() to make sure that the first name is at least 2 characters long.  If it's not, just return from the method without changing First_Name.
Assignment 7.24: again modify SetFirstName() to make sure that the first name only contains letters.  HINT: you can go through all the characters in the string by doing something like "for c in s:"
I can keep going here, but you get the hint. :)  Accessing the object's data members using Get...() and Set...() are just good habits to get into.  This is especially true when working on a project with other people.  It gives you more control (and flexibility) over how an object is manipulated.  As in the SetFirstName() example, writing "set" and "get" functions give you an opportunity to monitor and manipulate desired changes to your object.  Of course, sometimes you don't need to do this, especially when you have full control of the data input, and you pretty much know what you're doing.  But when writing more complicated code that depends on user input, this is usually a good idea to go this way.

And now it's time for some bigger challenge!  (HURRAY!)

Below is an incomplete class definition for a car (based on the car example from earlier on).  I did you the little favor of writing the constructor for you, as well as providing you with empty methods that you should fill with actual code.  Note that sometimes I had to use the keyword pass, which basically does nothing at all, just because Python requires something to exist inside a function, even if it's just the keyword pass.  :)

But before going through the details, let's think about what is a car?

Well, a car may have a make, model, etc.  But it may also have a certain fuel capacity, fuel efficiency, and distance traveled.  Using the American system, I'll call these gallons, miles per gallon, and mileage. :)  I sincerely apologize to the rest of the world.  All these are information about a car.  But what can a car do?  Well, a car can drive, right?  And when it drives, it uses fuel as well as increases mileage!  Another useful thing that a car can do is fill up gas.  Since the information about a car as well as what it does all relate to each other, we can put them together inside a single class, like so:

Assignment 7.25: complete the Car class.  That is, implement all the required class methods. :)
Assignment 7.26: I have owner just be the name of a person.  Can you modify it so that the constructor accepts as its first parameter (besides self) a Person object?
Assignment 7.27: I've left out who the driver is and who are the passengers in the car, add them in now. 
Assignment 7.28: now implement the Bird as well as the BankAccount classes (include their methods) 

The classes that you've always known...

Remember lists, and how you can do stuff like:
>>> mylist = []
>>> mylist.append(34)

Now think about the above car example, and how you can do:
>>> mycar = Car(...)
>>> mycar.fill_up(20)

Looks rather similar, doesn't it? 
A little too similar? :)

Well, it should!  That's because in Python, everything is some sort of class!  It's just that to make things more readable for the eager programmer, Python has some special syntax (the way the code is structured) for some built-in classes!  These not only include lists and maps, but also numbers and strings!  That's why you can do things like:

>>> s = "hello"
>>> better_s = s.capitalize()
>>> print better_s

Try it!  capitalize() is just a method that belongs to the string class!  The string class has many more little methods that you can use.  In fact, you can read all about them here!  lower(), find(), and replace() are all pretty useful.  Read about them and try them out!  

Even numbers are classes!  Actually, they only have one method, and it's not very useful, but it's a class nonetheless. Since you're just dying to know, well, you can do something like this:
>>> x = 20
>>> print x.bit_length()

Which will tell you how many bits, or the smallest, most basic type of information that a computer works with (usually represented as a "0" or "1"), are required to represent the given number (in our case, 20).  I'm not sure why you would need this, but it's there!  In fact, if you want to see the bit representation of the number 20, you can do this:
>>> print bin(20)

Lovely, isn't it?

But going back to the issue at hand, everything in Python is a class, and thus has class methods and data members that are used to make it work.  Neat, huh?  

The class ecosystem

In any real piece of software, you're going to have a bunch of classes that relate to one another.  You got a sense of how this works with some of the above examples.  For instance, a Car class had a data-member, owner which was of the Person class.  Let's go over a few case-studies to see more ecosystems in action:


The above describes a very simple text editor.  One that is implemented using only three classes!

The main class here, which is also the simplest, is the "Text Editor" class.  It keeps a list of open documents, and one active document.  It also lets the user create a new document as well as close an opened one.

The "Doc" class here is a container for an actual document.  It has a file name, an author, as well as some relevant dates.  But the most important piece of information here is the Content data-member, which is basically a list of "Char" objects (more on them soon.)  The Doc class also lets the user save the document, and of course type in a character ("Add Char") as well as delete a character ("Remove Char").

At the core of this text editor is the "Char" class, which describes a single character in a single document.  It has the character itself ('a', '3', '?', ' ', or what not...), as well as information about its size, font, and whether or not its bold or italicized.  You can imagine that this isn't a very efficient text editor, as every single character that the user types requires a lot of describing information.  

I didn't go into the mechanics of actually displaying the document here.  But in theory, the Char class can have a display method that displays that particular character to the screen.  This would let us have another display method, but one that is part of the Doc class, which would go through all the characters in its Content and call their display method, kind of like this:

Let's look at a more complicated example:
Here are some of the classes that can be used in a program that manages a very simple bank. :) 

Our simple bank consists of customers and employees, nothing more!  In it, we can manage (add/remove) our customers and employees.  But our bank also has some routine tasks that it needs to take care of.  For example, every day, the bank has to pay the relevant interest in all its accounts.  Also, every month, the bank needs to charge the monthly fees to the accounts, as well as pay the monthly wages.  Once a year, the bank needs to send a "thank you" letter to its customers, as well as build a yearly financial report.

To keep the Bank class's methods simple, they can take advantage of the functionality that the other classes offer!  For instance, our Employee class deals with salary and bonus payments.  Our Customer class deals with mailing statements and thank-you letters.  Each Customer instance also has a list of Account instances that deal with interest payments, monthly fees, and deposits / withdrawals. 

Finally, we have a "Contact Information" class, which is used by both the Employee and the Customer classes.  This class is responsible for making sure that the relevant address / phone numbers are valid.

Obviously, there's a lot more work that just that's involved in running a bank.  But these classes can give you an idea of how to organize the various pieces of information and actions that relate to each other.

Notice that we have a two-way dependency here: Customer objects contains Account objects, and Account objects contain a Customer object!  In essence, I have duplicated the one piece of information on which account belongs to which customer.  The reason I did this here is that it simplifies both figuring out which accounts any given customer has, and also who owns any particular account.

This approach, however, has one huge drawback: if, for some reason, a particular account changes ownership, then both the relevant Customer object as well as the relevant Account object need to be modified.  Otherwise, you get a data-integrity problem, because you have the same piece of information in two different places contradict each other!

It's not always obvious how to solve this problem.  One clear solution is to chose between either having Account objects in Customer objects, OR having Customer objects in Account objects, but not both.  Although it sounds simple, actually writing code with such restrictions in place may end up complicating matter much more than simply duplicating the information.   Fortunately, this is a very common problem, and there are tools out there to help us deal with it (namely database and their various object wrappers, but that is for another day.)  For now, just keep in mind of the issue of duplicating information, try to avoid it, but when that's too complicate, be aware of its pitfalls and make sure that your code is correct.

I've created a sample implementation of the above banking ecosystem classes.   Check it out to see how the above can be implemented in code: banking.py (in HTML).  Can you think of ways to extend it?  Or test it further?

In our final example, let's describe the classes that involve in setting up a Skype-like client (that is, the software that is installed on its users computers, not at the company's main servers.)


Our simple Skype-like program is made up of four classes.  The main class manages the whole interaction with the end-user: it enables log-in/log-out capabilities, address book management, and starting / ending chats and calls.  

It has the information on which user is currently logged in, as well as that user's address book.  It also needs to keep track of current chat and call sessions.

Both the currently logged in user as well as her address book information is managed by the Account class.  The Account class describes an account's username as well as her display name.  It also keeps track on whether a particular account is currently online or offline.

The two remaining classes, Chat and Call, manage actual chat and call conversations.  You can see that while a Chat can be with multiple other participants, a Call can only have one person on the other end.  You can also see some of the relevant class methods that would be required.

One potentially "stinky" issue here is that the Skype class is very heavy.  It's responsible for doing a lot of things, a lot of them having nothing to do with each other!  This may be a sign that we need to break it up into a bunch of simpler classes, perhaps into something like this:
Now all that the Skype class is responsible for is log-in/log-out functionality.  It has three new manager classes that help it manage the address book, chats, and calls.  Although we have way more classes now, each class has a clearly defined role, and all the information / actions that they contain actually do relate to each other!  I like this solution much better!

Can this get any better?

Surprisingly enough, it sure as heck can!  But I'm going to leave that for the next lesson :)

For now, I want you to appreciate how classes let you define the relationships between pieces of information and the methods that act upon them.  This capability enables you to organize your code in much smarter ways.  Instead of having a bunch of variables and a bunch of functions that act on them, with no obvious hint as to which functions relate to which variables, classes let you put all the relevant parts of the code into nice groups known as classes!

To get you thinking more about things this way, try implementing the following classes:
Assignment 7.29: write a class for the rectangle shape.  What should its data members be?  Besides its constructor and __str__(), what some of its methods be?  (I can think of area and perimeter calculations, but can you think of anything else? How about a method that returns True or False depending on whether or not the rectangle is also a square?)
Assignment 7.30: write a similar class for the circle shape.
Writing a similar class for the triangle is more challenging.  If you're not good with geometry, you can skip this one.  On the other hand, if you like geometry, can you figure out what its constructor should be to guarantee that such a triangle actually exists?  What should its data members and methods be?  If you need to calculate the sinus or cosine, you should use Python's built-in math library (more on this later).  But just so you can write the class, you can do something like this:
>>> import math
and then:
>>> x = math.sin(2)
>>> y = math.cos(2.3)
etc.   You can read about the complete list of geometrical functions here.

But on to different kinds of classes...
Assignment: can you think of a computer class?  What would be its data members?  What are some simple things that you can do with a computer?
Assignment: how about a balloon?  You can fill it, but has it popped? :)
Assignment: write a class for a wallet that contains money. 
Assignment: how about an item in a grocery store?  What can be its data members?  What can be its methods?  (How about whether or not it expired?)
Assignment: how about the grocery store itself?  I can imagine it having an inventory of items.  Perhaps ItemInventory should be a class on its one?  One that contains a list of similar items, and can tell you how many non-expired ones exist, or let you throw away all expired items, etc.  Then the grocery store can have a list of ItemInventory objects, one for each kind of item in the grocery store.  At least this is how I'm imagining it.  Can you implement a grocery store like this or in some other fashion that makes sense to you?
Assignment: now have a person class, one that has a wallet class.  Add a method to the grocery store that takes in a person, and tries to make a purchase of some sorts.  This may get a bit complicated, but don't lose heart.  I'm not trying to get you to actually write some important grocery store code, just to better get a feel for how classes interact with each other.  The specific details are less important here.
Can you think of any other classes that you can implement?  Go ahead and play with classes for a while... In the next lesson, I'll show you some more crazy stuff that you can do with classes.....  :)

Did you think I forgot about Minesweeper?

I don't think so.

Although in this lesson I didn't teach you anything that would change the way the player interacts with the game, I did teach you some new ways that you can organize your code!  Can you think of how you can re-write Minesweeper in an object-oriented manner?

What classes would you have in there?
How would they relate to one another?
What data members and methods would each class have?

Think about it.

There's no single "right" way to organize your code.  Ultimately the way you organize it has to make sense to you.  Here are some ideas that I have for organizing Minesweeper into classes:
  • You can have a cell class.  What would its key data members and methods be?
  • How about grid class? 
  • Does a gameplay class make sense?  One that would be responsible for getting user input, and putting together various parts of the game?
Again, think about the way to organize the game that makes the most sense to you.   I recommend that you first write draw a high-level view of the various classes that you want to have (similar to the diagrams at the start of this less.)  Then drill down and add some details by writing an outline of the classes that you want to have (similar to what I did in the Car class example above.)   You don't have to do this, but it's just a way to get you thinking about the different classes, what they do,  and how they interact with one another.  Go ahead and try it!

Now that you have an outline of the classes that you want, go ahead and try to "fill them up" with code!  This shouldn't be sooo bad since you already have all the code in functional form.  You just need to make little adjustments to it so it'll work in the object-oriented way of thinking.  

Were you able to do it?

What do you think?  Compare your code that uses functions with the one that uses classes.  Do you like the way classes help organize your code?    :)