Monday, April 22, 2013

PyTutorial: Playing with Information

This lesson is a  continuation of the previous lesson, PyTutorial: Intro to Programming.   Here you will actually start programming, playing with information in various ways.  Enjoy!

So let's get started with programming!  First, you should download Python to your computer.

Strangely enough, there are two competing versions of Python:  the old and the new.  While the new version is where the language wants to go, it's not quite there yet.  The older version of the language is much better supported.  They're very similar actually, and for many things you wouldn't be able to tell the difference.  In this tutorial, I'll be using the older version (that is, Python 2.7), so please use that one when working with my examples.  If, later, you will want to switch over to the newer version (that is, Python 3.3), well, I sure as heck won't try and stop you.  But I just want to make it clear that in this tutorial, I'll be working with Python 2.7, so this is what you'll need to be using as well.
If you're running windows 32-bit, go here, but if it's windows 64-bit, then go here.  If it's anything else, then go here and figure it out. :)

You should see "python-2.7.4.msi" downloaded on your computer.  Click on it, and install it by clicking "next" "next" "next"....  Mazal-Tov! Now you have Python on your computer!

To Run it, click on "Start" --> "All Programs" --> "Python 2.7" -->  "IDLE (Python GUI)"

You should now see something like this:

That's Python's interactive shell.  It's not the way "real" programs are written (more on that soon), but it's a good way to get a feel for and learn new programming ideas.  It's something that stays useful even after one learns to program... Well, let's get started!

Type in "3+4" and press <Enter>.   (Really, try it, don't just read what I'm writing, it's important.)  What do you see?

You should see something like this:

What you're seeing is the number 7.  It's pretty clear what happened: Python figured out that 3+4 is 7.
Do you remember that in the previous page, I mentioned that all that programs do is deal with information and actions?  Well, here we have just such an example: 3 & 4 are two pieces of information (numbers), and the program performed an action on them (addition), resulting in a new piece of information: the number 7.

Seriously, that's what programs do.

What do you think will happen if you type in: "3 * 4", or "8 / 2", or "128 - 23"?  Try it!
Assignment 2.1: play around a bit, try things like "3 * (7 + 2)" and "5 + 2 * 3", etc.  
 You should notice a few things
  • Python behaves like most calculators that you know.
  • Spaces are not important.  That is, "3+2" is the same as "3     +     2", etc.
Now try something like "4 / 3".  What do you get?
Did you get 1?  Why is that?  What did you expect to get?  
Doesn't 4 / 3 equal 1.3333333333333333..........?    Why did Python round it to 1?

Even worse, try 5 / 3!  What do you expect to get now?  5 / 3 equals, after all, 1.666666....
So if Python rounds the answer, it should be 2, right?  Well, what do you get?

Again, you get 1!!!  Aaaaarrrrrgf!!!!1!111!!  :)

Chill out, my good friend.  There is reason behind the madness.  Let's take a look at what's going on:
For starters, it should be clear that Python is working with whole numbers. So 5 / 3 becomes 1, which is OK.  But why isn't 5/4 rounded to 2?  The reason is that Python doesn't round the numbers, it just "gets rid" of the fraction part...  So 5 / 4, which is really 1.666666.... simply becomes 1.  Simple, eh?

But what if you don't want to work with whole numbers?  What if you want to work with real numbers? Well, it's pretty easy, but you need to tell Python that this is what you want.  To do it, you need to type in a number with a period in it, like "4.0" or "4.7234" or whatever.  Even "0.0" works.

For instance try "3.0 / 4.0".  What do you get?  You should get "0.75".  Great!
What about "1.0 + 3.0 * 2.0"?  I hope you got "7.0".

Now try "2.0 / 3.0".  What do you expect to get?  The real answer is 0.6666666666666666666666666666666666666666666666666666666666666666666........... for ever and ever and ever...

