[20:00] <ClassBot> Logs for this session will be available at http://irclogs.ubuntu.com/2010/10/09/%23ubuntu-classroom.html following the conclusion of the session.
[20:01] <pedro3005> Hello folks
[20:01] <pedro3005> Anybody out there?
[20:01] <pedro3005> erm
[20:01] <pedro3005> my fail
[20:02] <pedro3005> ok, I'm in -chat now
[20:02] <pedro3005> Alright, let's begin
[20:03] <pedro3005> Last class we were talking about functions and list comprehension
[20:03] <pedro3005> now these are difficult subjects
[20:03] <pedro3005> I gave some examples but I realized they might've been unclear
[20:04] <pedro3005> Functions are used a lot in programming
[20:04] <pedro3005> List comprehension isn't used as much, but it still is used not rarely
[20:05] <pedro3005> The purpose of functions is simple
[20:05] <pedro3005> When we are doing one procedure over an over, we can direct it to a function to avoid code repetition
[20:06] <pedro3005> For instance, suppose we are coding a little greeting program, which talks to the user
[20:07] <pedro3005> the user gave you his name, something like "Mr. H" or "Mrs. K"
[20:07] <pedro3005> Now, suppose you have many lines which are oriented by gender
[20:08] <pedro3005> before each of these lines, you are doing:
[20:08] <pedro3005> if name.startswith("Mr."):
[20:08] <pedro3005> bla
[20:08] <pedro3005> To avoid all this code being repeated over and over, you might use... functions!
[20:09] <pedro3005> as we learned last class, you can define a function with the keyword def
[20:09] <pedro3005> All functions return a value
[20:09] <pedro3005> but some functions return Null
[20:10] <pedro3005> Functions may or may not receive parameters, which are kind of like informations about the things it's supposed to do
[20:10] <pedro3005> In our case, it makes sense that our function receives as a parameter the name of the person
[20:11] <pedro3005> So it can determine the person's gender
[20:11] <pedro3005> Enough talk, let's get dirty
[20:12] <pedro3005> >>> def gender(name):
[20:13] <pedro3005> ...     if name.startswith("Mr."):
[20:13] <pedro3005> ...             return "male"
[20:13] <pedro3005> ...     elif name.startswith("Mrs."):
[20:13] <pedro3005> ...             return "female"
[20:13] <pedro3005> ...
[20:13] <pedro3005> you can observe it returning
[20:13] <pedro3005> >>> gender("Mr. Rob")
[20:13] <pedro3005> 'male'
[20:14] <pedro3005> Now, let me share a dirty little secret with you
[20:15] <pedro3005> In this function, we're just assuming the parameter <name> is a string
[20:15] <pedro3005> what happens if we call it with an integer, for instance?
[20:15] <pedro3005> >>> gender(2)
[20:15] <pedro3005> Traceback (most recent call last):
[20:15] <pedro3005>   File "<stdin>", line 1, in <module>
[20:15] <pedro3005>   File "<stdin>", line 2, in gender
[20:15] <pedro3005> AttributeError: 'int' object has no attribute 'startswith'
[20:16] <pedro3005> But, worry not, my lad
[20:17] <pedro3005> You, sir, are the programmer
[20:17] <pedro3005> You know better than to pass an int into your function expecting a string
[20:17] <pedro3005> But you must be careful with user values
[20:17] <pedro3005> If the user typed a value, you should NEVER assume it is what it's meant to be
[20:17] <pedro3005> We've discussed that previously, I just wanted to stress it again
[20:19] <pedro3005> We can also have functions with no parameters
[20:20] <pedro3005> As an example, we have the print_help function
[20:20] <pedro3005> Our program could have a help message
[20:20] <pedro3005> and we want to create a function to display it
[20:20] <pedro3005> But I don't really have any parameters, I just want the damn thing to print it
[20:20] <pedro3005> >>> def print_help():
[20:20] <pedro3005> ...     print "rtfm"
[20:22] <pedro3005> You may ask: what does this function return?
[20:22] <pedro3005> I didn't tell it to return anything
[20:22] <pedro3005> Well, we can tru to assign it to a variable
[20:23] <pedro3005> try*
[20:23] <pedro3005> >>> a = print_help()
[20:23] <pedro3005> rtfm
[20:23] <pedro3005> >>> print a
[20:23] <pedro3005> None
[20:23] <pedro3005> You can note that the function returns None
[20:24] <ClassBot> TrueCryer45 asked: None as value? not Null?
[20:24] <pedro3005> Yeah, I got the name wrong on the first time
[20:24] <pedro3005> :P
[20:24] <pedro3005> It's None
[20:25] <ClassBot> matematikaadit asked: none is none
[20:25] <pedro3005> >>> None is None
[20:25] <pedro3005> True
[20:25] <pedro3005> does that answer your question?
[20:26] <pedro3005> We also talked about the scope of functions
[20:26] <pedro3005> A function has its own scope of variables
[20:27] <pedro3005> for instance, if you declare a variable inside a function, it doesn't exist outside that function
[20:27] <pedro3005> if you declare variables outside the function, you can access the variable from within the function, but you cannot change it (unless if you call it global)
[20:27] <pedro3005> let's go over that
[20:28] <pedro3005> >>> def a():
[20:28] <pedro3005> ...     n = 1
[20:28] <pedro3005> ...
[20:28] <pedro3005> >>> a()
[20:28] <pedro3005> >>> n
[20:28] <pedro3005> Traceback (most recent call last):
[20:28] <pedro3005>   File "<stdin>", line 1, in <module>
[20:28] <pedro3005> NameError: name 'n' is not defined
[20:28] <pedro3005> Here, we can clearly see the effects of this
[20:28] <pedro3005> n is not defined outside the function
[20:29] <pedro3005> >>> n = 1
[20:29] <pedro3005> >>> def a():
[20:29] <pedro3005> ...     print n
[20:29] <pedro3005> ...
[20:29] <pedro3005> >>> a()
[20:29] <pedro3005> 1
[20:29] <pedro3005> here, we show that you can access the variable even though it wasn't defined in that very function
[20:29] <pedro3005> >>> def a():
[20:29] <pedro3005> ...     n = 2
[20:29] <pedro3005> ...
[20:29] <pedro3005> >>> a()
[20:29] <pedro3005> >>> n
[20:29] <pedro3005> 1
[20:30] <pedro3005> But here, you see that you cannot change n
[20:30] <pedro3005> When you try to define a new value to n, you are actually creating a new, different n
[20:30] <pedro3005> this n exists only inside a()
[20:30] <pedro3005> when you get out of that function
[20:30] <pedro3005> there is another n
[20:30] <pedro3005> which is still 1
[20:30] <pedro3005> it was not changed
[20:31] <pedro3005> We can use the global keyword to identify it as a global variable
[20:31] <pedro3005> >>> def a():
[20:31] <pedro3005> ...     global n
[20:31] <pedro3005> ...     n = 2
[20:31] <pedro3005> ...
[20:31] <pedro3005> >>> n = 1
[20:31] <pedro3005> >>> a()
[20:31] <pedro3005> >>> n
[20:31] <pedro3005> 2
[20:31] <pedro3005> Are we clear on this, everyone?
[20:34] <pedro3005> Good
[20:34] <pedro3005> Let's introduce a new subject then
[20:35] <pedro3005> Named parameters
[20:35] <pedro3005> this is useful for holding default values
[20:36] <pedro3005> for instance, suppose you have a help function
[20:37] <pedro3005> if you call that with a certain command, it displays help about the command
[20:37] <pedro3005> if you call it by itself, it displays a general help message
[20:37] <pedro3005> we can accomplish this with named parameters
[20:38] <pedro3005> >>> def p_help(command=None):
[20:38] <pedro3005> ...     if command == None:
[20:38] <pedro3005> ...             print "general help message"
[20:38] <pedro3005> ...     else:
[20:38] <pedro3005> ...             print "specific help about %s" % command
[20:38] <pedro3005> ...
[20:38] <pedro3005> >>> p_help("ls")
[20:38] <pedro3005> specific help about ls
[20:38] <pedro3005> >>> p_help()
[20:38] <pedro3005> general help message
[20:39] <pedro3005> if you don't pass anything, command gets the default value of None
[20:42] <pedro3005> >>> def p_help(command=None, detailed=None):
[20:42] <pedro3005> ...     if command == None:
[20:42] <pedro3005> ...             if detailed:
[20:42] <pedro3005> ...                     print "detailed general help message"
[20:42] <pedro3005> ...             else:
[20:42] <pedro3005> ...                     print "general help message"
[20:42] <pedro3005> ...     else:
[20:42] <pedro3005> ...             if detailed:
[20:42] <pedro3005> ...                     print "detailed help message about %s" % command
[20:42] <pedro3005> ...             else:
[20:42] <pedro3005> ...                     print "help message about %s" % command
[20:42] <pedro3005> ...
[20:43] <pedro3005> >>> p_help(detailed=True)
[20:43] <pedro3005> detailed general help message
[20:44] <pedro3005> So as you see in this last function, you can use named parameters to only pass a certain value to the function
[20:44] <pedro3005> Any questions?
[20:45] <ClassBot> OttoBusDriver asked: Can you call functions with named parameters with positional paramters? EG p_help('command', True)
[20:45] <pedro3005> Yes
[20:45] <pedro3005> >>> p_help("ls", True)
[20:45] <pedro3005> detailed help message about ls
[20:46] <ClassBot> OttoBusDriver asked: And can you define a function with positional and named parameters?
[20:46] <pedro3005> didn't we just do that?
[20:46] <pedro3005> def p_help(command=None, detailed=None):
[20:48] <pedro3005> Good
[20:48] <pedro3005> It seems we are all clear on this subject
[20:48] <pedro3005> Let me see if there's anything more of functions I should go through today
[20:50] <pedro3005> Oh yes
[20:50] <pedro3005> this looks hard but it is actually quite easy
[20:50] <pedro3005> Python has a shortcut for easy, one-expression functions
[20:50] <pedro3005> if you have a function that just grabs a value x and adds 2, for instance
[20:50] <pedro3005> or grabs the value x and calls some_random_function(x)
[20:50] <pedro3005> you can use lambda expressions
[20:51] <pedro3005> >>> a = lambda x: x + 2
[20:51] <pedro3005> >>> a(40)
[20:51] <pedro3005> 42
[20:52] <pedro3005> lambda of x is x + 2
[20:52] <pedro3005> the syntax is a bit different from the def keyword
[20:52] <pedro3005> you must assign it to a variable, as you see
[20:52] <pedro3005> the x is actually the parameter
[20:52] <pedro3005> not the function's name
[20:52] <pedro3005> lambda expressions can take in multiple parameters
[20:53] <pedro3005> >>> a = lambda x, y: x + y
[20:53] <pedro3005> >>> a(2, 3)
[20:53] <pedro3005> 5
[20:53] <pedro3005> >>> a = lambda x=1, y=2: x + y
[20:53] <pedro3005> >>> a()
[20:53] <pedro3005> 3
[20:53] <pedro3005> >>> a(2)
[20:53] <pedro3005> 4
[20:53] <pedro3005> And you have named parameters with lambdas ^
[20:54] <pedro3005> Lambda comes from functional programming, which (obviously) bases itself heavily on functions
[20:54] <pedro3005> so it was needed to create a shorter path to small functions
[20:54] <pedro3005> thus lambda
[20:55] <pedro3005> It's not used much outside of FP (functional programming), but I wanted to go over it because FP knowledge is important to any decent programmer
[20:55] <pedro3005> Any questions?
[20:57] <pedro3005> Alright
[20:57] <pedro3005> this is it for functions
[20:57] <pedro3005> I mean, there is more to it, but I think I have explained most of it
[20:58] <pedro3005> you should play with functions, use them in your programs, get used to them
[20:58] <pedro3005> they are really important in programming
[20:58] <pedro3005> Also reference to last class where I explained functions as well
[20:58] <pedro3005> (to find out that a function can receive another function as argument)
[20:59] <pedro3005> But let us continue on exploring data structures
[20:59] <pedro3005> We've been talking about lists
[20:59] <pedro3005> they are ways of sequencing things
[20:59] <pedro3005> you can create a list for instace
[20:59] <pedro3005> instance*
[21:00] <pedro3005> numbers = [1, 2, 3, 4, 5]
[21:00] <pedro3005> And we went over various things you can do with lists
[21:00] <pedro3005> grab elements
[21:00] <pedro3005> numbers[0] being the first
[21:00] <pedro3005> put in new elements, with numbers.append(6) or numbers.insert(0, 0)
[21:00] <pedro3005> (insert 0 at the position 0)
[21:01] <pedro3005> http://docs.python.org/tutorial/datastructures.html#more-on-lists
[21:01] <pedro3005> those are all the methods you have with lists
[21:01] <pedro3005> I want to go over a new type today
[21:01] <pedro3005> it is called a dict
[21:01] <pedro3005> short for dictionary
[21:02] <pedro3005> let's think about real dicitonaries
[21:02] <pedro3005> they have a word and a definition
[21:02] <pedro3005> so they are kind of like mapping tools
[21:02] <pedro3005> they link one thing to another
[21:02] <pedro3005> in our case, a word to a definition
[21:02] <pedro3005> In python, we have that
[21:03] <pedro3005> we have dictionaries that map a string to an object
[21:03] <pedro3005> but get this
[21:03] <pedro3005> everything is an object
[21:03] <pedro3005> a fuction is an object, a list is an object, they're all objects
[21:03] <pedro3005> so a dict maps a string to pretty much anything
[21:03] <pedro3005> let's go over the syntax
[21:04] <pedro3005> imagine you have three users, Rob, Joe and Max
[21:04] <pedro3005> and they have user ids of 1, 2 and 3 respectively
[21:04] <pedro3005> let's create a dictionary which maps user to user id
[21:05] <pedro3005> users = {"Rob":1, "Joe":2, "Max":3}
[21:05] <pedro3005> Notice we use {}
[21:05] <pedro3005> We can access an element of this dict by calling: users["Rob"]
[21:05] <pedro3005> that will return 1
[21:06] <pedro3005> because Rob is mapped to 1
[21:06] <pedro3005> >>> users["Rob"]
[21:06] <pedro3005> 1
[21:07] <pedro3005> Questions?
[21:07] <pedro3005> Good
[21:08] <pedro3005> In Python terms, "Rob", "Joe" and "Max" are keys of the dict users
[21:08] <pedro3005> And how do you get all the keys in users?
[21:08] <pedro3005> >>> users.keys()
[21:08] <pedro3005> ['Max', 'Rob', 'Joe']
[21:09] <pedro3005> But hey, wait a minute!
[21:09] <pedro3005> I put in Rob _first_
[21:09] <pedro3005> Why did I get Rob in second?
[21:09] <pedro3005> What the hell is python thinking?!
[21:09] <pedro3005> It's simple
[21:10] <pedro3005> they're random
[21:10] <pedro3005> You see, Python doesn't guarantee that your dict will be in the order you left it
[21:12] <pedro3005> The function of dicts is to relate string to anything
[21:12] <pedro3005> and that function is kept
[21:12] <pedro3005> I think python 3 will have ordered dicts
[21:12] <pedro3005> or was that 2.7?
[21:12] <pedro3005> not sure
[21:12] <ClassBot> matematikaadit asked: is it possible a key related to nothing?
[21:13] <pedro3005> well, sure
[21:13] <pedro3005> but in python we call nothing None :)
[21:13] <pedro3005> >>> a = {"a": None}
[21:13] <pedro3005> >>> a["a"]
[21:14] <pedro3005> Questions?
[21:14] <pedro3005> Good
[21:16] <ClassBot> matematikaadit asked: users.keys() is for calling the key, how about the value?
[21:16] <pedro3005> As TrueCryer45 lovely pointed out, users.values()
[21:16] <pedro3005> You can use the method .has_key() to check if a dict has a certain key
[21:16] <pedro3005> >>> users.has_key("Rob")
[21:16] <pedro3005> True
[21:17] <pedro3005> example:
[21:17] <pedro3005> >>> if users.has_key("Rob"):
[21:17] <pedro3005> ...     print "Rob is here. His ID is %s" % users["Rob"]
[21:17] <pedro3005> ...
[21:17] <pedro3005> Rob is here. His ID is 1
[21:18] <pedro3005> Here we are mapping a string ("Rob", "Joe", whatever) to an int (1, 2, 3 ..)
[21:18] <pedro3005> But who's to say we can't map strings to lists, for instance?
[21:18] <pedro3005> We can!
[21:19] <pedro3005> >>> boxes = {"box1": ["a key", "an old cd"], "box2": ["three coins", "a phone"]}
[21:19] <pedro3005> >>> boxes["box1"][0]
[21:19] <pedro3005> 'a key'
[21:21] <pedro3005> Hell, we can map strings to functions, other dicts, other dicts that have dicts within them, other dicts with dicts with dicts within..
[21:21] <pedro3005> in short, we can map strings to practically anything
[21:21] <pedro3005> with dictionaries
[21:22] <pedro3005> What if we wanted to print each user's name and id?
[21:22] <pedro3005> We need to iterate over this dict
[21:22] <pedro3005> we would use a for loop (I hope you all remember the for loop class)
[21:23] <pedro3005> >>> for user, id in users.iteritems():
[21:23] <pedro3005> ...     print user, id
[21:23] <pedro3005> ...
[21:23] <pedro3005> Max 3
[21:23] <pedro3005> Rob 1
[21:23] <pedro3005> Joe 2
[21:23] <pedro3005> now, let's analyze that
[21:24] <pedro3005> do you guys remember tuples? they we're like (1, 2)
[21:24] <pedro3005> sort of like lists
[21:24] <pedro3005> I taught that we could unpack these tuples into variables
[21:24] <pedro3005> x, y = (1, 2)
[21:24] <pedro3005> x = 1 and y = 2
[21:24] <pedro3005> this is exactly what happens in the for loop
[21:25] <pedro3005> the function returns something like ('Max', 3)
[21:25] <pedro3005> and it's unpacked into user and in
[21:25] <pedro3005> id*
[21:25] <pedro3005> then we print these
[21:25] <pedro3005> Questions?
[21:27] <pedro3005> Ok, good
[21:28] <pedro3005> Now
[21:28] <pedro3005> Let's turn our attentions to something more tangible
[21:28] <pedro3005> Hang in there guys
[21:28] <pedro3005> we're nearly getting over the basic python
[21:29] <pedro3005> Programs usually have a functionality of reading and writing to files
[21:29] <pedro3005> so let's learn how to do that in python
[21:29] <pedro3005> All this time, you've been reading and writing to files and you didn't know it
[21:30] <pedro3005> print "bla"
[21:30] <pedro3005> this writes "bla" into the file stdout
[21:30] <pedro3005> which in our case is the terminal
[21:30] <pedro3005> when you call raw_input() you're reading from stdin
[21:30] <pedro3005> how cool is that?
[21:30] <pedro3005> When we change to other files, it's not much different
[21:31] <pedro3005> We use the open() function to open a file
[21:32] <pedro3005> We do it like this:
[21:32] <pedro3005> f = open("some_text_file")
[21:32] <pedro3005> notice that we didn't define a mode here
[21:32] <pedro3005> by default, it is in reading mode
[21:32] <pedro3005> that is equivalent to
[21:33] <pedro3005> f = open("some_text_file", "r")
[21:33] <pedro3005> now you can do things with f
[21:33] <pedro3005> for instance, let's read our file
[21:33] <pedro3005> f.read()
[21:34] <pedro3005> this returns a string with the entire file
[21:34] <pedro3005> it will not remove newlines ("\n") etc
[21:34] <pedro3005> Let me quote the python docs
[21:34] <pedro3005> To read a file’s contents, call f.read(size), which reads some quantity of data and returns it as a string. size is an optional numeric argument. When size is omitted or negative, the entire contents of the file will be read and returned; it’s your problem if the file is twice as large as your machine’s memory. Otherwise, at most size bytes are read and returned. If the end of the file has been reached, f.read() will return an emp
[21:34] <pedro3005> ty string ("").
[21:37] <pedro3005> You may call f.readline() to read just one line
[21:37] <pedro3005> and you can iterate over the file
[21:38] <pedro3005> >>> for line in f:
[21:38] <pedro3005> ...     print line
[21:38] <pedro3005> ...
[21:38] <pedro3005> this
[21:38] <pedro3005> is
[21:38] <pedro3005> a
[21:38] <pedro3005> file
[21:39] <pedro3005> iterating over f will give you line by line
[21:39] <pedro3005> Questions?
[21:41] <pedro3005> Good
[21:41] <pedro3005> Writing to files is just as easy
[21:41] <pedro3005> Open it in "w" mode
[21:41] <pedro3005> f = open("some_file", "w")
[21:41] <pedro3005> and then call write()
[21:41] <pedro3005> f.write("blablabla")
[21:42] <pedro3005> when you're done, don't forget
[21:42] <pedro3005> f.close()
[21:42] <pedro3005> remember that you must call write with a string
[21:42] <pedro3005> so imagine you have
[21:42] <pedro3005> answer = 42
[21:43] <pedro3005> you can't do
[21:43] <pedro3005> f.write(answer)
[21:43] <pedro3005> because answer has type int
[21:43] <pedro3005> convert it to string
[21:43] <pedro3005> f.write(str(answer))
[21:44] <pedro3005> There are more methods to files
[21:44] <pedro3005> these are the most used
[21:44] <pedro3005> http://docs.python.org/tutorial/inputoutput.html#methods-of-file-objects
[21:44] <pedro3005> I recommend you read this
[21:46] <pedro3005> Given this, I think now you are experienced enough to try your hands at a challenge
[21:46] <pedro3005> http://ubuntuforums.org/showthread.php?t=884394
[21:48] <pedro3005> OH, I forgot to mention
[21:48] <pedro3005> files also havc the append mode
[21:48] <pedro3005> which is similar to write
[21:48] <pedro3005> but you begin writing where the file stop
[21:48] <pedro3005> whereas the file is cleared if you open it in write mode
[21:48] <pedro3005> f = open("bla", "w")
[21:48] <pedro3005> and f = open("bla", "a")
[21:48] <pedro3005> Is that clear?
[21:50] <ClassBot> There are 10 minutes remaining in the current session.
[21:55] <pedro3005> So just for recalling
[21:55] <ClassBot> There are 5 minutes remaining in the current session.
[21:55] <pedro3005> so far we went over variables, user input, outputting (print), types, type checking & conversion, boolean expressions, if blocks, for and while loops, functions, lists and dicts, list comprehension, files
[21:56] <pedro3005> So it'd be good if you all were sharp on these subjects
[21:58] <pedro3005> I think in the next class I will present a program, so we can study how to actually develop full stuff
[21:58] <pedro3005> But anyway
[21:58] <pedro3005> Time for us to call it a day
[21:58] <pedro3005> I hope this was of some use
[22:00] <ClassBot> Logs for this session will be available at http://irclogs.ubuntu.com/2010/10/09/%23ubuntu-classroom.html