 So, here is a while loop that actually computes the Fibonacci sequence. So, while loop is basically written as while condition block. So, basically you say while B is less than 10, print B, A, B is equal to B, I plus B. So, what are we doing here, tuple expansion. So, what does this do, A, B is B, I plus B, it sets A to B and then sets B to A plus B and so it loops and then it keeps checking for B executes the block until this condition fails. Now, if I wanted to make the condition fail by force, if I say if B happens to be 2, you please exit, you can add what is called a break statement. So, just do a quick example, A, B equals 0, 1, B is less than 100, print B, A, B equals B, A plus B. If B is greater than 70, this is stupid I know but I am just showing you how break works, break. So, it stops at 55, the idea is so we do looping with if, while, for and if has special syntax using the in notation, notation not in, containers like list, tuples and dictionaries support the notion of in. So, do strings, so you could also have done this, so if I say word, so I can say hell or okay, L, what do you think will happen here? It is true, so this answers kind of your question, so the notion of in is a useful thing, so I could have said L in some dictionary, it is a false, so I do not have to know has key or anything like that, I can just use the notion of in, if this thing in this and then you have for loops which let you iterate over any container and technically you can iterate over what are called any iterable. Now, the next thing is, so this lets us do basic things, but the real power of programming language is code reuse, so the first way of doing code reuse is to build functions. Now, in Python functions support what are called, you can call them with arguments of course, they can return any number of things. They support both default and keyword arguments, which means you do not have to always specify things and you can also explicitly specify things, we will do this in detail. Now, every time you create a function, we will get to that, the scope of variables in that function is local, so if I create x is equal to 10 inside a function, x only exists inside that function, so I cannot say x once the function scope is done. Mutable items, when you call a function, mutable items are passed by reference, they are not passed by copy. The first line after a definition can be a documentation string, so I am going to show you an example, so just bear with me and here is an example, so I have defined fib n, so fib is the name of the function, this def is a keyword that indicates I am going to define a function. The brackets indicate arguments that you are going to specify, if you had no arguments you do not specify the n, so it just becomes brackets, if you have an argument it becomes whatever argument in a sequence, so you can say n, a, b, c, so on and so forth. The first line you see here, not this comment you see here, this first string you see here is the doc string of that function. This is useful because if I say fib, question mark, it gives me the documentation and it only gives the documentation that the developer has written, if you have not written documentation somebody is going to curse you saying this guy has not documented its code, so it is up to you to document, it is a good practice to always document your function, but you do not have to, if you did not just the doc string would not show up, it is not it is just a convention that the first string is interpreted as a documentation string, this a and b you see inside here they are purely local, if I access a here it is an error, so a, b exist only inside here, similarly with n, n is again inside the function scope, n will not impede or interfere with any n that is outside here, is that clear? And the insides are just like any of the other constructs that you have learned up to this point, except everything in that function is indented one level to the right, so if you notice this function all of this is inside the function, once we get out of it we are back to this level of indentation at the level of def and that indicates that you are out of that function, you are finished defining that function, to call a function, so at the instant when you type this function up in python and you finish the function scope, a function object is created, so think of it as an object just another object called a function object that is sitting in memory somewhere and this name fib over here is bound to that function object, so when you call the function you call it as fib bracket argument and it prints the sequence, now because fib is a name bound to a function object I can assign another variable to it, so I can say f is fib, in as much as I can say a equals b for the previous example I can always say f is fib and then call f, so functions are first class objects they are just like anything else and functions also have methods they will have attributes they are just objects, so that is one of the nice things about python, pretty much everything is an object, so as you see here fib 2000 does this, f is fib, f is 10, so I have this thing I have already typed this out, so fib oops I typed it out this is what I typed, so I can say fib 2000 I get this, I can say f is fib, f 100, I did f is fib and that is giving me an error saying so this shows you the error, so supposing I say f is fib what happens it says fib takes exactly one argument I gave 0, so if you call fib with nothing it gives me an error, what if I called it with 2 it is also an error, so again you get detailed information it says it takes 1 you gave me 2, so I could also assign fib to x, what is x sorry x is none, the reason is I have not made any return statement here, in python if you have no return statement by default it returns none, but if I added a return statement it will return that particular thing that object it can be any object, so I can return multiple I can return a tuple I can return a list I can return a dictionary I can return a function I can return whatever you want, so you are not restricted by just returning something and having to return a pointer and worry about allocation nothing, you return what you want that is return and you can assign that to the object on the left hand side, so for example I will just do a quick example f f some junk I am not going to do anything special I am going to return a tuple 1, 2, 3, now if I say f it returns a tuple, so if I say x, y, z equals f x, y, z is 1, 2, 3, I can also say x is f in which case x is 1, 2, 3, so it does not matter it is smart enough to figure out things if I do x, y is f there is a problem because python does not know if x should be 1, 2 or y should be 2, 3 okay, so it is usually it is intuitive if you think yeah this looks like it is going to work it is going to work, if you think hey there is ambiguity here it is not going to work and typically that is the way python works, so it kind of there is a quote by Bruce Ekel it says python fits my brain, so basically if you think yeah this looks right it is going to work okay, so now we know how to create simple functions and what did I do here I did not show you how return works, so return just returns and you can put return anywhere you want inside a function, but once it returns it is out of that function, here we look at what are called default arguments, so I have a function which takes 1, 2, 3 arguments the first is prompt I do not have to say what prompt is, this second argument is retries which is 4 and a complaint inside we have a while loop, so what is while true do, while true is an infinite loop because the condition is always true, so it is going to keep doing whatever you have asked it to do inside here first thing is give me a value the user is given, so okay is raw input prompt, raw input does what raw input gives a user a prompt and returns the value entered keyed in by the user you remember okay, so the okay value is going to be a string and I am saying if okay in these return true, if okay in the other things return false I am decrementing the retries, if retries is less than 0 I say I give the user a message saying bad user, the way I do it is by using an exception we will do this later ignore this statement for now and print a complaint okay, so if the user did not print yes or no it will say yes or no, now the thing here is the retries is by default 4, so if I simply said so let us say ask okay is here I just typed it out, so if I say ask okay so it asks me give me a number, so I say which says yes or no, now I say again I am persistent in my persistent in my stupidity, so I do this now it says bad error because it retried 4 times but I say no I do not want to retry 4 times I am very impatient I am going to say retries only 2 times, now I type nonsense, no nonsense there is a bug in the code it does it one more time than I want it but at the end of 3 it rises bad, so the point is I just say ask okay prompt by default it assumes retries is 4 and it assumes that the complaint is yes or no, but now I say no no I can change that by saying 2 and I can say I can change the complaint I can say, so now I enter nonsense and it says idiot instead of yes or no, so the point is now if I am good, oh yes, so now when I put why it said true, so it did okay, so the point is default values let you specify defaults for that function it is very handy in order to write functions that are nicely usable imagine if every time the user has to use use use okay he has to say this thing this argument the next argument so on and so forth we had 100 arguments it is a pain this makes it very easy to do these kinds of things. The other thing is keyword arguments, so let us go back to this example let us say I want the retries to be 4 but I want to change just the complaint I want to say idiot but I do not want to say I want to do it 4 times, so I say if I did this we have a problem because the second argument is the number of retries and that is supposed to be a number it has no way of knowing so if I did this and type some nonsense it will give me an error because it says I do not know what it means to subtract one from the string so the way to do this is to say complaint equals idiot. So if you remember the function has complaint so this is what is called keyword argument so if I say complaint is idiot now it knows then only the complain is that and that works so is that clear so default arguments let you specify defaults you can specify the value of that thing explicitly by using keyword arguments that is name of that argument equals value and this is more elaborately explained in this particular case so I have a silly function this is again taken from the tutorial voltage state is blah blah blah so I have the function here this is the same function I say parrot 1000 so it says this is a parrot would not womb if you put 1000 volts through it lovely plumage the Norwegian blue it is a stiff okay very nice so now I can say action equals now notice there is a problem the first argument I am not specified so if I just called it like this it is an error so parrot takes at least one non keyword argument 0 given but I want to explicitly call it like this that works because again I have made it unambiguous to python as to what I mean and I have specified all arguments so when python looks at this it says I know what state is the default action has been specified over here as womb triple exclamation type has been specified and voltage has explicitly been specified by name by keyword argument therefore it works so as you can see again it is it is sensible the same thing so there are bunch of other examples okay so now we know how to create functions return values the code inside a function is completely local and you can support both default and keyword arguments now sometimes you want to create functions we take arbitrary number of arguments okay so let us say you want to say I want to add a collection of elements I do not know how many elements you want to add you may want 1 2 3 4 I cannot explicitly create one function with 1 2 3 4 instead I want a way by which I can create multiple so if you use the star args in your definition so if you look at this definition here funk funk star args the args will be any number of arguments the user supplies similarly if you want to do this with keyword arguments you use star star so let us look at this example funk is that so if I say funk 1 2 3 4 5 I get 1 2 3 4 5 as a tuple and the keywords as a dictionary instead if I say a equals 100 b equals 200 I get that so I have a function I have ways by which I can create functions that take arbitrary number of keyword and position of arguments using star args and star star keyword args now sometimes you have a list or you have a tuple and you want to call a function with these list arguments the way you do that is to use what is called unpacking so you save foo star 5 comma 10 so I think I have foo as well okay so foo just prints what is passed as a and b default is 10 comma 100 now if I say foo star 1 comma 2 given a list or a tuple it expands that out into positional arguments and calls that function is that clear you can do the same thing with keyword arguments so notice this foo a colon 5 b colon 10 is a dictionary it expands this out into a equals 5 b equals 10 and calls f is that clear so you can create functions that do whatever you want them to do they can return values and you can call them with you can use default arguments keyword arguments you can call functions using unpacking argument unpacking okay so the next thing is so now we have data types we have functions we can build this build functionality into this and now we need to go beyond that so now we need to create what are called modules modules basically package variables functions data types into one unit okay the other thing is exceptions which we have been looking at all this while whenever we got an error we got an exception so more details on exception and finally we look at classes so modules basically define functions variables and classes all you do is you put them all into a dot pi file a text file which has a dot pi extension so for example I have in my home directory this file here talk dot pi so that is a python file this is a module so I am going to quit the python interpreter so you know I am not cheating clearing all this stuff now I can say import talk that is just a python file is a text file and once I import it I have a module okay we look at the details of that so basically the things you put into that python file become a python module python needs to know where your modules are if I put the stock dot pi in some other directory python has no way of knowing where to find it so there are they follows a certain standard in how it look looks at where to look for modules so the first thing is it looks at the current directory not quite the first thing but it looks at the current directory and then it looks at standard directories so on Unix machines is typically user lib python 2 point whatever slash site packages somewhere it has a bunch of paths where it actually looks by default it also looks at any directories you specify in an environment variable called python path so if you look at my python path notice I am doing something on ipython I am doing bang bang will actually run a shell command I am doing echo which is a shell command and I am looking at what the environment variable dollar python path in my bash shell has it was not a login shell so anyway so the thing here is I have a path here I don't know if it's visible basically just a second okay so ignore the error message but what I have here is a path that is separated by colons so I have some directory colon another directory colon another directory so in Unix if you use this form each of these directories is searched for python modules if you want to find out what are the paths that currently python is looking at you use the module sys so you say import sys sys dot path is a list containing strings of directories where python currently looks for modules I will review that current directory anything in the standard directories python path and finally you can check where it's looking for using sys dot path when you say import which is a keyword import module name it imports this module into your current namespace you can also use from some module import some name so what I did now exit again I said import talk so that gives me now as soon as I do import talk I get a module called talk it's an object so this talk is a module and it's from this file here ipython tells me that now talk internally has various things that I've defined I could say from talk I only want fib let's say so from talk import fib if I want to call something inside talk the usual way is you say talk dot fib that works so fib is a function as you see here defined in talk I import talk and then say talk dot fib it calls that function if instead I want to call fib directly I simply say fib I simply say from talk import fib and then I can call fib here right here so basically what import does is it imports a module associates this name talk in your current namespace with that module object which is from that file is that clear again names bound to objects so talk is a mod is a name bound to a module object and now when you say from module import name it binds this name to that object inside that particular module so when you say from talk import fib there's a function object called fib inside talk the local fib is a name fib that's bound to that function object which you can call and assign variables to do whatever you want is that clear so again they just is just names and objects and you just have these notions of we'll come to name spaces in a bit you can also do what's called from module import star which will import everything in that module and stick it in the current namespace so fib parrot all these functions that are defined here all of this stuff will be stuck in the current namespace any variables any functions so this is dangerous the reason is I may have a fib in my current namespace I may have defined a fib and now when I do from import from talk import star my fib is gone supposing I had a is one so let's say def f okay so if I do fib it works but now if I do from talk import star and do fib I get an error so this is a problem so therefore you never import from star unless you know exactly what you're doing or you're working on the interactive interpreter and you're playing around in main code in your modules you should avoid doing from something import star because it's going to overwrite everything you're doing up to that point okay so here's an example the same thing that I've typed out there you can also define variables so if I look at talk at some var values one I can assign it to something else no problem it will work you define functions in the end of file and that becomes a model it's as simple as that now you can import this call it change values and do whatever you want so in all of this I've been saying namespace namespace namespace so what is a namespace the namespace is again the same thing it's a mapping from names to objects so modules introduce a namespace so when I say import talk there's a talk namespace inside talk there are things there's a name there's there's a mapping so inside talk there's a mapping from fib to fib object in my current namespace there is a mapping from fib to talks fib object you understand so basically name there are objects and namespaces are everywhere in Python so modules introduce a namespace when you use classes they introduce a namespace when you create a function it introduces a local namespace okay so namespaces are pervasive in Python so you'll hear the idea all the time the idea is very simple it's simply a binding from names to objects so when you are running in I Python right now the current namespace is determined by name the special word key special symbol underscore underscore name underscore underscore and that's main so main program is main this is the main thing that's running on the other hand talks name is talk okay we saw that the modules namespace is identified by its name so look at talk if you remember we had functions like len abs and things like that those were what I call standard from range all of these come from a namespace called built-in okay so so built-in has all of these things and typically when Python starts built-in is there for you okay so objects super abs you can look at abs here so built-in has all of these so the general idea is this namespace help organize different names and their bindings so modules have their own namespace current namespace is something so this lets you do very interesting things if you notice my talk dot pi it was a module but if I quit and run python talk dot pi it actually did something so if you look at if I do import talk it didn't do anything the reason this happens is I've defined a various things here at the bottom I have what's called standalone code I'm checking I check to see is name main which means is this executing as main or has it been imported by somebody had this been imported when I do import talk talk's name is talk so it will not execute this if block is that clear when I import talk and talk prints name it will be talk it will not be main but when I run python talk talk is the main is that clear so when you do an import the name underscore name is set to the name of the module but when you execute it it becomes main you say python this file name then it runs then it becomes main so you can actually do a conditional thing by saying if I'm running execute as an executable you do this if I'm not running as an executable don't do anything because I don't want it to print every time I'm importing talk okay so this is the way again you build reusable pieces so I build something that's a script that executes and does something useful but I also want to use that functionality built into that script so I have some functions written there some function that cleans up my directories for example I want to import that in something else so I can import this and use it so that's the idea okay so now we know how to make basic data types we know how to do control flow we know how to do while loops for loops if conditions and then we know how to make functions and then we know how to put all of these into modules so we're already quite far ahead so as you noticed there are lots of errors that can arise and python notifies people to errors using make mechanism called exceptions and there are several standard exceptions syntax error IO error name error type error value error index error many of these we've seen so there are a whole bunch of standard exceptions as we looked at and you can what is called raise an error so let's say we ran into an error we ran into this a little while ago over here I said raise IO error IO error is a standard error and you say raise this comma message it'll actually throw an exception we'll say here's an error and this is the message that the error raised okay we'll do this in a bit now the beauty of exceptions is you can catch an exception and do something when that error occurs so usually if you look at C programs often you have some check and it just crashes there it's gone you have no way of recovering whereas in python you have an exception and you can catch the exception and say oh there's an exception here and go to that location and fix it so here are a bunch of examples here I have division by 0 so there's a zero division error 1 by 0 I say 4 plus spam into 3 spam is not defined so you get a name error so if you ever come into come across a name error it means that name is not defined and then you have type errors which we saw when we multiplied 2.5 into a string we got a type error because the type does not support certain things the way you catch exceptions isn't this man so let's say I have a wild proof which is a for infinite loop I try x is int raw input enter a number if this works it will break if this fails see the point is this if I say int foo it's an error so if I do this I will just type this out true try x is int of raw input break except value error so when I when I have this int foo I get a value error that is the value given to int is wrong so I say except value error colon do something else okay so I am nasty so now it does this so I type some nonsense so it shouts at me until I give it a 12 or some integer because then that works and it breaks out of the infinite loop so here's an example of break try and accept now the same way you want to raise it raise an error you just say raise value error your error message here and you get this output so if you have multiple exceptions that you're catching for so let's say you want to catch all exceptions you just say except and this I highly recommend against the reason is even if I press control C it's not going to quit so I have forced to put a number I can kill the program or something like that but it's a little too much but multiple exceptions supposing I say I want to capture okay sorry the first thing is I want to capture the error the I want to catch the case when I have a value error and I also want to find the message that I got so in this case you give it like this is the syntax so it prints that message so the way in which you capture and you catch an exception and also get the message is this but this raises a problem how do I know specify multiple errors the way to do it is you put them in parenthesis so this works so the idea is you can use try except blocks to catch for errors and handle those errors in your quotes