But what you actually get is: 0.6666666666666666.  And that's it.  No more, no less.
Why is that? Now is the time to remember the previous page, in which I mentioned that computers are limited in memory.  It's due to this limitation that 2.0 / 3.0 is computed to 0.6666666666666666 and nothing more.  More precision requires more memory, and 14 decimal places seem to be "good enough" for most things.  If you need more precision, of course it's possible to achieve with computers, but it will require more memory, of course.  For now, let's assume that the precision you get is good enough, and work with it.  Most likely, you'll never need more precision than that anyways.

BTW, have you tried to do something bad with this?  And by bad, I mean really bad...  Yea, I mean try to divide by zero!  HA!  Type in "7 / 0".  But step back from the computer when you do, because who knows what may happen?  HA HA HA!!!

So, what did you get?  Did you get something like this:

Well, don't look at me!  You're the one who tried to do the impossible!  An attempt to divide by zero raises an error, or an exception, as they call it in programming.  We'll talk more about this later, but it's good to know that the world won't end even when you divide by zero. :)

Put this number somewhere, please!

So far we played around with numbers, but now let's do something more with them.  Type in:
"x = 7"  What do you get?  Nothing, right?   Now type in "y = 8".  Still nothing... 

But happens if you type in "x + y".  WOA!!  Definitely something! :)
You can also do things like "z = x + 2 * y".  Nice, eh?

If you want to see the value that "z" has, just type in "z".
You can also type in "print z", which does the same thing.  Try it!
Well, what's going on here?  What is the meaning behind "x = 7" or "z = x + y"?
Well, remember that computers deal with information and actions on information?  Well, "=" is just another action.  By typing in "x = 7", you're telling the computer to take the number 7 (information) and assign it (action) to a variable x (information).  Variables are just places to store information.  You call them whatever you want, and the program will behave exactly the same.  They're for your convenience, and trust me, they're very convenient!
Assignment 2.2: play around with wacky variable names.  Go nuts!  Try "zoolan" and "my_nose_is_flute" and "z4"...  really, go wild here!  But whatever you don't, don't name your variable "Ido".  The computer will crash.  Trust me.
BTW, did you notice that not all names work in Python?  For instance, if you try to create a variable that starts with a number, like 2muchfun4me, well, it won't work.  There are other little restrictions, but you should be able to come up with a variable name that works. ;)
A little side note:
Want to know what value something has? Well, go ahead and print it!  As you go through this lesson and others in this tutorial, make use of the print command to your heart's delight in order to get a better understanding of what's going on in the code.  Really, print is your friend.  Of course, in the interactive python mode (what you're doing now), just typing in "z" is almost the same as typing in "print z" (I'll tell you about the differences soon).  But when you write "real" code (in a file, I'll show you how very soon), just typing in "z" won't do much, and to see what z contains you'll have to type in "print z".  This is why I write "print" this or "print" that in this tutorial.  But if you're using the interactive shell (as you are doing now), then you can just type in the variable name, and it should work just as well.

But regardless if you "print" something or just type in the variable's name in the interactive interpreter, you should use print whenever you're unsure about something.  In fact, you should play around and try different things until you really get what's going on.  Playing around like this is very important when learning to program, because although there is theory behind programming, practice really does make the difference.  Plus, it doesn't cost you anything!  So go ahead and experiment, trying whatever's on your mind!  This is your chance to be young again. :)

But are numbers the only pieces of information that you can deal with?

HECK NO!

Try typing in:
>>> x = "hi"
(note that you don't actually type in the >>>, it's just to make it clear what to type, because there are quotes in what I want you to type, and asking you to type in "x = "hi"" can be rather confusing.)

So anyways, type it in.  Now type in "print x".  What do you get?  Nice, eh?
Now type in:
>>> y = "there"

and now  "z = x+ y".  Strange?  What's in "z" now?  What do you expect to see?
Well, how do you find out?  That's right, type in "print z" and find out!

WHOA!  Nice, huh?  Python added "hi" and "there", and gave you "hithere".  Yup, programming is awesome.

There is more than one way to refer to text in Python, all are the same:
>>> a = "hi"                          # double quotes
>>> b = 'hi'                           # single quotes
>>> c = """hi"""                     # three consecutive double quotes

Why have three ways to do the same thing? And what's up with the pound sign, # (or hashtag for all the youngsters out there)?  Whoa! One thing at a time here, please!
The three ways to quote is just for convenience.  For instance, what if you want to quote: let's go.  See, there's a single quote in there, so to quote it, it's easier to use the double-quote, like so: "let's go".  Easy.
But let's say you want to quote: she said "hi"
Then, using the single quotes is easier, like so: 'she said "hi"'
[Note that right after the double quote, there's a single quote up there]
And if you want to quote both kinds of quotes: let's say "hi"
Then, using the three consecutive double-quotes is easier: """let's say "hi", ok?"""
[Again, note that after the double-quote, there are three double quotes for a total of four double-quotes in a row]
Assignment 2.3: play around with the three different kinds of quotes, assigning them to variables, and printing them using the "print" function.
Have you noticed that if you do something like this:
>>> x = """let's say "hi", ok?"""
Then typing in "x" gives you different results than typing in "print x"?  If you have't, try it now. :)
The reason for the difference is a bit technical, and not super important, but I'll tell you anyways (because I'm so kind.)

"print x", displays the value of x to the screen, which is pretty much what you expect to get in our case.
Just typing in "x" prints the representation of x to the screen.   The what? The representation.  Basically, it prints to the screen a more detailed value of x, similar to what you would have to type in in python to get the value of x.  Think of the representation value as containing all the technical information that is relevant, or what a computer would expect to see, while "print" gives you what a human would expect to see.

But wait!  There's more!  As I said, the three types of quotes are for your convenience, you don't actually need all three types.  You can get along with one, any one, just fine, but you need to escape strange characters.  For instance, you can do:
>>> a = "she said \"hi\""
>>> b = 'let\'s go!'
etc. etc.
In fact, Python makes it nicer for you.  After typing the above commands, try this:
>>> b
>>> print b

You see what happened?
Assignment 2.4: play around escaping quotes a bit.  You'll learn to like it.
But wait! There's even more!  You can escape even more strange characters, like <ENTER> and <TAB>.
<ENTER> is escaped using \n, and <TAB> using \t, like so:
>>> c = "hi there\nvery nice\tof\tyou to join me\n  great!"
>>> c
>>> print c

See?  Do you see c?  Nice.
Assignment 2.5: play around with the \n and \t escapes.  You'll learn to love it.
Don't think I forgot your question about the pound sign, #.  Remember?
>>> a = "hi"                          # double quotes

Everything after the # is a comment, meant for people to read.  Python completely ignores everything past the # (until the end of the line).

BTW, what is the difference between 3, 3.0, and "3"?  
>>> a = 3
>>> b = 3.0
>>> c = "3"

Well, 3, or "a", is a whole number, or an integer in programming-speak.  3.0 is a rational number, or a float in programming-speak.  And "3" is plain and simple text, or string in programming-speak.  Why are they called what they're called?  Beats me, ask the programming-speak god.  :)

But don't trust me!  Find out for yourself by typing:
>>> type(3)
>>> type(a)
>>> type(3.0)
>>> type(b)
>>> type("3")
>>> type(c)
etc. etc.  See!!  I'm not making these things up!  But what is this "type" thing? And the parenthesis?  These are called functions, but more on those later.  For now, just notice how you can ask the computer about the type of particular information, or variables, just by typing in "type(...)".  And if I use the word "type" one more time I'll go crazy.

Now, just to be mischievous, try to type in:
>>> 3 + "hi"
and 
>>> "hi" - "there"

You should have gotten some more exceptions.  That's because python doesn't know how to add an integer with a string.  Perhaps you know how, but Python doesn't.  Python also doesn't know how to subtract one string from another string.   Such is life...

Lists galore!

As you can guess, you can also keep lists in Python.  Try:
>>> x = [3, 5, 2, 9]
>>> type(x)
>>> x[0]
>>> x[1]
>>> x[0] + x[1]

WOA!  Pretty neat eh?
how about:
>>> len(x)
>>> y = len(x)
>>> print y
>>> print y + x[2]
>>> print y + x[2] * x[3]

Incredible, just incredible.  Isn't it? :)
Did you figure out what happened here?

Let's review:
  • You can create a list by using the square brackets: [...] Each item in the list is separated by a comma.
  • To access something, an item in the list, you need to give the index number of the item that you want.  Index numbers, strangely enough, start at zero, yes zero, and no, not one.  Why?  Just because.  Just because.  So, say you have a list called listlist.  Say, you created it by typing in "listlist = [4, 2, 9]".  Now, if you want the first item in the list, what do you do?  Well, the first index number is zero, so you need to type in, again, using square brackets: listlist[0].  Yup, it's that easy. To get the second item in the list, you need to type in: listlist[1].  Easy!
  • if you want to know how many items are in the list, just type in "len(<your list>)":  len([2, 5,2,43]) or len(listlist), etc.
BTW, you can use len with text as well. Try this:
>>> len("hello")
>>> len("")
>>> len("i like blue cheese.")

Can you access the last item in a list?  Of course! Say you have the list:
>>> x = [3, 5, 2, 9]

If you do:
>>> len(x)
You get 4, because it has four items, duh.  But how do you access the last item in the list?  Remember that you need to give the index number, which starts at zero.  So in our case, the fourth item has an index number of 3.  Can you think of how you can use len(x) to access the last item in the list?   Try this:
>>> i = len(x) - 1
>>> i

Now you have a clue?  You can do something like this:
>>> x[len(x) - 1]

It's a bit ugly, but it works.  How about the second-to-last item?
>>> x[len(x) - 2]

Get the idea?  
Assignment 2.6: access the third-to-last item in list x
Assignment 2.7: multiply the third-to-last item in list x by 2!   
But in Python, there's an easier way to do this.  To access the last item of list x, you can use a negative index value, like this:
>>> x[-1]                                   # access the last item in list x
>>> x[-2]                                   # access the second-to-last item in list x

Much nicer, huh?  What will these do:
>>> x[-4] * 3
>>> x[-3] * x[1]

BTW, lists are variables just like integers and strings above.  In fact, they can be combined.  Can you guess what this results in:
>>> x = 3
>>> y = "hi"
>>> z = [x, y, 77]
>>> print z

What happens is that the variable z is assigned a list with three items: the first item is the value contained in x (3), the second is the value contained in y ("hi"), and the third is just 77.  Thus z is assigned the list [3, "hi", 77].  If after creating the above list z, you modify the value for x or y, z remains the same:

>>> x = 99
>>> print z

You still get [3, "hi", 77].
Assignment 2.8: assign some numbers and strings to some variables, and then create a list using those variables.

I'm tired of using IDLE and all the ">>>", I want to program like a BOSS!

Ok, I feel that perhaps now is a good time to move on and up to better things.  Yes, you'll come back to IDLE and all the ">>>" because it's awesome, but for now, let's write a real program, from beginning-to-end:  
  • In the IDLE menu, choose "File", and then "New Window":
  • An empty, "Untitled" window should appear.
  • In the menu, choose "File" and "Save"
  • Save it somewhere.  Call it something.  Make sure that that something ends with a ".py".  For instance, call it "awesome.py" or "not_awsome.py" or "balloon.py"... You get it.  But save it somewhere where you'll actually remember where to find in the future.  Otherwise, you'll feel like a loser.  Trust me.
  • Now, type code inside it, just like you would in IDLE, but now there's no ">>>" to guide you along:
    x = 3
    y = x * 8
    print y
  • etc. etc.
  • Press <Control-S> to Save.
  • Press <F5> to run it.  If you typed in what I wrote above, you should see something like this:

Can you guess what happened?  Go ahead and guess, I won't judge your dumbness.  Really, I can't even hear your thoughts, so go head and guess!  GUESS ALREADY!  Great!  Now you see, you were wrong.  And that's ok.  
This is what happened:
What you wrote happened.  One line after the other, really fast!  Really really fast!  One could say "computer fast" even.  It's like magic, huh?  Play around, writing different things in there, and press <F5> to run.  It's neat.  It's even neato.  It's programming.
Assignment 2.9: Create a new file, call it "clouds.py", in it, assign the number 30 to x, and the number 20 to y.  Now, have z be x multiplied by y.  Print the value of z.  Great.
Now go back to IDLE, I want to should you something cool.  You can do neat stuff with "print":
>>> yy = 38
>>> print yy
>>> print "yy =", yy
>>> print "i love peanuts"
>>> print "i eat peanuts", yy, "times a day!"

Nice, huh?  You can do more with print, but that's good enough for now.
Assignment 2.10: Modify "clouds.py" above to print a funny message relating to z.  It's really fun, I know.
Assignment 2.11: Now modify "clouds.py" to have the message actually be funny.

 Back to lists, and all the cool stuff you can do with them!

I hope you didn't forget about our good lists.  Before, we created a list of whole numbers, or integers, like so:
>>> somelist = [2, 5, 2 ,6]

But as you probably have guessed, we can do more.  Much more.  Try this:
>>> x = ["hi", "there", "world"]
>>> y = [3, 6.2, 9.34]
>>> z = ["hi", 3, 2.9343, "wow", "yup, you can put a comma here", "nice list, eh?"]

What will x[1] give you?  How about y[0], and finally, what about z[4]?
Assignment 2.12: play around with lists.  Create a list with 10 items in it.  Create a list with different things in it. 
Yes! You can even have lists of whatever you want, even lists of lists, like so:
>>> xx = ["hi", 3, [5, "there"], 8]
>>> yy = [33, 5, "lala", [3, "bibi", [3, 5.3, 2, "mimi"], 3, [3, 5], [2, 5], 3], "howdy!", 3, 5]

wow!
What will xx[1] give you?  How about xx[2]?
What about xx[2][0]?
What the heck is xx[2][0]?  

Let's figure out, together, what xx[2][0] is.  
xx[2] should be pretty clear by now: it returns the third item in the list, known as xx. In our case, the third item in xx is another list, one without a name, but one which contains the following two items:
[5, "there"]

Is that clear so far?  Kind of?  Great!  It can be a bit confusing, I know.  But just keep in mind that computers are simple, and do what they're told.  Using the square brackets tells the computer to access some item in some list, whatever that may be.   xx[0] accesses the first item (the string "hi", in our case), xx[1] accesses the second item (the integer 3, in our case), and xx[2] access the third item (the list [5, "there"], in our case).  That's all.  Simple.  Powerful, but simple.

So now that we figured out xx[2], can we figure out what xx[2][0] does?
xx[2][0] tells the computer to perform two actions in a row: first, access the third item in list xx, and then, access the first item in that list.

Check out this example:

>>> a = xx[2]
>>> print a
>>> b = a[0]
>>> print b
>>> print xx[2][0]

Do you see how xx[2][0] is the same as b?  Very nice.

Of course, you can't use [] when it's not appropriate.  What do you think will happen if you do:
>>> print xx[1][0]
Try it!

You should get an exception, something like: TypeError: 'int' object has no attribute '__getitem__'

Why did you get that?  Well, what is xx[1]?  In our example, xx[1] is the integer 3.  When you typed in xx[1][0], you basically asked for the first item in the integer 3.  Integers don't have item, but lists do!

For kicks, what do you expect to get when you do:
>>> xx[0][0]

? Another exception.  NO?!  You got the letter 'h'?
Why was that?  Well, it turns out that strings do have items. In English, these items may be called letters, but in computer-speak, the more generic term, characters, is used
Assignment 2.13: using yy from above, figure out, in your head, what the following results in.  Then try it in IDLE to see if you were right:
yy[1], yy[2], yy[2][1], yy[3], yy[3][1], yy[3][2][3][1]
Truly wonderful, indeed.

You can also modify lists.  For instance, say you have the list:
>>> zz = [5, 3, 2]

As you know, the second item in the list, or zz[1], is the number 3.  Say we want it to be the number 9, instead?  We can do the following:
>>> zz[1] = 9
>>> print zz
>>> print zz[1]

See how zz now contains the values [5, 9, 2]?  We can also add an item to the end of the list, or append an item:
>>> zz.append(22)
>>> print zz

Now zz has the items [5, 9, 2, 22].

We can also delete an item.  Say we want to delete the second item in the list, we can do it like this:
>>> del zz[1]
>>> print zz

Now zz has the items [5, 2, 22]

You can create an empty list like this:
>>> zz = []
Assignment 2.14: play with lists.  Create new ones that have values, or new empty ones.  Access different values, modify values, and delete values...

 Is there anything more amazing than lists?

Hard to imagine, but yes, there is.  And it's called a dictionary, or in computer-speak, a map.  I'll show you what I mean:
>>> aa = {"hi": 7, "there": 3.2, 99: "blue"}
>>> print aa["hi"]
>>> print aa["there"]
>>> print aa[99]
>>> print aa

>>> print len(aa)
>>> print type(aa)

Did you see what happened? If you typed it in, you should have, if you didn't, then you should be punished.  Type it in already you big loser!  Notice that to create a list, you need to use the squiggly-brackets {}.

See?  Nice, huh?  But let's take a closer look at what happened.

Maps are basically a look-up table that contain key-value pairs of information.  To get access to the value part of the information, the key needs to be given.  When creating maps, the keys are what goes before the colon, while the value is what goes after the colon.  In our example, the map aa has three keys: the string "hi", the string "there", and the integer 99.  Each key is matched with a value.  In our case, "hi" is matched with the number 7, "there" is matched with 3.2, and 99 is matched with "blue".  It's that simple.

But wait!  While we typed in:
>>> aa = {"hi": 7, "there": 3.2, 99: "blue"}
When we did "print aa", we got:
{'there': 3.2, 99: 'blue', 'hi': 7}
For some reason, the order of the key/values got moved around?!!  Yup. This happens not in order to confuse, but because with maps (unlike with lists), the order of the key / value pairs are irrelevant.  In maps, a value is associated with a particular key, not with a particular location as in a list.  Because of this, Python is free to order the keys in maps in a way that will make your code run as fast as possible.  If, for some reason, you want a dictionary that maintains the order that the keys were inserted, well, python has something called an OrderedDict that you can use, but don't worry about this for now.

I keep mentioning that one needs to use the key in order to gain access to its matching value.  Well, to actually do this, we use the square brackets, like this:
>>> print aa["hi"]
Accesses the value that matches the key "hi", or in our case, the number 7.

Just as in lists, you can change and delete map values:
>>> aa["hi"] = 9
>>> del aa["hi"]

You can create an empty list, like this:
>>> aa = {}

Maps are a little more restricted than lists.  Although you can have any value that you want, you cannot have lists as key.  You can have something like a list, called a tuple, but that's for another time.  For now, remember that you can do things like this:

To create a dictionary that contains lists, you can do this:
>>> aa = {"hi": [3, 5, 6], "there": [6, 2, 4]}
>>> print aa
>>> print aa["hi"]
>>> print aa["hi"][1]
>>> print aa["there"][1]

You can also create a list that contains dictionaries:
>>> bb = [{"hi": 3, "there": 8}, {"me": 2, "you": 9}]
>>> print bb
>>> print bb[0]
>>> print bb[0]["there"]
>>> print bb[1]["you"]

Here's some more practice:
>>> aa = {"hi": [3, 5, 6], "there": [6, 2, 4]}

What will this print:
>>> print aa["hi"]

How about now:
>>> aa["hi"] = [3, 5, 2]        # aa is a dictionary that contains a list for the key "hi"
>>> print aa["hi"]
>>> print aa["hi"][1]

How about these:
>>> aa["hi"] = [3, 2, [6, 2], 3]               # aa is a dictionary that contains a list that contains a list
                                                             # for the key "hi"
>>> print aa
>>> print aa["hi"]
>>> print aa["hi"][2][1]

You can even have dictionaries that contain lists that contain dictionaries that contain lists....
>> aa["hi"] = [6, 2, {99: [2, 5, 6], 18: [2, 3, 1]}, 7, 3, {"hi": 77}, 8 ]
>> print aa

Can you figure out what this will print:
>> print aa["hi"][2][99][1]

It's tough, you need to be very careful as you go through the information.
Assignment 2.15: access the value 77 (the value for the key "hi" towards the end) in aa.
Assignment 2.16: create a dictionary, cc, that contains a few keys, two of them being lists. Access the items in the lists.
Assignment 2.17: create a list, ll, that contains a few items, two of them being a dictionary.  Access the values in the dictionaries.
As you work with maps, keep in mind that the keys need to be unique.  That is, two keys can't be the same.  Just like every word in the dictionary is different. On the other hand, values can be the same:

>>> b = {}
>>> b["hi"] = 3
>>> b["there"] = 3                     # OK to have two identical values, so long as the keys are different
>>> b["there"] = 4                     # because the key "there" is already used, the computer will modify
                                                  # its value from 3 to 4.

Assignment 2.18: play with dictionaries.  Create new ones with values, or empty ones.  Access values, modify values, and remove values. 

A little something about how Python deals with variables...

Python deals with variables in ways that may not be completely intuitive, but it's important that you are aware of as you play around with the language.  In most cases, what I'm about to show you doesn't make a bit of a difference, but sometimes, you may encounter things that may seem plain bizarre if I didn't show this to you.  So I'm going to go into something that may be a bit technical, but may come in handy one day.  Less important than memorizing the details is to understand that this is going on...

Say you do something like this:
>>> x = 3
>>> y = x
>>> print "x=",x, "y=",y

What do you expect to see happen? If you expect to see something like: x=3, y=3, then you would be right! :) But why?  Or more precisely, what what happens when you do "y = x"?  Intuitively, you may think that y gets a copy of the value in x.  But sorry, that's not what really happens.  Instead, y is used to represent the exact same piece of information as x!  Or in tech speak, y gets a reference to x.

In python, every piece of information, whether an integer, string, map or a list (or anything else, actually), gets an ID number! (It's all very official...) You can even see that ID, by doing something like this:
>>> x = 3
>>> y = x
>>> z = 7
>>> print id(x), x
>>> print id(y), y
>>> print id(z), z

You can see that x & y have the same ID, while z has a different one!  That's because while y was assigned a reference to x, z was assigned a whole new piece of information! These references aren't set in stone, in fact, you can easily de-reference a variable by simply assigning to it something else!  For example, you can do something like this:
>>> x = 3
>>> y = x
>>> y = 2
>>> print id(x), x
>>> print id(y), y

Now they have a different ID!  Even if instead of "y=2" you wrote "y= y * 2", you would get assign a new piece of information, and thus get a new ID!

Sometimes, you can get strange surprises, try this:
>>> x = 3
>>> y = 3
>>> print id(x), x
>>> print id(y), y

What do you expect to see?  Well, because the number 3 is just that, the number three, unchanged and everlasting, Python treats it as one piece of information, and thus x & y get the same ID!

Now, while with numbers and strings, all modifications give you a new ID, and thus nothing really unexpected happens, with lists and maps, this isn't the case!  You can modify a list and still have the same ID.  This is because, as far as Python is concerned, the list is still the same list, but now has different items.  Check this out:

>>> x = [1, 2, 3]
>>> print id(x), x
>>> x.append(7)
>>> print id(x), x

See, x has the same ID!  If, instead of doing "x.append(7)" I would have done "x = [1, 2, 3, 7]", then although the value of the list would have been the same, the ID would be different.  That's because I'm actually assigning x a new list, instead of appending a value to an existing one.  A bit tricky, but you'll get the hang of it.  Now look at this:

>>> x = [1, 2, 3]
>>> y = x
>>> print y
>>> x.append(7)
>>> print y

What do you expect to see happen?  Think about it.  First, y gets a reference to x.  Then x is modified, that is its ID remains the same.  As long as x and y refer to the same ID, any changes to x affect y, and and changes to y affect x, because, well, they're the same thing!  Thus later, when I print y, I get [1, 2, 3, 7], even though I appended a value to x!  See that?  A bit unintuitive, but that's how it works.

Why??  Well, a very fair question! There are a few reasons for this, but by far the most important one is that computers have time and space limitations.  Copying a reference is usually much more efficient than making a copy of the whole value.  Especially when talking about large lists and maps.  For now, this seems like overkill, especially with what we're doing with lists and maps thus far.  But you got to think big, and theoretically, you can have lists that are just plain HUGE.  Being able to assign references to them becomes very important.   You will see this when I show you how to work with functions and objects, but for now, you'll just have to take my word for it (and quietly suffer). :)

Assignment 2.19: figure out what the above does, and why on earth, why?!
Assignment 2.20: change the above code to actually append different values to y. 

Let's get started with Minesweeper!

As with most programming tasks, information plays a key role in how the software gets developed.  Minesweeper is no exception.  Using what you've learned in this tutorial, try to come up with different ways that you can represent the core data of the game:
  • Each cell on the grid either has a mine or not.  Think of different ways that you can represent this information (of a single cell) in a variable.  Which way makes the most sense to you?
  • A user can mark each cell s "flagged".  This is the user's way to mark a cell that she thinks has a mine in it.  Can you think of different ways to represent this information as well?  
  • Finally, each cell can either have been clicked or not.  Clearly, if a cell that has a mine has been clicked, the game has been lost.  But that's not important to us now.  We just want to be able to know whether or not a particular cell has ever been clicked.
  • How would you combine the above three pieces of information for a single cell? 
Of course, the actual game grid is actually made up of many different cells.  It may comprise of, say, 4 rows containing 5 cells each, for a total of 20 cells.  But we're not going worry about all that for now, I just want you to think of a single cell.  But as an extra challenge, can you think of how to organize a single row of cells?  Perhaps a row that contains 5 cells?

By the way, can you think of any other pieces of data that you may care about?  How about a high-score? Can you think of a good way to represent that?

There you have it!

In this tutorial, you were introduced to some useful ways to organize information in Python.  Information is probably the most important aspect of programming.  In fact, there are entire technologies, called databases, that are dedicated to help programmers organize and manipulate information.   These databases can be accessed using Python or just about any other programming language.  

In the next section, I'll go into more actions that computers perform on information.  Information and actions, put together, make up the core of programming!  Seriously, you're half way there!

Other aspects of programming help you organize your program.  This is important as well, and very powerful, but it builds upon the core of programming that you are learning in this and the next section.

I would say that the final aspects of programming are social in nature: how to work in a team, how to be clear and understand one another, as well as how to work in a way that will systematically create higher quality code.  

For now, play with what you learned in this section.  Try to get comfortable manipulating information in Python.   Good luck!

To continue to the next section, go here.

Want another riddle?

This one is pretty self-explanatory, good luck:

[       { 'start': 0, 'count': 3, 'text': 'Helvetica' },
        { 'start': 3, 'count': 2, 'text': 'jello' },
        { 'start': 2, 'count': 4, 'text': 'be there' },
        { 'start': 1, 'count': 5, 'text': 'are lively today...' },
        { 'start': 2, 'count': 2, 'text': 'bitter herbs' },
        { 'start': 2, 'count': 4, 'text': 'file right' },
        { 'start': 6, 'count': 5, 'text': 'the chain clock' },
        { 'start': 0, 'count': 4, 'text': 'loud and clear!' }     ]


No comments:

Post a Comment