Skip to content

Harvard CS50’s Introduction to Programming with Python – Full University Course

Harvard's CS50 Introduction to Programming with Python teaches coding, debugging, testing, and key programming concepts for beginners.

Key Takeaways

  • Python programming fundamentals are accessible to beginners with no prior experience.
  • Testing and debugging are critical skills taught alongside coding.
  • Understanding multiple programming paradigms enhances coding versatility.
  • Practical problem-solving and project work reinforce learning.
  • Defensive coding and exception handling improve code reliability.

What the video covers

  • The course is an introduction to programming using Python, designed for students with or without prior experience.
  • Taught by Dr. David Malan, it covers fundamental programming concepts such as functions, variables, conditionals, and loops.
  • Students learn to write, test, and debug code, including defensive programming and exception handling.
  • The course introduces unit testing to ensure code correctness and maintainability over time.
  • File input/output operations and regular expressions for data validation and extraction are covered.
  • It explores programming paradigms including procedural, functional, and object-oriented programming.
  • Students gain practical experience by solving progressively challenging problems and working on projects.
  • The course emphasizes writing reusable code and leveraging libraries to avoid reinventing the wheel.
  • No prior programming background is required, making it accessible to complete beginners.
  • By the end, students are equipped with a solid foundation to pursue further programming studies or projects.

Answers

Questions about this video

Do I need prior programming experience to take this course?

No prior programming experience is required. The course is designed to teach programming fundamentals to complete beginners using Python.

What programming concepts does this course cover?

The course covers functions, variables, conditionals, loops, exception handling, unit testing, file I/O, regular expressions, and multiple programming paradigms including object-oriented programming.

Who teaches this course and where is it from?

The course is taught by Dr. David Malan and is offered by Harvard University as part of the CS50 series.

Full Transcript — Download SRT & Markdown

00:00
Speaker A
This course from Harvard University is an introduction to programming using the Python programming language. You will learn how to read and write code, as well as how to test and debug it. This course is taught by Dr. David Malan, and it's
00:16
Speaker A
designed for students with or without prior programming experience who'd like to Learn Python [Music] [Music] hello world my name is David Meen and this is cs50's Introduction to programming with python whereas cs50 itself is an introduction to the
00:54
Speaker A
designed for students with or without prior programming experience who'd like to learn Python. [Music] [Music] Hello, world! My name is David Malan, and this is CS50's Introduction to Programming with Python. Whereas CS50 itself is an introduction to the
01:07
Speaker A
which you can write code that solve smaller problems but you can compose those smaller Solutions into solutions to larger problems still we'll then transition to a look at conditionals a way in code of expressing yourself logically to maybe do something if some
01:22
Speaker A
intellectual enterprises of computer science and the arts of programming, this course is specifically focused on programming in Python itself. At the beginning of the course, we'll be focused on a topic in programming known as functions and variables, mechanisms via
01:34
Speaker A
something a little more technical known as exceptions unfortunately a lot can go wrong when you're writing code some of it your fault some of it perhaps someone else's fault but you can write code defensively so to speak and actually
01:45
Speaker A
which you can write code that solves smaller problems, but you can compose those smaller solutions into solutions to larger problems still. We'll then transition to a look at conditionals, a way in code of expressing yourself logically to maybe do something if some
01:59
Speaker A
can use and reuse in your own project so as to avoid Reinventing the wheel again and again we'll look thereafter at something called Unit tests and turns out you'll actually write code to test your own code but you won't have to
02:12
Speaker A
question has an answer of true, or not do something if the answer is false. We'll transition thereafter to introducing you to loops, the ability in code to do something again and again and again some number of times. We then transition to
02:23
Speaker A
someone else modifies your code tomorrow or down the line you can rerun those same tests to ensure that those new changes have not broken anything about your own code we'll then take a look at something called file Io Io for input
02:36
Speaker A
something a little more technical known as exceptions. Unfortunately, a lot can go wrong when you're writing code. Some of it your fault, some of it perhaps someone else's fault, but you can write code defensively, so to speak, and actually
02:49
Speaker A
whereby in Python you can Define patterns and you can validate data to make sure the human type something in as you expect you can use regular Expressions to extract data perhaps from some data set you're trying to analyze
03:00
Speaker A
catch those kinds of exceptions, those errors, and handle them properly so that the users you're writing code for don't actually see the same. Thereafter, we'll take a look at libraries, third-party code written by other people often, or perhaps yourself in the past, that you
03:14
Speaker A
programming where you write lots of those functions procedures really top to bottom to solve problems step by step and even something known as functional programming as well and then at the very end of the course will we equip you with
03:25
Speaker A
can use and reuse in your own project so as to avoid reinventing the wheel again and again. We'll look thereafter at something called unit tests, and it turns out you'll actually write code to test your own code, but you won't have to
03:38
Speaker A
mechanisms now this course itself assumes no prior programming background so you don't have to have written a single line of code in python or any language yet but this is also a course that you can take before during or even
03:50
Speaker A
write tests for your tests. Indeed, this is a best practice in industry: writing tests for your code so that one, you can be sure that your code today is hopefully, if your tests are correct, correct itself, but moreover, if you or
04:02
Speaker A
week that is programming projects that will enable you to apply some of those Lessons Learned to problems of your very own and by the end of the course you'll solve to have solved so many problems that ideally are representative of
04:15
Speaker A
someone else modifies your code tomorrow or down the line, you can rerun those same tests to ensure that those new changes have not broken anything about your own code. We'll then take a look at something called file I/O, I/O for input
04:28
Speaker A
which to approach the same this then is cs50 and this is cs50's Introduction to programming with python [Music] all right this is cs50's Introduction to programming with python my name is David men and this is our week on functions
05:09
Speaker A
and output, the ability to not just store information inside of a computer's memory, but rather save it persistently to disk, so to speak, to files and folders. We'll then take a look at another technique known as regular expressions,
05:22
Speaker A
which is just a very popular program nowadays for actually writing code now you don't have to write code using this particular tool in fact all we need at the end of the day is is a a so-called text editor a program for writing text
05:33
Speaker A
whereby in Python you can define patterns and you can validate data to make sure the human typed something in as you expect. You can use regular expressions to extract data, perhaps from some data set you're trying to analyze.
05:42
Speaker A
writing text because that's what code is text now within this particular program I'm going to have the ability to create one or more files via this top portion of the screen and I'm going to do so by diving right in and doing this at the
05:54
Speaker A
We'll then take a look ultimately at object-oriented programming, a paradigm, a way of writing code whereby you can represent in code real-world entities, and this is in addition to other paradigms of programming that we'll also explore, among them procedural
06:08
Speaker A
to do here is literally write code and then the name of the file that I want to code for instance hello.py as we'll soon see any program that you write in Python generally has a file name that ends inp to indicate to
06:21
Speaker A
programming, where you write lots of those functions, procedures really, top to bottom to solve problems step by step, and even something known as functional programming as well. And then at the very end of the course, we'll equip you with
06:30
Speaker A
and then just a tab that reminds me of the name of this file hello.py and without even knowing much python I'm going to write my very first program here as follows print open parenthesis quote hello comma World close quote and
06:45
Speaker A
all the more tools for your toolkit, additional building blocks, additional vocabulary via which, after this same course, you can go off on your own and either take other courses or solve projects of your own using all of these
06:55
Speaker A
this tool here now even if you've never programmed before odds already you can guess infer what this simple program is going to do and it's only one line print open parenthesis quote Hello World close quote close parenthesis indeed when I
07:11
Speaker A
mechanisms. Now, this course itself assumes no prior programming background, so you don't have to have written a single line of code in Python or any language yet, but this is also a course that you can take before, during, or even
07:21
Speaker A
that's what I've done here but on my Mac my PC even my phone I'm generally in the habit like you of running programs by double clicking an icon or just tapping on the screen but I see no such icons
07:33
Speaker A
after CS50 itself if you'd like to get all the more versed with Python. Each week, via the course's lectures, we'll introduce you to any number of concepts that will then drill down more deeply into in the form of problem sets each
07:45
Speaker A
icons that you and I take for granted every day you'll find we think that it's ultimately a much more powerful interface and Incredibly popular to use among programmers in the real world so to run this program I'm going to have to
07:57
Speaker A
week, that is, programming projects that will enable you to apply some of those lessons learned to problems of your very own. And by the end of the course, you'll have solved so many problems that ideally are representative of
08:10
Speaker A
of the file that I wanted to code up now I have a chance to type a second command and you'll see I see a second dollar sign now the dollar sign here doesn't indicate any kind of currency or money
08:19
Speaker A
problems you'll eventually encounter in the real world, whether you aspire to solve code in the technical world or perhaps in the arts, the humanities, the social sciences, the natural sciences, or beyond. You'll have ultimately the vocabulary and the technical skills via
08:32
Speaker A
hello.py now why is that well it turns out that when I actually write code in a language like python it's of course stored in that file hello.py but I need to interpret the code top to bottom left to right so that the computer knows what
08:47
Speaker A
which to approach the same. This then is CS50, and this is CS50's Introduction to Programming with Python. [Music] All right, this is CS50's Introduction to Programming with Python. My name is David Malan, and this is our week on functions
08:58
Speaker A
print and parenthe is and quote unquote hello world is not surely zeros and ones we have to somehow translate it into the zeros and ones that the computer understands now fortunately so long as you've installed such a program in
09:11
Speaker A
and variables. But odds are many of you, most of you, have never actually programmed before, so let's start by doing just that. Let me go ahead here and open up my computer and on it a program called Visual Studio Code, or VS Code,
09:23
Speaker A
server in the cloud and you can then run that program that interpreter passing to it as input the name of your file like mine here hello.py and then that program that interpreter will handle the process of reading it top to bottom left to
09:37
Speaker A
which is just a very popular program nowadays for actually writing code. Now, you don't have to write code using this particular tool. In fact, all we need at the end of the day is a so-called text editor, a program for writing text,
09:50
Speaker A
now going to kick off this command and hopefully if I didn't mess any of this up I should see my very first program's output to the screen and voila hello world so if you two have typed exactly that same code and have executed exactly
10:06
Speaker A
and heck, if you really want, you could even use something like Google Docs or Microsoft Word. You'd have to save it in the right format, but really at the end of the day, all you need is a program for
10:18
Speaker A
foremost in most any programming language you tend to have access to what are called functions a function is like an action or a verb that lets you do something in the program and generally speaking any language comes with some
10:30
Speaker A
writing text because that's what code is: text. Now, within this particular program, I'm going to have the ability to create one or more files via this top portion of the screen, and I'm going to do so by diving right in and doing this at the
10:43
Speaker A
the computer to do those things now the program in question here hello.py is using one function and you can perhaps guess what it is that function is of course going to be this function print and that print function of course
10:57
Speaker A
bottom of my screen. At the bottom of my screen is a so-called terminal window, and this is a command line interface, or CLI, interface to the underlying computer, be it your Mac or your PC or even some server in the cloud. And what I'm going
11:11
Speaker A
to a function that somehow influences Its Behavior the people who invented python of course didn't necessarily know what it is you and I are going to want to print to the screen so they designed this print function using these
11:23
Speaker A
to do here is literally write code and then the name of the file that I want to code for, instance hello.py. As we'll soon see, any program that you write in Python generally has a file name that ends in .py to indicate to
11:37
Speaker A
doing on the screen well it's printing of course it's showing us hello world on the screen and that's generally in programming known as a side effect it can be visual it can be audio in this case it's something that appears on the
11:47
Speaker A
the computer that it's indeed a program written in Python. Now, you'll see here at the top of my screen I have a blinking cursor, a line one, which is where the very first line of my code is going to
12:00
Speaker A
so that's my first program and you know I'm feeling pretty good everything worked as planned I didn't make any mistakes but honestly when you're learning how to program and even once you've learned how to program years later you're going to make mistakes and
12:13
Speaker A
go, and then just a tab that reminds me of the name of this file, hello.py. And without even knowing much Python, I'm going to write my very first program here as follows: print open parenthesis quote hello, comma world, close quote and
12:23
Speaker A
over the coming weeks you're going to make so many mistakes you're going to have so many bugs in your code just like I did and just as I still do and those bugs themselves are just mistakes that are problems for you to solve and over
12:36
Speaker A
close parenthesis. And you'll see that at my keyboard some of my thoughts were finished for me. I only had to type one parenthesis, and the other one automatically appeared, and that's just a feature that we'll see of tools like
12:47
Speaker A
first time it will with time with practice and with experience so let me deliberately now make a mistake that there was a nonzero chance I might have done accidentally already but I got lucky let me go ahead and just suppose I
13:00
Speaker A
this tool here. Now, even if you've never programmed before, odds are you can guess, infer what this simple program is going to do, and it's only one line: print open parenthesis quote Hello World close quote close parenthesis. Indeed, when I
13:12
Speaker A
closed parenthesis but even little seemingly Minor Details like that that you and I as humans wouldn't really care about and if you're sending an email or a text message oh whatever it's just a typo it's not that big a deal it is
13:24
Speaker A
run this program, ultimately it's just going to say hello to the world. And in fact, this is a very famous, perhaps the most canonical program that you can write as your very first program in Python or any other language. And so
13:34
Speaker A
let's do this I'm going to go ahead here and clear my screen down at the bottom just so I can start fresh and I'm going to go ahead and run this version of my program after having made that change by
13:43
Speaker A
that's what I've done here. But on my Mac, my PC, even my phone, I'm generally in the habit, like you, of running programs by double-clicking an icon or just tapping on the screen, but I see no such icons
13:57
Speaker A
my having made a mistake at my keyboard and it this one fortunately is pretty straightforward it indeed says that this open parenthesis was never closed and so that's probably pretty intuitive now what I need to do I need of course to
14:11
Speaker A
here. And in fact, that's because my interface to at least my current Mac or PC or some server in the cloud is again only a CLI, command line interface, which even though it might feel like it's a step back from the menus and buttons and
14:24
Speaker A
correctly let me go ahead run now hello.py and hit enter and voila we're back in business well let me pause here and see if we have any questions now about python itself writing or running even the simplest of these
14:39
Speaker A
icons that you and I take for granted every day, you'll find we think that it's ultimately a much more powerful interface and incredibly popular to use among programmers in the real world. So to run this program, I'm going to have to
14:55
Speaker A
with Microsoft Word I mention that only because it's a tool via which you can write text and code is at the end of the day just text but it's not the right tool for the job we don't need bold
15:04
Speaker A
use a command, and I'm going to move my cursor back down to the bottom of the screen.
15:16
Speaker A
human to edit text nowadays these text editors come with many more features in fact you'll notice that even in my code here even though it's just one line there's a bit of color to it the word print for me is appearing in blue the
15:28
Speaker A
parentheses are black and we'll see as we might write more lines of code more and more of the lines will come to life in various colors now that's just one feature of a text editor we'll see too that it has features like this built-in
15:39
Speaker A
terminal window it's going to have a built-in tool for debugging or finding problems with code and it's just a very popular tool nowadays but there are many many others out there you're welcome to use them for this course and Beyond we
15:50
Speaker A
just happen to use this one in large part too because you can also use vs code nowadays uh for free in the cloud how about one other question here on programming with python or hello world or syntax more generally I was trying to
16:04
Speaker A
ask if is not possible to run the code without using the terminal window I think I heard is it not if it's possible to run the program without the terminal window are you yes sir okay you froze for me again but let me infer what the
16:19
Speaker A
question is so in this environment as I've configured my computer I can only run these python programs via the terminal window now that's good for me the programmer or the person who's trying to learn how to program but it's
16:31
Speaker A
not very good if you want to ship this software and have other people use your actual code you can absolutely write programs and then allow other people to use not a command line interface but a graphical user interface or guey GUI
16:44
Speaker A
this is just one mechanism and perhaps I think the the best one with which to start writing code because eventually it's going to give us a lot more control allow me to forge ahead here but please feel free to continue asking questions
16:56
Speaker A
along the way if only via the chat let's consider now how we might go about improving this program let's go about improving this program to make it a little more interactive and not just assume that everyone is going to want to
17:08
Speaker A
be greeted more generically as hello world let's see if I can't get this program to say something like hello David or hello Jeremiah or hello Horatio or whatever the actual user's name is well to do this I'm going to go back up
17:20
Speaker A
to hello.py and I'm going to add another line of code at the very top that simply says for instance uh what's your name quote unquote with an extra space at the end so I'm printing to the user asking
17:32
Speaker A
them a question for some input but now I need another function to actually get input from the user and perfectly enough python comes with a function named input so here I'm going to go ahead and call a function input open pen close pen and
17:46
Speaker A
that's going to prompt the user with just a blinking cursor waiting for them to type something in now it turns out if I read the documentation for the input function it actually takes an argument itself I don't need to use print
17:57
Speaker A
separately and then promp the user for input so I can actually simplify this code before we even use it I'm going to go ahead here and take that same string from print put it as an argument to the
18:08
Speaker A
input function and get rid of the print alt together and in fact that print would have added a new line anyway so now I've just got a prompt where the user's cursor is going to end up blinking at the end of the line asking
18:17
Speaker A
them what's your name in my terminal window I'm going to run python of hello.py enter okay we're making progress it seems that this new function input is indeed prompting me the human for input so I'm going to type in my
18:30
Speaker A
name David and hit enter unfortunately it doesn't really do anything with my name it just outputs it immediately all right well I could fix this right I could go up to line two and I could change world to David and then back in
18:44
Speaker A
my terminal window here I can do python of hello.py enter what's your name David enter and there we go all right now I'm up and running now my program is working as intended of course this isn't really working as intend Ed here let me go
19:00
Speaker A
ahead and try pretending to be my colleague Carter here well Carter's name is this I'm going to go ahead and hit enter and I'll see of course hello Carter well obviously not because I've hardcoded so to speak I've written
19:11
Speaker A
literally my name inside of the string so we need some way now of actually getting back what the user's input is and doing something with It ultimately and for this we're going to leverage another feature of programming specifically a feature of some functions
19:25
Speaker A
which is that they can have return values as well if you think of input as being again this action this verb you can actually personify it as maybe a person like a friend of yours that you've asked a question of and you've
19:36
Speaker A
asked your friend to go get input from someone else go ask that person their name and if your friend comes back knowing that person's name well wouldn't it be nice if they handed that name back to you that's kind of what we need
19:48
Speaker A
metaphorically the function to do is get the user's input and then hand it back to me so that I the programmer can do something with it but if it's going to be handed back to me I kind of want to
19:58
Speaker A
put it somewhere so that I can then print it back on the screen I need to do the equivalent of take out like a piece of paper or a Post-It note write down on this piece of paper what it is the human
20:09
Speaker A
has said so that I can then feed it into as input that print function and to do that we're going to need one more feature of programming namely variables and odds are most everyone's familiar with variables from math class way back
20:21
Speaker A
when X and Y and Z and the like well programming has that same capability this ability to create a variable in this case in the computer's memory not just on a piece of paper and that variable can store a value a number some
20:35
Speaker A
text even an image or video or more a variable is just a container for some variable a variable is just a container for some value inside of a computer or inside of your own program so how do I
20:47
Speaker A
go about expressing myself in this way well I think what I'm going to do is introduce a variable that's a little more interestingly named than x or y i i could just say this x equals input but I'm going to use a better name than a
21:00
Speaker A
typical mathematical variable here and I'm going to literally call my variable name why well in programming because I have a whole keyboard in front of me I can use more descriptive terms to describe what it is I'm writing and now
21:11
Speaker A
though there's an opportunity to consider a specific piece of syntax we've seen parentheses we've seen quotes all of which are necessary when passing inputs to a function but this equal sign here that's in between input on the right and name on the left is actually
21:27
Speaker A
important and it's technically not an equal sign per se it doesn't mean equality as much as it means assignment so in Python and many programming languages a single equal sign is the assignment operator and what that means specifically is that you want to assign
21:43
Speaker A
from right to left whatever the user's input is so the equal sign copies from the right to the left whatever the return value of the function on the right is so again the input function clearly gets input from the user that's
21:59
Speaker A
why I was able to type my name or Carter's but it also sort of behind the scenes hands that value that return value back to me the programmer and if I use an equal sign in a variable no
22:11
Speaker A
matter what I call it I can store that input in that variable so is to reuse it later so now sitting in the computer's memory somewhere is a container containing David quote unquote or Carter quote unquote or whatever the human has
22:24
Speaker A
typed in but here it's easy to make a mistake suppose I decide to try to print that name and so I I kind of on a hunch type in this hello comma name just kind of plugging in the name of the variable
22:39
Speaker A
well let me go ahead here and run python of hello.py and hit enter that's going to prompt me for my name and let me type in my name daid but I haven't hit enter yet and perhaps via the chat what's going to
22:50
Speaker A
happen here when I now hit enter I'm hoping it says hello David I'd be okay if it says hello world but I don't want it to say what it's actually G to say and yep what we're seeing in the chat is
23:03
Speaker A
well it's probably going to say literally hello comma name so that's not quite right so we need another way of printing out the value inside of that variable rather than just this word name well let me try this in a couple of
23:16
Speaker A
different ways let me try this as follows let me go ahead and maybe undo this because I've gotten pretty good already at saying hello so let's let you know let's draw that Line in the Sand and just say all right let's get at
23:26
Speaker A
least get hello comma out the door let's now print name and just on a hunch I'm going to try this I'm going to use print again because you can use these functions as many times as you need and
23:36
Speaker A
I'm going to pass to the name to the print function the variable called name but notice I'm being a little clever now I'm not putting it in double quotes because we've seen already that double quotes means literally print out n m I'm
23:49
Speaker A
getting rid of the quotes this time in hopes that now by passing the variable called name to the function called print it will in fact go about printing printing the contents of that variable that is its so-called value all right
24:03
Speaker A
let's go ahead and do this here python of hello.py enter what's your name David and now crossing my finger still I see hello comma David all right so it's not the best program I'm I'm kind of cutting some Corners here so to speak I'm saying
24:19
Speaker A
hello David on two separate lines so it's not as elegant it's not as pretty it's not as grammatically appropriate in English as just saying it all in one breath on one line but at least I've solved the problem just not very well
24:32
Speaker A
yet but let me take a step back now and perhaps introduce a couple of other concepts with which we should be familiar which is as our programs get longer and they're no longer just one line or two or even three eventually our
24:43
Speaker A
programs are going to become dozens of lines maybe even hundreds of lines long let's set the stage for Success moving forward it turns out that python and a lot of programming languages also support something called comments comments are notes to yourself in your
24:59
Speaker A
code and you include comments by way of a special symbol in Python it's going to be the hash symbol typically and that allows you to write the equivalent of a note to yourself but in a way that's not
25:08
Speaker A
going to break your code the computer actually ignores your comments it's just there for you it's just there for your teacher it's just there for your colleague with whom you're sharing ultimately that code so if I go back to
25:19
Speaker A
VSS code here and I just want to add some comments to this program to explain to my teacher to myself to my colleagues what this program is doing well let's go ahead and do that I'm going to go at the
25:29
Speaker A
very top of my program and on line one now I'm going to move that original line of code down a bit I'm going to add a hash and I'm going to say something like this uh ask user for their name now I
25:42
Speaker A
don't have to use that language I don't have to use that uh that text I could use any human language whatsoever it doesn't have to be English but I'm going to now below that just say something like this say hello to user and you'll
25:54
Speaker A
notice that vs code by default is kind of graying out my comments they're no longer blue there's no red there's no color in them and that's just because they're notes to myself and the computer ultimately is going to ignore them but
26:05
Speaker A
what we have now is two comments ask user for their name and then a second comment say hello to user and I've just kind of commented each chunk of code like each line or lines plural of code that are doing something noteworthy why
26:19
Speaker A
well tomorrow morning when I wake up having you know uh uh slept for quite some time forgotten what it is I did the previous day it's convenient with comments to just see in English or your own human language what it is this
26:31
Speaker A
program is doing so that you don't have to read the code itself and better yet if there's maybe a mistake down the road you can read what your intention was and then you can look at the code and figure
26:41
Speaker A
out if your codee's now doing what you intended so this isn't really necessary for a program this small it's pretty obvious with just one or two or three lines what the program is doing it's just as fast to read the code than the
26:52
Speaker A
comments but getting into this habit is generally a good thing to comment your code every one or few lines so is to remind yourself and others what it is your intent and your code is doing what's nice about comments too is this
27:05
Speaker A
comments can also serve to be sort of a to-do list for yourself there's this notion in uh programming of pseudo code pseudo code isn't a formal thing it's not one specific language it's just using English or your own human language
27:18
Speaker A
to express your thoughts succinctly methodically algorithmically so to speak but pseudo code therefore because it's not Python and it's not necessarily English it just kind of allows you to outline your program even in advance so for instance if I wasn't sure today how
27:35
Speaker A
I wanted to go about writing this program but I did know what I want to do I could have started today by just writing this in hello.py no code I could have written just a couple of comments to myself step one ask user for their
27:47
Speaker A
name step two say hello to user then once I've outlined my program in pseudo code then I can go in there and say all right how do I ask the user for their name uh well I can do input quote
27:58
Speaker A
unquote what what's your name question mark and then on the left here I can maybe put a variable and assign it to that okay how do I say hello to the user well I know I can use print to say
28:07
Speaker A
things on the screen let me say hello comma uh and let me okay let me now print the person's name so again pseudo code is a nice way of structuring your to-do list especially if you have no idea how to write the code because it
28:20
Speaker A
breaks a bigger program down into small bite-size tasks all right let me pause here to see if there are now any questions on comments pseudo code return values or variables any questions we can clear up here yeah my question is uh does the
28:39
Speaker A
function input uh work for any type of of information or only for Words yeah really good question so according to its documentation and we'll look more at formal documentation soon input is going to expect what's called a string that is
28:53
Speaker A
a sequence of text be it in English or any other human language but it's indeed going to be expecting text with which to prompt the user a good question how about another question from the group if we could I wanted to ask how I make
29:07
Speaker A
several line comment oh how do you do many lines of comments if if I'm hearing you correctly sure uh you would just keep doing them like this you just prefix each of the lines with a hash symbol like I'm doing here there is
29:22
Speaker A
another technique for doing multi-line comments in Python that actually tend to have special meaning you can do three double quotes like this and then anything in between here is a comment that's another technique or you can use single quotes as well but more on those
29:37
Speaker A
I think another time all right well if you don't mind let me Forge ahead here and see how we might improve this program further and also introduce a few other features that we might want to take into account over time so it turns
29:49
Speaker A
out that we can certainly improve on this program because it's a little disappointing that I'm cutting this corner and saying hello comma and then on a new line print out name like we can do better and most programs you use on
30:01
Speaker A
your phone or your laptop certainly keep text together when people want so how can we go about doing that well there's a few different ways and in fact the goal here is not so much to solve this one problem but to demonstrate and
30:12
Speaker A
emphasize that in programming Python and other languages there's so many ways sometimes to solve the same problem and here's one way to solve this problem let me go in here and let me go ahead now and say hello comma and let me just add
30:27
Speaker A
to the end of that the user's name so I'm using Plus in kind of an interesting way this is not addition per se I'm not adding numbers obviously but I do kind of want to add the person's name to the
30:40
Speaker A
string of text hello comma well let me go now down to my terminal window and run python of hello.py again enter what's your name I'm going to type in David enter okay it's better it's better but there's a minor bug albeit aesthetic
30:56
Speaker A
here there's missing space but let's just use some intuition here well if I'm missing the space after the comma why don't I go ahead and just add it manually here let me now rerun the program python of hello.py enter David
31:08
Speaker A
enter and there we go now we have something that looks a little prettier in terms of English grammar hello comma space David and now if we rewind you might have noticed before or wondered why I had this seemingly extra space
31:22
Speaker A
after my question mark namely here there's a space after the question mark but before the double quote and that was just for Aesthetics to I wanted to move the user's cursor one space to the right so that when I type their name or they
31:33
Speaker A
type their name it's not immediately next to that same question mark there but there's other ways we can do this it turns out that some functions print among them actually take multiple arguments and it turns out that if you
31:48
Speaker A
separate the inputs to a function the so-called arguments to a function with a comma you can pass in not just one but two 3 four five onward so let me go ahead and pass in not just hello comma
32:00
Speaker A
space but that followed by name and this is a little confusing potentially at first glance because now I've got two commas but it's important to note that the first comma is inside of my quotation marks which is uh simply an
32:14
Speaker A
English grammatical thing the second comma here is outside of the quotes but between what are now two separate arguments to print the first argument is hello comma space the second argument is the name variable itself so let's see
32:28
Speaker A
how this looks python of hello.py enter what's your name David enter okay I've kind of overcorrected now I've got two spaces for some reason well it turns out and this is subtle when you pass multiple arguments to print it
32:43
Speaker A
automatically inserts a space for you this was not relevant earlier because I was passing in one big argument to print all at once by using that plus operator this time I'm passing in two because of the comma so if I don't want that extra
32:59
Speaker A
space I don't need to pass in one myself I can just do this and now notice if I run this program again python of hello.py type in my name David now it looks grammatically like I might want now which of these approaches is better
33:12
Speaker A
this approach uses a function print with two arguments hello comma and the name variable the previous version recall technically used one argument even though it looked a little curious It's one argument in the sense that the computer just like mathematicians are
33:27
Speaker A
going to what's inside of parentheses first so if inside of parentheses you have this string of text hello comma and a space which I need to add back then you have a plus which means not addition per se but concatenation to join the
33:41
Speaker A
thing on the left and the thing on the right this ultimately becomes the English phrase hello comma space David and then what's being passed ultimately to the function is technically something like this but it's doing it all dynamically it's not me typing in David
33:59
Speaker A
as I I secretly as I discreetly did earlier it's figuring out dynamically what that value is after concatenating hello with the value of name and then passing that ultimately to print as the sole argument let me pause here to see
34:13
Speaker A
if there's any questions on numbers of arguments now to functions can we use a function uh many times to solve a certain problem which we can encounter many times in our code you can you can can use a function
34:28
Speaker A
many different times to solve some problem what we'll soon see though is if you find yourself as the programmer solving a problem the same way again and again and again it turns out you'll be able to make your own function so that
34:40
Speaker A
you don't have to keep reusing the basic ones that come with the language I was curious about the comma and the plus sign so after plus sign can we give just one variable and after Comm again we give multiple variables like what is the
34:56
Speaker A
difference a good question so in the context of strings and I keep using that term string is a technical term in a programming language and again it means a a sequence of text a character a word a whole paragraph even so the plus
35:10
Speaker A
operator is not just used as we'll see for addition of numbers in Python like we do on paper pencil but it also is used for concatenation of strings on the left and the right if you did want to
35:21
Speaker A
combine not just two strings left and right but a third and a fourth you can absolutely keep using plus plus plus plus and chain them together just like in math eventually that's going to start to look a little ugly I dare say
35:34
Speaker A
especially if your line of code gets long so there's better ways that we'll actually soon see and a good question as well well let me come back to the code here in question and see if we can show
35:44
Speaker A
you just a couple of other ways to solve the same problem along the way emphasizing that what we're technically talking about here yes are strings but there's even a technical term for these strings in Python it's just stir so to
35:55
Speaker A
speak St for short for string as you may know if you programmed in other languages people who invent programming languages like to be very uh succinct to the point so we tend to use fairly short phrases to describe things not
36:08
Speaker A
necessarily full words so while you might say string technically in Python what we're really talking about these sequences of text are technically stirs this is an actual type of data in a program but we'll soon see that there's
36:21
Speaker A
other types of data in programs as well in fact let's see if we can't improve this in one other way I like the progress we've made by keeping everything on the same line hello comma David all on the same line what more
36:34
Speaker A
though could we do in terms of solving this problem well it turns out that we didn't have to give up entirely with using print twice let me rewind a little bit and go back to that earlier version where I wasn't really sure how to solve
36:47
Speaker A
this problem so I was using print once to print out just the hello and the space and the comma and then I used print again to call uh to print name that strictly speaking wasn't bad but there was this visual side effect that I
37:00
Speaker A
just didn't like it just looked ugly to have these two lines of text separate from one another but there's another way to fix this clearly it seems to be the case that the print function is automatically outputting a blank line
37:14
Speaker A
it's moving the cursor automatically for me to the next line because that's why I'm seeing hello on one line and David on the next and then my prompt the dollar sign on the line below that so print seems to be presuming
37:26
Speaker A
automatically that you want it to move the cursor to the next line after you pass it some argument but you can override that behavior again functions take arguments which influence their behavior you just have to know what those arguments are and it turns out
37:41
Speaker A
that if we look at the documentation for Python's print function we can actually look up at this URL here docs.
37:49
Speaker A
python.org is where all of Python's official documentation lies if I poke around I can find my way to more specifically this URL here where I can find all of the available functions in Python that and the documentation therefore and if I go a little more
38:04
Speaker A
precisely I can even find specific documentation for the print function itself and rather than pull that up in a browser I'm going to go ahead and highlight just one line from that same URL which is this and this is easily the
38:16
Speaker A
most cryptic thing we've seen yet but this is the official documentation for the print function and one of the best things you can do when learning a programming language is honestly learn to read the documentation because truly all of the answers to your questions
38:29
Speaker A
will in some way be there even though admittedly it's not always obvious and I will say too Python's documentation isn't necessarily the easiest thing especially for a first time or novice programmer it too just takes practice so try not to get overwhelmed if you're not
38:43
Speaker A
sure what you're looking at but let me walk you through this example this again is a line of text from Python's official documentation for the print function what this indicates as follows is this the name of this function is of course
38:55
Speaker A
print then there's a parenthesis over here and another Clos parenthesis way over there everything inside of those parentheses are the arguments the potential arguments to the function however when we're looking at these arguments in the documentation like this
39:11
Speaker A
there's technically a different term that we would use these are technically the parameters to the function so when you're talking about what you can pass to a function and what those inputs are called those are parameters when you
39:24
Speaker A
actually use the function and pass in values in inside of those parentheses those inputs those values are arguments so we're talking about the exact same thing parameters and arguments are effectively the same thing but they terms you use from looking at the
39:38
Speaker A
problem from different directions when we're looking at what the function can take versus what you're actually passing into the function so what does this imply well this syntax is pretty cryptic but at the moment just know that an
39:49
Speaker A
asterisk a star and then the word objects means that the print function can take any number of objects you can pass in zero strings text one string like I did two strings like I did or technically infinitely many if you you
40:03
Speaker A
really want though that code's not going to look very good after that we see a comma then we see another parameter here called sep short for separator in English and notice the equal sign and the single quote space single quote so
40:17
Speaker A
quote unquote space I don't know what that is yet but I I I think we've seen a hint about it let's focus though for a moment on this the print function takes another parameter called n and the default value of that parameter
40:30
Speaker A
is apparently based on this equal sign and these quotes back sln and what is backs slash n if you'd like to chime in the chat anyone who's programmed before has probably seen this though if you've never programmed before this might look
40:43
Speaker A
quite cryptic back sln means new line and it's a way textually of indicating if and one you want the computer effectively to move the cursor to the next line create a new line of text and so technically if we
40:59
Speaker A
read into the documentation we'll see more detail on this the fact that there's a parameter called end in the documentation for the print function just means that by default this print function is going to end every line with
41:12
Speaker A
back slash n you don't literally see backs slash n you see a new line you see the cursor moving to the next line now by that logic let's move backwards sep for separator the default value of separator is apparently a single Blank
41:27
Speaker A
Space well where have we seen that well recall in an earlier example when I passed in not just one but two arguments to the print function recall that they magically had a space between them in fact they had that space plus my own
41:40
Speaker A
space and that's why I deleted my space because at that point it was extra so this just means that when you pass multiple arguments to print by default they're going to be separated by a single Space by default when you pass
41:51
Speaker A
arguments to print it's the whole thing is going to be ended with a new line now just by knowing this and let me let me literally wave my hand at the rest of the documentation for another day there's more things that print can do
42:03
Speaker A
but we're going to focus just on sep and on end let's see if we can't leverage this now to solve that original problem the original problem was this I don't like how hello comma David is on two different lines well that's happening
42:15
Speaker A
again because print is automatically printing out a new line so let's tell it not to do that let's Tell It by passing a second argument to the first use of print to say end equals quote unquote not back sln which is the
42:31
Speaker A
default automatically let's make it quote unquote nothing else let's override the default value so there is no new line there's literally nothing there and let's see what happens let me now go down to my terminal window and clear it and I'm going to run python of
42:48
Speaker A
hello.py enter I'm going to type in my name David and I think now everything's going to stay on the same line because and it did this line here five is going to print out hello comma space but then
43:01
Speaker A
nothing at the end of it because I changed it to be quote unquote the second line is going to print the name David or whatever the human's name is and it will move the cursor to the next line because I didn't override the value
43:13
Speaker A
of end there just to see this more explicitly if you do something cryptic like well I have no idea what's going on let me just put in temporarily three question marks here we'll see the results of this too let me go back down
43:25
Speaker A
to my terminal window run python of. hi what's your name David and now you see literally really ugly output but you see literally what's going on hello comma space then three question marks and that print statement and then you see d a ID
43:42
Speaker A
so not a good out outcome but it demonstrates just how much control we have here too and let me rewind further recall that in our other version of this when I passed in hello comma and name they were separated by a single space so
43:57
Speaker A
Pyon of hello.py D Aid enter that just worked well what if we override the value of sep for separator instead of being one space we could say something like uh question mark question mark question mark just to wrap our minds
44:13
Speaker A
around what's going on there let me now do python of hello.py David enter and you see two these two inputs hello comma and the name are now separated in an ugly Way by three question marks Mar s because I've overridden the default
44:29
Speaker A
behavior of sep and even though the documentation uses single quotes I've been in the habit of using double quotes in Python you can use either strictly speaking it doesn't matter but you should be consistent and I generally always use double quotes Python's
44:42
Speaker A
documentation though always uses single quotes questions now on these types of parameters and allow me to propose that we give these an official name up until now when we've been passing values to print those are called positional parameters positional in the sense that
45:00
Speaker A
the first thing you pass to print gets printed first the second thing you pass to print after a comma gets printed second and so forth but there's also these things we've now seen called named parameters named sep separator or end
45:14
Speaker A
end D for the line ending those are named parameters because one they're optional and you can pass them in at the end of your print statement but you can also call uh use them by name this may be aird question but I was wondering uh
45:29
Speaker A
what if someone wants to like add actually qu quotation marks within the quotation marks yeah I like how you think this is what we would call a corner case right just when we've made right this is this is all sounding great
45:43
Speaker A
at least as as programming goes but wait a minute what if you want to print a quote that's a really good question well let's see if we can't figure this out suppose that I want to print out not
45:53
Speaker A
just the user's name let me simplify this further let me go ahead and get rid of a lot of this and let me just say something like hello um maybe I'm being a little sarcastic here hello friend you know in
46:07
Speaker A
that kind of tone well this is not going to work actually because you are trying to use quotes to be like friend in finger quotes but you're also trying to end the sentence and if I try running this let's do this python if hello.py
46:19
Speaker A
you'll see that this is just invalid syntax perhaps you forgot a comma and this is actually a bit annoying sometimes the error messages you see are misleading like the computer the language doesn't really know what's going on so it gives its best guess but
46:31
Speaker A
it's not necessarily correct but I can solve this problem in a couple of ways I can do this I can change my outermost quotes to single quotes because recall a moment get I said you could use double quotes or single quotes so long as
46:44
Speaker A
you're consistent so that's fine if you use single quotes on the outside you can then use double quotes on the inside and you'll see them literally so for instance if I run python of hello.py there we go hello friend but there's
46:57
Speaker A
another way if you insist on using double quotes as you might want to just to be consistent you can also use that backslash character again we saw the backs slash n a moment ago and that meant we don't want a literal n to be in
47:11
Speaker A
the output we wanted a new line so the backslash actually represents what's called an escape character an escape character is one that you can't just type necessarily once on your keyboard you need to express it with multiple characters so I can actually put
47:25
Speaker A
backslashes in front of these inner double quotes so that the computer realizes oh wait a minute those aren't literal those aren't quotes that finish or start the thought they're literal quotes So now let me go back to my
47:37
Speaker A
terminal window run python of hello.py enter and now it's working as well so escaping is a general technique that allows us to do that too and if I may let me rewind now on these examples and go back to where we left off with my
47:52
Speaker A
code I'm just undoing all of that because I want to get back to the point ultimately of specifying now a a final way of solving this problem well it turns out that we have yet another way we can
48:05
Speaker A
solve this problem which is perhaps the most frequently done now or at least the most elegant when it comes to setting us up for longer and longer uh uses of strings you can use a relatively new feature of python that allows you to do
48:21
Speaker A
this you can literally put not the name of the variable like that in your string because we already saw this is right if you do this you will literally see hello comma name but what if I do this what if
48:32
Speaker A
I put curly braces or curly brackets around the variable's name notice vs code is actually very subtly changing the color of it so vs code knows something interesting is going on here let me run this program but I'm not done
48:44
Speaker A
yet python of hello.py enter David enter okay obviously not what I want but I need to tell python that this is a special string this is what we're going to call a format string or an F string a
48:57
Speaker A
relatively new feature of python in the past few years that tells python to actually format stuff in the string in a special way and the symbol via what you do this is a little weird but this is what the world chose if you put a f at
49:11
Speaker A
the beginning of the string right before the first quote Mark that's a clue to python that o this is a special string let me format this in a special way for you let me now rerun the program python
49:24
Speaker A
hello.py enter David enter and now we see the goal this whole time hello comma David we don't start with this way because I think if we did this the first way you'd be like why are we doing this
49:35
Speaker A
what are all these magical symbols but this is just yet another way to solve the same problem but let me propose that we consider now yet other things we can do with strings and it turns out that even as we've been doing some relatively
49:48
Speaker A
simple operations here we've generally been trusting that the user is going to cooperate and that is to say that they're going to actually type in what we want them to type now now just because they type A String though
49:58
Speaker A
doesn't mean it's going to look the way we want you and I honestly as humans are actually in the habit on websites and apps of like accidentally hitting the space bar a lot either at the beginning of our input or at the end maybe because
50:10
Speaker A
the space bar tends to be so big it's pretty common to get accidental spaces before or after some users input you and I are definitely in the habit of not necessarily capitalizing words like we should if we're sending text messages
50:22
Speaker A
we're probably being a little quick and just sending everything in lowercase for instance if that's your style if your phone's not fixing it for you maybe in a formal letter you would capitalize things properly but you and I as humans
50:32
Speaker A
we can't really be trusted to type things in a nice way necessarily when using some piece of software be it an app or website or something else but it turns out that strings themselves come with a lot of built-in functionality and
50:44
Speaker A
you can see all of that in Python's own documentation here the string data type that we've been talking about comes with a lot of functionality built in that means that we can manipulate the user's input to do more than just join it with
50:57
Speaker A
something else like hello we can actually clean it up or reformat it in a way that hopefully looks a little better for us so let me go back to my code here and let me just demonstrate what might
51:08
Speaker A
happen if a user doesn't cooperate if I go ahead here and run python of hello.py enter let me just sloppily hit the space bar a few too many times why I just wasn't paying attention and I'm going to
51:20
Speaker A
type in my name da viid and I don't know I hit the space bar a couple more times like it's kind of a mess it's all lowercase that's not going to necessarily look grammatically right it's got spaces here and here the
51:30
Speaker A
program is going to print exactly that and that looks really bad at least if we're prioritizing Aesthetics and grammar like why are there so many spaces after the comma this is not a very nice way to greet your users but we
51:42
Speaker A
can clean this up it turns out that built into Strings which again is this data type so to speak this type of data in Python is the ability to actually do things to that string so let me do this
51:55
Speaker A
I can actually go ahead and do something something like this uh name equals name.
52:01
Speaker A
strip and what does this do remove Whit space from string and what do I mean by this well on the right hand side notice I've written the variable name called name I've then used a period or a DOT and
52:18
Speaker A
then I seem to be doing what's a function right anytime we've seen a function thus far we see it's the the function's name print or input then we see a parenthesis then another parenthesis and that's exactly what I
52:28
Speaker A
see here but I'm using this function a little differently technically this function is in this context called a method and what do I mean by that well if name is a string AKA stir well it turns out according to the documentation
52:41
Speaker A
there's a lot of functions that come with strings in Python and you can access that functionality by using the name of a string like literally name here then a period Then the name of the function and then an open parenthesis
52:55
Speaker A
and a closed parenthesis Maybe some arguments inside of those parentheses but in this case it doesn't need any arguments I just want to strip the space from the left and the space from the right of the user's input but that's not
53:07
Speaker A
enough I want to remember that I've stripped off that white space on the left and the right so I'm going to use the equal sign again here and notice that just as before this doesn't mean equality this means assignment from
53:18
Speaker A
right to left so when this line of code here name. strip returns to me AKA a return value it will return the same thing that the user typed in but with no more white space to the left or to the
53:30
Speaker A
white to to the right so then the equal sign assignment is going to copy that value from the right to the left thereby updating the value inside of my name variable so you can not only assign values to variables you can absolutely
53:46
Speaker A
change the value of variables by just using the assignment operator the equal sign again and again and again and it will just keep copying from right to left whatever the new value should be so now now if I rerun this program python
53:59
Speaker A
of hello.py enter I have Davi oh let's do it again space space space space space daav ID in all lowercase space space enter it's better it hasn't fixed my capitalization so I'm still being a little sloppy with the first D but it
54:15
Speaker A
has stripped off all of that extra space super Minor Detail right like this isn't all that exciting but it just speaks to the power of what you can do with just a single line of code now what else can I
54:27
Speaker A
do here well I could capitalize the user's input let me go ahead and try this it turns out that I could also uh do this name. capitalize so let me go ahead and capitalize uh user's name and again I'm
54:42
Speaker A
making comments and there's no one right way to write the comments I'm just using some short English phrases here to remind myself of what I'm doing what's now going on here well let me go ahead and run python of hello.py enter uh
54:53
Speaker A
space space space space space DAV ID space space enter okay now it's looking prettier right no matter how the user typed in their name even a little sloppily I'm now fixing that but let's let's try something I'm getting a little curious here how about
55:07
Speaker A
this uh space space space space space David space maen I'll use my last name now enter okay so ironically capitalize is not really capitalizing everything we want it's clearly capitalizing what just the very first letter so it turns out
55:25
Speaker A
that again there's other functions in in Python that come with strings and if we poke around the documentation scrolling through a URL like that I bet we'll find another solution one of which is actually this let's actually change this
55:38
Speaker A
to title there's yet another function that come with strings called title that do title based capitalization just like a book or a person's name capitalizing the first letter of each word and this is just going to do a little more work
55:52
Speaker A
for us so let's go ahead and run this and as an aside I'm kind of tired now at this point of typing python python python all the time it turns out that when using a command line interface like this you can
56:04
Speaker A
actually go back through all of your old commands what I just did a moment ago was I hit the up arrow that immediately goes back through my history of all of the commands I've ever typed so this is
56:13
Speaker A
just a faster way now for repeat myself than typing everything manually let me go ahead and hit enter uh space space space space space DAV ID mailin space space all lowercase enter now it's it's looking better now I've capitalized
56:29
Speaker A
things and cleaned things up but what about my code I've got like eight lines of code now four of which are comments four of which are actual code do I really need this much well not necessarily watch what I can also do in
56:41
Speaker A
Python let me not bother capitalizing the user's name separately let me say this and capital uh capitalize users name I can chain these functions together I can add title to the end of this and now what's happening well again with a line of code
56:59
Speaker A
like this you first focus on what's to the right of the equal sign then we'll get to the left of the equal sign what's on the right of the equal sign this line here well what does this mean get the
57:09
Speaker A
value of the name variable like daavid space m n then strip off the white space on the left and the right that is going to return a value it's going to return da ID space m n without any white space
57:23
Speaker A
to the left or right what do you want to do with that return value you want python to title case it that is go through every word in that resulting string and fix the first letter of the first word the first letter of the
57:35
Speaker A
second word and so forth and then now we can finish our thought copy the whole thing from right to left into that same name variable and you know what I can take this even one step further why don't we go ahead and do this if we want
57:49
Speaker A
let me get rid of all that and let me just do strip and title all on that first line and now we've gone from like eight lines of code to four it's a lot tighter it's a lot neater and even
58:02
Speaker A
though reasonable people might disagree it's arguably better because it's just easier to read fewer lines of code fewer opportunities for mistakes it just allows me to move on with my next problem to solve all right let me pause
58:16
Speaker A
here and see if there's any questions on these methods a method is a function that's built in to a a type of value like these functions are or on F strings which we saw a moment ago yes hi thanks
58:30
Speaker A
David um so is there a way to remove the spaces between the spaces that I might have added a short answer no if you read the documentation at that same URL earlier you'll see that strip removes from the left and the right but not in
58:43
Speaker A
between in fact there's two other functions that come with strings one's called L strip the other's called R strip that allow you to do one or the other if we want to start getting rid of space in the middle we're going to have
58:53
Speaker A
to do a different trick Al together how many functions can we combined like this do stripe do title you have combined so how many we can combine yeah a really good question technically as many as you want but at some point your codee's
59:09
Speaker A
going to start to look really really bad right because the line of code's going to get really really long it's eventually going to maybe wrap around again and again so at some point you just kind of say like uhuh that's too
59:19
Speaker A
many and you start breaking it up into multiple lines like I did maybe reassigning the value to the variable as needed and this is actually a good question if I can pivot div off your question I mean what do people think if
59:31
Speaker A
we could go ahead and put everyone's hands down for a moment let me ask this is the way I've done this now with strip and title and input all in the same line better than my previous approach in Zoom
59:46
Speaker A
you can use the yes icon or the no icon if you think this version is better say yes if you think this previous version was better for instance this one here where we had everything broken out say no and then we'll see why in just a
60:04
Speaker A
moment I proposed earlier that reasonable people can disagree and that's absolutely the case doing it one way or the other isn't necessarily best at least if you can justify it let me go back to the most recent version
60:18
Speaker A
here all right so we're seeing a lot of yeses and a lot of NOS why don't we go ahead and and call on one of the yeses if if we could someone who's voting yes why do you think the current version of
60:30
Speaker A
this code is indeed better than the previous longer version of the code I think it's more readable so I can say hey this is the name fun this is the name variable it gets some input and then remove the space and give it a
60:45
Speaker A
title and there you go you have a Hello name yeah I think that's pretty reasonable it's very readable at least if you're in the habit as you are in English of reading left to right it just kind of flows very naturally as a result
60:55
Speaker A
the lines is not really that long it's certainly fitting nicely onto the screen so I think that's a good argument how about a Counterpoint though someone who voted no if we could call on someone who thinks this is worse uh because it's not
61:07
Speaker A
avilable at all uh it seems like uh it's a very long uh line so I think it's better to separate yeah I I think that's persuasive too right it's getting a little longer and even though my sentence here what's your name is
61:24
Speaker A
relatively short you could imagine that this could get even uglier quickly if I were asking a longer question of the user that's going to make this line of code even longer and therefore less readable it might be less obvious to me
61:35
Speaker A
or my colleagues that I am calling strip or that I am calling title it might be kind of a unexpected surprise so I think that's reasonable too in short there is no right answer here and in fact part of
61:46
Speaker A
the process of getting better at programming is getting your own sense of style or working for a company where they might prescribe which way is better than the other because they just want everyone doing the same thing even
61:57
Speaker A
though reasonable people might uh disagree ultimately though so long as you have what's a pretty good argument in favor of one way or the other like ultimately that's what's important if you're just doing things because you don't really know which one's better
62:10
Speaker A
that's not great but if if and when you start to acquire opinions and if your boss if your teacher if your colleague your friend can challenge you and say wait why did you do it like this they might not agree with you but at least
62:21
Speaker A
have an answer and that should be sufficiently persuasive in general now strings come with a whole bunch of other methods as well among which is one called split which can as the name suggests split a string into multiple
62:33
Speaker A
smaller substring so to speak for instance if the human here is in the habit of typing in their first name then a space and then their last name and you want to go ahead and greet them only by
62:42
Speaker A
first name well we could actually leverage that single space between the first name and last name and split that string into two smaller substrings how can we do this well let me go ahead and in between these lines proactively
62:54
Speaker A
comment that we're about to split user's name into first name and last name and then let's go ahead and take that name variable which currently contains something like presumably David space Ma and let me go ahead and call split and
63:09
Speaker A
pass in as the argument to split a single white space thereby indicating that I indeed want to split on that character now it turns out split's going to return a sequence of values ideally a first name and then a last name and we
63:21
Speaker A
can actually in Python assign both of those values from that sequence at once to some variable for instance first comma last equals and that's going to have the effect from right to left of putting the first such value in the
63:33
Speaker A
first variable the second such value in the second variable so now on my last line of code I can go in and say hello not to the full name something like David man I can just say hello comma
63:44
Speaker A
first all right let's go ahead and clear my terminal window run python of hello.py and hit enter I won't bother with any leading Whit space this time but let me go ahead and type in David space maen and crossing my fingers is as
63:56
Speaker A
usual hello David is what we now see all right so we've seen so much so many examples thus far involving strings but certainly programs uh and programming languages can manipulate other types of data as well let's go ahead and
64:11
Speaker A
transition then to another very common type of data in Python in programming more generally namely integers otherwise known in python as int int so just as stir St Str is short for string so is INT in Python short for integer well
64:25
Speaker A
what's in an integer well just like in math it's a number like -2 Nega 1 0 1 2 and all the way toward negative Infinity all the way toward positive Infinity but there's no decimal point in an integer
64:37
Speaker A
it's just a number like -2 Nega 1 0 1 and two onward that's an INT of course in the world of mathematics there's lots of symbols that we use and we've seen plus before although we used it for
64:49
Speaker A
different purpose but python supports these symbols and more and python allows you to add numbers together plus subtract numbers uh multiply numbers divide numbers and the only one here that might look a little strange to people or unfamiliar is this percent
65:04
Speaker A
sign but it doesn't mean percent in this context if you use a single percent sign in a Python program that's actually the so-called modulo operator the operator that allows you to take the remainder after dividing one number by another so
65:18
Speaker A
we'll see examples of that before long but the first four of these are perhaps quite quite familiar well it turns out that in Python you cannot necessarily you don't necessarily have to keep writing code in a file like hello.py and
65:33
Speaker A
then running it in a terminal window one of the features that many people like about python is that it supports this a so-called interactive mode like you can start writing python code and immediately execute each of those lines
65:46
Speaker A
interactively if especially if you don't care about saving all of your lines of code you just want to execute code and get back some answers so for instance let me go back to VSS code here and let me close hello pi and let me click on
65:57
Speaker A
the Little Triangle over here in my terminal window just to make it much bigger just temporarily for a moment so I'm not creating any piy file now I'm just going to run python by itself at my prompt and you'll see when I do this I
66:11
Speaker A
get some cryptic looking output and the date and time at which the program was last updated and so forth but I ultimately get three triple uh brackets like this this is the interactive mode for python so I'm running the python
66:26
Speaker A
interpreter and anytime I type A Comm a line of code in The Interpreter it's going to execute it immediately I don't have to keep running python again and again it's as though in the human world if you were standing next to a human who
66:38
Speaker A
speaks some other language and you're just having a conversation with them back and forth It's all happening the translation immediately so what might I do in interactive mode well I could do something like 1 + one enter that's
66:50
Speaker A
actually code right you might not think of it as code but if you know a bit of arithmetic and you know uh numbers and you know plus that's valid python code and you can use Python really as a fancy
67:01
Speaker A
calculator but I could do other things too if I want to print to myself hello comma world I can also print out that line of code there too hello world so it's interactive in the sense that the moment you execute a line of code boom
67:14
Speaker A
you see the result we're generally not going to do that because at least when teaching the language we tend to want to do things incrementally and we want you to be able to see where it is we came
67:24
Speaker A
from and we want to be able to try things again in again especially if we make mistakes but know that this is indeed a feature of python this so-called interactive mode but let's focus for a moment now not just on that
67:34
Speaker A
interactivity but really on the fact that python apparently supports integers and Mathematics and some of those basic operations and let's see if we can't make maybe our our own little calculator so let me go ahead and open up vs code
67:46
Speaker A
again and I'm going to shrink down my terminal window and I'm going to create a new file called calculator. piy so to do that recall I can type code down here here and the name of the file I want to
67:57
Speaker A
create Pi enter that gives me a new tab up top so I have already closed hello.py I'm now in calculator. piy and let's just make a simple calculator that does some addition for me but I'm going to do
68:09
Speaker A
it in a file so that we can iterate on this and make changes For Better or For Worse over time let me go ahead and first declare a couple variables I'm going to do the mathematical thing of calling my first variable X my second
68:21
Speaker A
variable Y and then I'm going to give myself a third variable Z equals x + y and then I'm going to go ahead and print out Z now this program admittedly not very exciting or interesting in fact it's a little less interesting than
68:35
Speaker A
printing stuff on the screen like before with strings but we'll build on this and see what other features exist in Python that we can leverage so hopefully if python knows its math as well as I do when I run python of calculator. piy I
68:49
Speaker A
should see hopefully that 1 + 2 equals indeed three all right so not that surprising and not that that interesting and honestly this isn't the most useful program because it's always going to calculate 1 + 2 equal 3 let's at least
69:04
Speaker A
make this program say a little more interactive right we already know from previous examples how we can get input from the user let's bring back that input function and let's do this let me go ahead now and at the top of my code
69:16
Speaker A
let's change X to not be the number one always let's change it to be whatever the return value is of asking the user for x and I can use any English or human language I want here I'm going to say
69:27
Speaker A
what's X just like I asked before what's your name and I'm going to do the same thing for y I'm going to use input again but this time change the question to be what's why all right at this point I
69:38
Speaker A
think I'm going to leave the rest of the code the same Z equals X Plus Y and then print Z but what's nice now is that I think I have a nice interactive calculator right now it's not going to
69:49
Speaker A
do 1 plus two all the time it's going to do whatever the user types plus whatever the user types so let's try this let me go ahead and run the program all right let's do it one is going to be x two is
70:01
Speaker A
going to be Y and of course everyone in agreement 1 + 2 equals 3 huh what's going on there either your math class misled you or I have misled you why don't we call on someone here to see if you can't help
70:21
Speaker A
us reason through what the bug is what's the mistake uh on jalli if I'm saying it right I think the issue is is that it's concatenating strings because you use the plus operator instead of adding perfect so perfect intuition we've seen
70:35
Speaker A
that plus is used a little differently in the context of strings because it concatenates that is it joins the two strings and that seems to indeed be what's happening here even though the user types a number but the interesting
70:47
Speaker A
thing here is that when you get user input because they're using a keyboard on their Mac or PC or their phone it is always going to be text it might look like a number but by default it's coming
70:58
Speaker A
from the keyboard as a string that is as text and so how do we go about re uh resolving this if ultimately we don't want to treat those inputs as strings we want to treat them as actual numbers
71:10
Speaker A
well we need another function and it turns out in Python that you can convert sometimes from one type of data to another type of data for instance from string to int by doing something like this let me go back into my code and let
71:24
Speaker A
me change X before adding it to Y to be whatever the integer version of X is plus whatever the integer version of Y is so it turns out that int is not only a type of data in Python it's also a
71:39
Speaker A
function and it's a function that if you pass in an input like a string so long as that string looks like a number like one or like two it will convert it to an actual number that you can perform
71:51
Speaker A
mathematics on instead so if I now go back to my terminal window and run Python and let me show you another trick calculator is kind of a long word it's a little tedious to type notice what I can
72:02
Speaker A
do in my terminal window in a command line interface in general if I start typing C for calculator I can actually hit tab to finish my thought so autocomplete is possible in a terminal window like this type the first letter
72:16
Speaker A
or few letters and then boom with tab it'll finish your thought for you or you can go back in your history like I did with the up and down arrows let me go ahead and execute this what's X X1
72:26
Speaker A
what's X2 and there we go now we have a general purpose calculator that's going to support not just uh addition of one and two but now any two integers that the user types and let me now improve this right we've seen how we can make
72:40
Speaker A
improvements to code and I don't know if it's going to necessarily be better but let's try this do I really need the Z variable it's worth noting that I'm creating a variable called c z and then I'm immediately using it on the next
72:54
Speaker A
line of code now that's not that compelling because if you're creating a variable and then immediately using it but never again using it did you really need to take the time to introduce another symbol and another variable just
73:06
Speaker A
to use it once and only once well maybe not maybe we don't really need Z in this way maybe I should go and do something uh like this maybe I should get rid of Z here maybe I should change this to be
73:22
Speaker A
int up here change this to be int up here here doing something that's pretty interesting now even though it's a bit of new syntax notice that you can Nest function so to speak you can put one function call that is the use of a
73:39
Speaker A
function inside of the use of another function so that the return value of the inner function becomes the argument to or the input to the outer function so just like in math if you have parentheses parentheses parentheses your
73:52
Speaker A
teacher probably taught you to focus on what's inside the innermost parenthesis first and then work your way out same thing with programming that's what Python's going to do it's going to look at what's inside of the parenthesis first it's going to get the answer and
74:05
Speaker A
then it's going to pass the return value to the outermost function so what happens on line one now is that the input function gets called first then the result of that quote unquote one becomes the input to the int function
74:19
Speaker A
and same on line two the output of what's y becomes the input to this int function and now there is no Z I could just do print x + y and because I've taken the time to convert each of those
74:34
Speaker A
strings to an integer I think we're okay so let me try this python of calculator.
74:39
Speaker A
piy enter one and two and we're still getting three not 12 or not 12 one two we're indeed getting three and we've additionally gotten rid of the variable because we didn't necessarily need it it seems especially if only using it once
74:54
Speaker A
well here too let me put everyone's hands down for just a moment and let me ask as before this version now which uses int around the invocations of input and does not use Z is this better than the previous version if you want to vote
75:09
Speaker A
yes go ahead or if you prefer the old Way vote no the old way I'll undo all of this as we vote instead looked like this all right and let me go back to now the newest version let's take a hand of
75:25
Speaker A
the is someone who thinks this latest version is better I think this way is better because it uh allows us to immediately see what the X and Y variables are with um integers and so we know what to expect from them and also
75:44
Speaker A
the print argument is more U intuitive we avoid too much clutter uh in the codes I think those are all good reasons it's nice and succinct the lines of code are not very long uh I don't need to know what Z is
75:58
Speaker A
because it doesn't exist it just see print X Plus y I like that but someone who prefers the older way where we did have Z and we more explicitly passed individual variables to the int function yeah hi uh I think the earlier version
76:12
Speaker A
is better because when uh I mean if user inputs something else other than in let's say I mean let's say the type one and two like so it be it will be easier to debug this version or the this
76:26
Speaker A
version here or the old version the old version okay that's fair and in fact I'm I'm being very careful today as best I can not to mess up I have thus far only inputed integers when I'm expecting integers and R is actually pointing to
76:41
Speaker A
something we'll come back to in the coming weeks how do we actually handle errors what if the user doesn't type in the number one or the number two or a number at all what if they type in a
76:49
Speaker A
word like cat c a t that's not a number and I bet I can't convert it to an integer but for today I'm not going to focus on that I'm just going to hope that the user cooperates but that's not
76:59
Speaker A
going to be the case and so perhaps one way would set us up for more success when it comes to handling those errors now for today's purposes which is better h i mean I like both and I think both of
77:08
Speaker A
you made very valid arguments in there too so long as you have a justification that feels pretty reasonable I mean that's what ultimately matters but acquiring again a sense of the tradeoffs here well is this way better if so why
77:22
Speaker A
or why not just understanding what those trade-offs are but generally speaking prioritizing readability is a very good thing making your code readable for someone else is a very good thing and very good for you too so that when you
77:35
Speaker A
wake up the next morning or you come back the next week or the next year you too can read your own code without having to waste time trying to remember what you did and simplicity tends to be a good thing too keeping your code
77:46
Speaker A
simple so is as you get more comfortable with programming you might be tempted to try to like combine an entire program into one long line for instance let me do right just that that don't technically speaking we don't really
77:57
Speaker A
need X in a variable we don't really need Y in a variable we could also do this I could just get rid of X and Y Al together I could then now eliminate that and make it just one line of code okay
78:10
Speaker A
so on some sense you might be inclined to think wow that's really nice you made it one simple line of code I would argue this actually isn't that simple now I think I'm starting to Nest too many things I have to think about print and
78:23
Speaker A
int and input I then have to notice that okay I've opened two parentheses I've closed two of them there's a plus you're making me think too much and anytime you make me think you're wasting time and anytime you complicate the look of the
78:35
Speaker A
code like this you're just going to increase the probability of mistakes syntactical mistakes or logical errors in your code so of all the things we've done this is the only one that I would argue yes it's one line and it's nice
78:48
Speaker A
and compact it's just not readable enough I would shy away from doing this especially since two of those function calls are getting input from the user but there too reasonable people might disagree but that's the kind of like
78:59
Speaker A
visceral reaction you should have sometimes when code starts getting a little too complicated a little too clever perhaps for its own good all right well it's not just integers we have access to let me propose that we transition from integers
79:15
Speaker A
to one more data type here namely a float so again a string is a sequence of text an INT is an integer like negative 1 0 and one a a float is a number with a decimal point properly called a floating
79:29
Speaker A
point value and you can think of the floating Point as being the decimal that might be over here or over here with some number of digits to the left or the right mathematically it's a real number a number that has a decimal point in it
79:40
Speaker A
so that's a third type of data that python supports right now our calculator is somewhat naively assuming that the user is only going to type in integers but if I want to support floating Point values too I think I can just make a
79:52
Speaker A
couple of tweaks so I'm going to go back to VSS code here and instead of just converting the user's input X and Y to integers on line one and two let's just make a simple change let's actually convert it to a float on the first line
80:06
Speaker A
and a float on the second line here now I think if I go down to my terminal window and run python of calculator. Pi let's type in a number like 1.2 with a decimal point and 3.4 with the decimal
80:19
Speaker A
point and there we go we have 4.6 as the final answer so that wouldn't have worked before if I were only expecting integers from the user but now that I'm support expecting floating Point values and accommodating it I can actually now
80:31
Speaker A
do floating Point arithmetic as well but suppose that I don't really want the final answer to be a floating point value like 4.6 I would be happy if we just round to the nearest integer so I want to support the user typing in
80:46
Speaker A
floating Point values with decimal points but at the end of the day I just want to round the result to the nearest possible integer for instance well it turns out out that here too python comes with some functionality built in and in
80:59
Speaker A
fact if we return to this URL from earlier where in all of the Python built-in functions are listed there's one called round which does exactly as we would expect it takes as input a number and then rounds it for us for
81:11
Speaker A
instance to the nearest digit to the nearest integer but if we look a little closer at that documentation as we can here I'll provide an excerpt this is what the function looks like in the documentation and recall that earlier we
81:25
Speaker A
looked at the documentation for print and this is similar in spirit that this shows us not just the name of the function but it's available parameters that is inputs that we can provide when using this function but this is a little
81:37
Speaker A
cryptic too just like Prince was and it adds some syntax so let's see the name of this function here is of course round and its first argument is a number notice this times there's no star there's no star objects like there was
81:49
Speaker A
for print the round function takes just one number as its first argument period that's it positional parameter but notice this syntax and this is a convention in programming or technology more generally generally speaking when you see square brackets in documentation
82:05
Speaker A
like this this means that you're about to see something optional and so what this means is that if you want to specify more precisely the number of digits that you want the round function to round to you can specify it here by
82:19
Speaker A
adding a comma and then that number so if we read the documentation if you don't specify a number of digits you just specify the number to Round it rounds to the nearest integer but suppose you want to round to the 10's
82:32
Speaker A
place or the hundreds place that is one or two digits after the decimal point you could additionally pass in comma one or comma 2 to be more precise so that's what the documentation there is saying let's see if we can't then translate
82:46
Speaker A
this to some actual code for us so if I go back now to vs code and I consider that I want to go ahead and round X and Y I can do this in a couple of ways I
82:57
Speaker A
could do round X+ y but uh you know I'd actually kind of prefer to break this now out into two lines I don't have to and reasonable people here might disagree but I'd like to revert to a scenario where I'm printing Z so that I
83:10
Speaker A
can just a little more clearly to myself to others say Z equals the rounded result of x + y it's not necessarily the better way to do it but I'm a little more comfortable with breaking out my thoughts one at a time especially if I
83:23
Speaker A
want to start commenting of these chunks of code all right let me go down to my terminal window now and run python of calculator. Pi what's X let's do 1.2 again then let's do 3.4 and now it was
83:35
Speaker A
previously 4.6 but now it's been rounded up to the nearest integer which of course is going to be five all right what if I wanted to change this a little further what if I wanted to support maybe really big numbers big numbers
83:51
Speaker A
irrespective of rounding let's just do something like this let me go ahead and run python of calculator. Pi again and let me just add 999 + 1 and notice I don't have to type decimal points even though I'm
84:04
Speaker A
converting to float my program will just allow me to type decimal points but I don't need to oblige the answer of course here should be and is in fact 1,000 whether or not we round so that's just arithmetic with integers here but
84:17
Speaker A
in uh the us we tend to format long numbers by putting commas uh after or before every triple of digits other countries flip it and they use periods and commas instead that's a system setting you can change that on your own
84:31
Speaker A
Mac or PC or device for python or any language but for me I'm using the uh us approach here which is periods for decimal points and commas for separators what if I wanted this to be outputed as 1 comma
84:45
Speaker A
0000 just to make it a little more clear that it's 1,000 and not something like 100 that's even more useful when it's like 1 million 1 comma 00 comma 00 0 wouldn't it be nice if we could automatically output those numbers as
84:59
Speaker A
well well it turns out that we can there is a way using python to actually specify that we want to include commas like this and here we have an opportunity to bring back our old friend the F string first let me do something
85:14
Speaker A
that's not that productive first let me do this let me print out the value of Z but wait a minute I can't just say quote unquote Z because that's literally going to print Z on the screen so let me wrap
85:25
Speaker A
it with those curly braces like I did before but that two was not enough I literally needed to add an F at the beginning of my string to tell python that this is an F string a format string
85:35
Speaker A
that now is going to print out not very interestingly just the value of Z itself so that I'm going to Great Lengths just to print Z when really I could have just passed Z as the sole argument but just
85:47
Speaker A
to ensure that I haven't broken it let's do this again 999 + 1 enter okay it's still a th so I didn't make anything worse but notice and this syntax is unfortunately a bit cryptic notice that I can actually do this I can put a colon
86:02
Speaker A
after the Z and I can put a comma thereafter this looks very cryptic admittedly and even I have to constantly look things like this up in the documentation to remember the syntax but here let me run it again python of
86:15
Speaker A
calculator. 9991 and now notice that the number has been automatically formatted for me if I were in a different country or local I could abs absolutely override this to use periods instead of commas or vice versa but in this case here it's just
86:30
Speaker A
happening for me automatically so there too we see a hint of what it means to really format a string there's even more power more powerful capabilities built into that all right let me pause here to see if there's any questions now on
86:42
Speaker A
floats on rounding or on this use of f strings yes so I have a question so when using floats um is it like a cap to how many decimal points you can have a really good question so floats yes and
86:57
Speaker A
this is a problem we'll revisit before long floats cannot represent numbers infinitely precisely in a nutshell because computers only have so much memory they only have a finite amount of memory you and I only have a finite uh
87:10
Speaker A
amount of Hardware inside of the computer so at some point they're going to have to Round right now I'm rounding automatically effectively computers will eventually have to do that for us but we'll see that as a fundamental problem
87:21
Speaker A
before long allow me to turn back just for a few final examples on Flo before we introduce a few final examples that allow us not just to use functions but to make our own let me propose that we
87:32
Speaker A
also try our hand at a bit of division here let me propose that we modify this calculator now to still take a couple of floats but let's now just do something a little simpler than uh a little different from this just doing x ided y
87:45
Speaker A
and let me go ahead and get rid of my format string and just keep it simple for now printing out Z instead and what are we going to see here well just some simple division so python of calculat Pi
87:55
Speaker A
let's do something like 2 / 3 and of course I get 66666 and to Ethan's question a moment ago it does seem to be finite it's not rounding in a weird way here but I only seem to see so many
88:08
Speaker A
digits that's a uh an inevitability of using a float in this way by contrast just so you know integers nowadays in Python can be as big as you want them to be unlike other languages there is no upper bound on how big an INT can be now
88:21
Speaker A
in Python but there is a bound on just how precise prise a floating point value can be all right now that I've got some simple division working here let's go ahead and round this it would be nice to
88:31
Speaker A
round this really long number 6666666 and so forth to maybe just two decimal places we've seen how to do this with round though at least in its documentation let's just round this not to the nearest int by passing in just x
88:45
Speaker A
/ Y which is one argument once the math is done inside of the parenthesis I don't want to pass in just one argument I want to pass in two so that I can specify n digits number of digits which
88:56
Speaker A
recall was the second parameter for round let me go ahead and run python of calculator. Pi I'll do the same thing two and then three 67 so here too we see a way of rounding now not just to a
89:08
Speaker A
nearest integer but to a nearest number of digits but there's another way to do this here and in fact this evokes our our uh F F string example again let me go ahead and change this suppose that you didn't remember the round function
89:23
Speaker A
or for some reason you didn't want to use it you instead want to just use a format string well let's go there let me do quote unquote Z but let me surround it with those curly braces let me add
89:34
Speaker A
the F at the beginning and again this is not interesting yet this is just going to print out Z but I'm adding a lot more complexity to turn it into an F string but notice I can do something else after
89:44
Speaker A
my variable name after the colon if this were going to be a big integer I might want to use a comma like before to separate each triple of numbers with commas but I don't I'm going to use a
89:55
Speaker A
different sequence uh of characters I'm G to say 0 2f and this too is one of these very cryptic things I have to constantly look up because I forget if I don't use it that often so don't be
90:07
Speaker A
intimidated if this looks especially weird but this is according to the documentation the way you specify using an F string how many digits you want to print so let me run this version of the calculator type in two and then three we
90:20
Speaker A
get the exact same thing but again this is just consistent with my claim that in program we can so very often solve the same problem in multiple ways this is just now the F string approach to that very same problem all right which one is
90:35
Speaker A
better it depends in this case they're pretty equivalent you could imagine though it being useful to use a function sometime so that you can pass in an argument like n digits as that second argument or you can imagine just
90:47
Speaker A
deciding in advance that you want Point 2 and then writing it like this let's transition now from focusing on string and on integers and on floats to focusing now on functions themselves we began today by focusing on how you can
91:00
Speaker A
use functions that come with python but wouldn't it be nice if you could invent your own functions especially if to our Point earlier you find yourself solving the same kind of problem again and again it's nice that python comes with the
91:12
Speaker A
print function because it's really useful to be able to print things on the screen but wouldn't it be nice if you could print specific things on the screen by just calling your own function well let me propose that we do this let
91:22
Speaker A
me go back to VSS code here and let me propose that we go back to hello.py I'm going to reopen hello.py where we left it before and I'm going to go ahead now and propose that we consider how we can
91:34
Speaker A
start improving this further by making our own function I have written so many programs today that just say hello and each time I'm using print but wouldn't it have been nice if from the beginning of today we could just call a function
91:48
Speaker A
called hello that just says hello for us now the authors of python years ago didn't think that we a special function just to say hello but I would like that to exist I'm saying hello so many times I just want to be able to call a
92:01
Speaker A
function hello so I'm going to start from scratch here I'm going to delete all of my code from earlier and I'm going to pretend for the moment that a function called hello exists and I'm going to do just as I did before I'm
92:12
Speaker A
going to get the user's name with the input function asking what's your name question mark and now I'm going to call a function hello and then I'm going to print out the user's name now I will admit hello doesn't exist so bad things
92:27
Speaker A
are about to happen but let's see what let me go down to my terminal window let me run python of hello.py I think the first Line's going to be okay because that worked before and indeed it's prompting me for my name
92:39
Speaker A
so let me type in David the second line of code is apparently calling a function that looks like it's called hello because why is it a function it has a parenthesis and a Clos parenthesis immediately after it and that's what
92:50
Speaker A
every function we've used has looked like but Python's not going to recognize this one when I hit enter now I get a name error name hello is not defined did you mean help I didn't although it's opportune that's what I need at this
93:03
Speaker A
point is some help but I am encountering this error because why the function just doesn't exist so how do I make this function exist well I need to create it myself using this keyword defa defa for Define so here too just as stir is short
93:20
Speaker A
for string and int is short for integer def is short for Define if and when you want to Define create invent your own functions you can do so using now this keyword in Python so let me go back to
93:33
Speaker A
my code here and let me propose that we Define this perhaps in this way at the very top of my file I'm going to first take a moment to define a function called hello using def hello open parenthesis close parenthesis colon what
93:49
Speaker A
this means now is that python is going to treat every line of code that I IND underneath this one as the meaning of this new function hello So Def is important as is the space I get to choose the name of the function and I'm
94:03
Speaker A
choosing to call it hello the parentheses with nothing inside means that this function at the moment is not going to take any inputs no arguments there too the colon means stay tuned for some indentation everything that's indented beneath this line of code is
94:17
Speaker A
going to be part of this function it's going to be a super short function one line of code it's just going to print out quote unquote hello but now on lines one and two I have invented my own function hello notice
94:30
Speaker A
these dots that have now magically appeared here this is just a setting of my text editor VSS code in this case that's just making super explicit to me that I've hit the space bar four times or equivalently the Tab Key once which
94:42
Speaker A
is converted automatically to four spaces generally speaking I'm going to need to make sure that all of my indented code lines up now so that python knows that it's all part of the same thing but it's easy in this case
94:53
Speaker A
cuz it's just a single line but now thanks to lines one and two the function hello will absolutely exist when I'm ready to use it on line six so let me go down to my terminal window and run
95:05
Speaker A
python of hello.py enter here comes my name again and now when I hit enter I now see hello David all right we've kind of regressed though right this is not nearly as pretty as it once was I think
95:18
Speaker A
we can probably do better than this by improving things further why don't we consider though how we might say parameterize the same function that is to say can we customize hello to maybe take the user's name as input so that we
95:33
Speaker A
can say not only hello but the person's name all on one line all in one breath well I think we can do this let me propose that we do this as follows let me go ahead and up in my code let me
95:46
Speaker A
inside of these parentheses let me come up with my own parameter name I have complete Choice here and I'm going to say that the name of of my parameter will be the word two why because I want my function to sound like the verb it
96:00
Speaker A
represents hello but who do you want to say hello to well I'm going to call my parameter for this function to just CU in English it kind of sounds nice to me hello to who do you want to say hello to
96:11
Speaker A
that's why I'm calling this parameter to instead of something simpler like X or Y or Z all right well what do I want to do with the word to well I can do a couple of different things we've seen like so
96:21
Speaker A
many different ways to implement hello let me just add a comma there for grammar's sake and then let me put the word to after that as the second argument to the function hello there's other ways we can do this and we've seen
96:33
Speaker A
so many but this one looks a little clear to me I'll say what's going to happen next well I don't think I need this extra print line here I think what I'm going to do is this I'm going to go
96:44
Speaker A
ahead here and print out not the person's name manually I'm going to inste instead say hello parentheses name so what am I now doing on lines one and two I'm defining my very own function called hello but this time that function
97:00
Speaker A
has been designed to take a parameter a single parameter as input and I'm using the value of that parameter which I called two to plug into print so that I see not only hello but also that person's name what am I doing on line
97:15
Speaker A
five same as always I'm just getting the user's name line six I'm not only calling hello I'm passing as input the name variable as an ARG argument so that that's what gets passed into hello and what's Happening Here is essentially
97:28
Speaker A
this even though the variable is called name here when the function itself is called the computer assumes that that same value is now called two so name is essentially copied to another variable called two so that in the context of
97:45
Speaker A
hello I can say hello to that variable instead and we'll see in a moment what happens if we don't keep those uh straight let me go ahead and run python of hello.py enter what's your name and now I'm crossing my fingers enter there
97:59
Speaker A
we go we're back in business but now I have my own custom function called hello that's allowing me to say hello to a specific person and here's where now things can get really fancy what if you wanted your hello function to say hello
98:11
Speaker A
to someone specific but you know what if you don't know who you want to say hello to you want to say hello to the whole world you can give parameters default values we've seen that recall that with print there was a default value for sep
98:24
Speaker A
for the separator there was a default value for end the line ending we can do that too and here's the syntax if you want the value of this parameter by default if not provided by the programmer to be equal to quote unquote
98:38
Speaker A
world you literally do that in the same line you're defining the function and I'll admit it's starting to look more cryptic but I'm still just defining a function called hello it takes a parameter called two but I'm assigning
98:52
Speaker A
it with the equal sign a default value of quote unquote world just in case the programmer doesn't call hello with an argument and we can see this here let me change my code to use hello in two ways
99:05
Speaker A
on line five I'm going to very simply call hello no arguments then on line six I'm going to get the name line seven I'm going to call hello with an argument so you'll see hello now being used in two
99:16
Speaker A
ways let me go ahead and run python of hello.py I'll type in my name oh interesting notice I already see hello world but that's expected because line five happens before line six but once I type my name now the program is going to
99:31
Speaker A
be a little more polite and say hello to me personally so there too we see with relatively simple but new syntax how you can Implement functionality very similar in spirit to what the print function gave us automatically now you have
99:46
Speaker A
control over doing that yourself but let me now make this point too one of the whole points of defining your own function is one just to avoid having to repeat yourself again and again you don't have to actually keep Reinventing
99:59
Speaker A
the wheel and keep using the print function again and again and again if you just want to say hello wouldn't it be nice now if I could kind of move this code that I wrote for defining the hello
100:10
Speaker A
function and just to be dramatic I'm going to hit enter a whole lot of times 50 lines down and put my definition of hello way further down in this file why well just in the spirit of out of sight
100:22
Speaker A
out of mind because if I now rewind to the start of my program now you can sort of take for granted that oh hello is a function why because it's there on line one and it has an open parenthesis and a
100:32
Speaker A
closed parenthesis which up until now has meant call this function and then on line two we're getting a variable from the user by typing in their name and then we're calling hello passing in that value well at this point I can just take
100:44
Speaker A
for granted that hello exists even if it's way down further in the file or as we'll see in future weeks even if it's in a different file altogether but there's a problem here and let me go ahead and run this version of
100:56
Speaker A
hello.py notice that as soon as I run The Interpreter python of hello.py I see a name error name hello is not defined again did you mean help well again fitting I do need some help here but I didn't mean to call the function help
101:12
Speaker A
the problem here though is that python is just taking me literally I have defined my function hello all the way down here but I'm trying to use it way up here and that's not allowed Python's interpreter is going to take you
101:23
Speaker A
literally and if you use a function it must already exist by the time you are calling it so how do I fix this well apparently I can't do that I have to Define any functions I want at the very
101:34
Speaker A
top of my file but that too could get me into a bit of trouble eventually because if I constantly have to define a function above where I want to use it you're kind of writing code in Reverse you're constantly writing functions up
101:46
Speaker A
here up here up here as opposed to like writing your code logically top to bottom so let me fix this in a more standard way which is to do this generally speaking you do want to put the main part of your code at the top of
102:00
Speaker A
your file and in fact I'm going to go so far as to Define my function called main it's not a requirement but it's indeed a convention and this just connotes to the reader that this is the main part of my
102:11
Speaker A
program I'm going to get rid of my empty hello call now and only pass in one version with hello name and then down here a couple lines further down I'll actually Define my hello function unfortunately now that I've reordered
102:25
Speaker A
the functions in this way by putting the main part of my code at the top and hello at the bottom so that my logic kind of flows top to bottom if I go ahead and run python of hello.py enter
102:36
Speaker A
nothing whatsoever happens if I do it again nothing whatsoever happens well why in the world is this well just because I've defined a function called Main and I've defined a function called hello doesn't mean that I've actually called that is used either of them yes
102:52
Speaker A
I'm using hello in side of main but no one is telling python to actually use or call Main so in order to tidy this up the last thing I need to do in this file it seems is actually call my main
103:05
Speaker A
function and in fact by calling my main function in this way it gets me out of trouble because now I'm defining main first but I'm not calling hello yet I'm defining hello next but I'm not calling hello next I only at the very end of
103:19
Speaker A
this file call Main which has the effect of running this code up here which has the effect of running this code down here and it allows me therefore to organize my file and Order My functions in any way I want including main at the
103:33
Speaker A
very top and solving ultimately that problem of python not knowing what's going on now it's important to note that I defined my function hello as taking an argument to and then I passed into that function the value of the variable that
103:46
Speaker A
I wanted to say hello to that is the variable called name because suppose I had done something a little bit differently suppose that I hadn't defined hello is taking an argument so I just remove mention of two and its
103:58
Speaker A
default Value World and I go back up to my main function and I just call hello itself without passing in any arguments and now let me go ahead and make one more change one more mistake technically let me go ahead and just try to naively
104:12
Speaker A
print out the value of name in the hello function so now to be clear in my main function on line two I'm defining my variable called name and assigning it the return value of the input function from the user I'm then just calling
104:24
Speaker A
hello in my hello function which now no longer takes any arguments I am calling print passing in hello comma and then immediately passing in name the variable into which I got the user's input but the catch is that name exists now only
104:40
Speaker A
in Maine and so watch what happens when I try to run this version of the program with python hello.py I hit enter I'm prompted for my name DAV ID enter and ah a name error name name quote unquote is
104:52
Speaker A
not defined so it turns out that this is actually an issue of what's called scope scope refers to a variable only existing in the context in which you defined it so in so far as I Define this variable
105:04
Speaker A
name in my main function I can only use that variable in my name function I can't use it as I've tried to here in my hello function it doesn't exist in that so-called scope and so this is why now
105:16
Speaker A
if I rewind and undo all of those changes you'll see that I'm deliberately passing main from my main function into my hello function and now in the hello function it technically has a different name it's called two in that context but
105:30
Speaker A
that's fine it's completely up to each individual function to name its own variables or name its own arguments but this is a way now that I'm handing to the hello function the value of that variable so it can be printed by hello
105:42
Speaker A
as well and there's one final flourish we can add here now that we've implemented hello you'll notice that hello only has a so-called side effect it only prints out something to the screen well what if I also want my
105:55
Speaker A
function to not have a side effect per se but actually hand me back a value recall that the input function returns a value the string that the user typed in recall that the int function returns a value the float function returns a value
106:10
Speaker A
that was passed into it well you can use one final keyword here literally return to return a value explicitly yourself in fact let me go back to VSS code here and I think we'll return our attention to calculator. Pi and see if we can't
106:27
Speaker A
Implement one other version of calculate calculator. pi that actually has our own function that even returns a value so I'm going to go ahead and open up uh calculator. pi and I think this time I'm going to throw everything away as before
106:41
Speaker A
and I'm just going to start practicing what we're preaching here Define a function called main which is now going to be the main part of my function let's go ahead and now declare a variable called X and assign it to the converted
106:55
Speaker A
version of the user's input after asking them what's X so again a line of code quite like we've done before and suppose now that what I want to do is square this value I want to take the number
107:06
Speaker A
that the user typed in and raise it to the power of two so 2 squar would be 4 3 squar would be 9 4 squar would be 16 and so forth well how do I go about implementing a function literally called
107:18
Speaker A
Square which actually doesn't come with python built in well let me assume for the moment that it does exist and let me say something like this let me go ahead and say that uh printing how about uh X2 is
107:33
Speaker A
comma square of X so what have I done I've defined a function called Main and I've implemented two lines the first of these lines prompts the user for a value X and converts it to an INT and stores
107:46
Speaker A
it in a variable called X on line three I then say x^2 is and then I pass a second argument to the print function whatever the return value is of a square function but Square doesn't exist and I'll show you this here if I now call
108:01
Speaker A
Main at the bottom and I run python of calculator. Pi I'll see that X is two and then I see a whole bunch of Errors a name error name square is not defined so this isn't a typo here it's just the function
108:17
Speaker A
doesn't exist but I think I can make it exist here let me go ahead and Define another function called Square this one's going to take in a number and I'm going to call it generically n as many a programmer would just to
108:29
Speaker A
represent any old number and then what do I want to do in order to square n well a numbered squared is really just itself times itself so I'm going to do this n * n but it's not enough just to
108:42
Speaker A
do the math yourself n * n you're going to have to return the actual value n times n and that's our new keyword here when I now do this Watch What Happens python of calculator. Pi enter X sh say
108:56
Speaker A
shall be 2 x^2 is 4 let me go ahead now and say x is now three X2 is now 9 so I've implemented my very own function that Returns the square of a value and because I'm using the return keyword
109:11
Speaker A
that ensures that I can pass the return value of this just like the return value of input or int or float to another function like print instead and here too there's going to be so many ways to solve the same problem I can actually
109:24
Speaker A
raise n to the power of two we've not seen the syntax before but if you use two two asterisks like this two stars that raises the thing on the left to the power on the right or it turns out there
109:35
Speaker A
is in Python a function called pow for raising something to the power that takes two arguments the first of which is the number the second of which is the exponent so there too there's just so many ways to actually solve that same
109:47
Speaker A
problem as well so ultimately what we have we done here we first introduced functions these or verbs many of which come built into python that you can just use in your own code we then introduced variables via which you can store those
110:00
Speaker A
return values and then maybe do something more with it at the end of the day too you now have the ability to create to invent your own functions to solve simple problems like hello or in the weeks to come much more
110:10
Speaker A
sophisticated more challenging more fun problems as well [Music] [Music] all right this is cs50's Introduction to programming with python my name is David men and this week we focus on conditionals conditionals or conditional statements in Python and in other
110:51
Speaker A
languages are this ability ility to ask questions and answer those questions in order to decide do you want to execute this line of code or this line of code or this other line of code instead they allow you to take the proverbial Forks
111:04
Speaker A
in the road within your own code logically so how might we go about making some of these decisions well it turns out that python comes with a lot of built-in Syntax for instance here are just some of the symbols you can use in
111:16
Speaker A
Python to ask questions admittedly mathematical questions but we'll start there if only to keep the example simply simple early on this first symbol as you might know for math represents greater than the second symbol might not look too familiar because we usually write it
111:30
Speaker A
all as one thing on a piece of paper but on a keyboard if you want to say greater than or equal to you'd use this symbol Instead This of course means less than this means less than or equal to and
111:42
Speaker A
this one's a bit of a curiosity we've seen in our look at functions and variables how we were able to assign values to variables using a single equal sign but that equal sign didn't repres represent equality it represented
111:54
Speaker A
assignment from right to left that's great because it solved that problem but it kind of left us in a bit of a bind because how do we now compare two things left and right well in Python and in
112:04
Speaker A
many languages you actually use two equal signs so two equal signs represents equality comparing the thing on the left and the right one equal sign as always represents assignment copying the thing from the right to the left lastly this last symbol represents not
112:20
Speaker A
equal to so the exclamation point or Bang uh followed by an equal sign means not equal to some value next to it well to ask the questions using these symbols or any others we're going to need another keyword in Python and that
112:34
Speaker A
keyword quite simply as in English is if you can ask questions in Python code along the lines of if the answer to this question is true then go ahead and execute this code for me so let's go ahead and write some of these examples
112:49
Speaker A
here I'm going to go over to VSS code and let's go ahead and create a program for called compare. the goal of which is simply to write code that compares values and makes decisions based on those values let's go ahead and type
113:01
Speaker A
code of compare. py in order to create a brand new file called compare in which we'll start to express some of this logic all right well what do we want to compare suppose we want to compare for the sake of discussion just a couple of
113:13
Speaker A
integers but we'd like those integers to come from the user so that we can make uh decisions based on numbers we don't know the values of in advance well let's go ahead and do this as we've done in
113:24
Speaker A
the past let's declare a variable like X let's assign it equal to the return value of the int function and pass to the int function the return value of the input function asking the user a question like what's X question mark As
113:39
Speaker A
we've done in the past let's do this one more time with Y asking the user for the value of y and again uh converting that ultimately to an INT as well so at this am of the story we have two variables X
113:52
Speaker A
and Y Each of which has values and ideally we should be able to now compare these values so suppose I want to make a decision based on the values of these variables I'm going to use the keyword if and I'm going to use some of those
114:04
Speaker A
mathematical symbols to actually ask the question itself so how about this if x is less than y then let's go ahead and just print as much Out quote unquote X is less than y so this isn't a very
114:17
Speaker A
interesting program yet I'm literally just stating the obvious based on the math but it's allowing me to introduce some new syntax and exactly what is this syntax well it's this not just the keyword if which I've added here at the
114:29
Speaker A
start of line four but then I ask my question here x less than y x is one variable on the left Y is one variable on the right and of course the less than sign is expressing the mathematical
114:40
Speaker A
question I have what I've highlighted here is technically called a Boolean expression a Boolean expression named after a mathematician named bull is simply a question that has a yes or no answer or technically a true or false answer and that's nice because if
114:55
Speaker A
there's only two possible answers it's very easy for me and in turn the computer to make a decision do this or don't do this thing now notice if you come from other languages you might notice that I have not typed any
115:08
Speaker A
parentheses they are not in fact necessary at least in this case in Python but I have typed a colon at the end of the line and even more importantly at the next line I have begun my line with some indentation
115:20
Speaker A
hitting the space bar four times or just hitting tab once which will automatically be converted to the same that indentation is what tells python that line five should only be executed if the answer to line Four's question is
115:34
Speaker A
in fact true so if x is less than y that phrase will be printed thereafter well let's add a few more lines of code how about another question If X is greater than y then let's go ahead and print
115:46
Speaker A
that X is greater than y and let's do one final question if x equals y then wait a minute what have I done wrong here right a good eye here I don't want to assign y to x if x equals equals y is
116:02
Speaker A
how I express equality let's go ahead and print out X is equal to Y so I now have a uh three conditions if you will one question asking X less than y one asking X greater than y one asking xals
116:18
Speaker A
equals y let's run the code well down here in my terminal window I'm going to run python of pair. pi and hit enter what's X let's go with one what's y let's go with two this should of course
116:30
Speaker A
execute that first line of code and tell me indeed that X is less than y exactly as I would expect there well what just happened though in code well let's take a look perhaps at this same code uh
116:43
Speaker A
visually particularly if you're a more visual learner this I dare say is what just happened so what we're looking at here is a a flowchart it's a diagram of this program's logic and more technically it shows the program's
116:56
Speaker A
control flow that is the ability of you and code to control the flow of a program generally from top to bottom in fact let me go ahead and zoom in on the top of this flowchart and you'll see an
117:06
Speaker A
oval at the very top that says quite literally start that is irrespective of what shape or layout the diagram is is where your own thinking and logic should start when trying to wrap your mind around this program notice that there's
117:18
Speaker A
an arrow from start to this diamond shape and inside of that diamond is a question a an expression X less than y and this shape just means based on the answer to that question go left or go right specifically go left if the answer
117:32
Speaker A
is true or go right if the answer is false well the inputs I typed were one and two respectively for X and Y so of course one is less than two so that's why my program printed out quote unquote
117:46
Speaker A
X is less than y but recall the code the code then proceeded to ask two more questions is X greater than y is x equal equal to Y well the flowchart depicts those questions too notice that no matter whether the question had an
118:02
Speaker A
answer of true or false the arrows both converge back down to this second diamond shape here and that second diamond shape asks the second question X greater than y that too has a true or false answer so we go one way or the
118:16
Speaker A
other but if x is 1 and Y is 2 then no the answer is false one is not greater than y so so logically in the flowchart you follow the false Arrow this time and notice along that false Arrow you don't
118:28
Speaker A
print anything this time that's why we only saw one print out on the screen now there was still a third question and this flowchart captures that as well the third Diamond asks x equals equals y now that to has a false answer in this case
118:40
Speaker A
because one of course does not equal equal Y and so we again follow the third false Branch here and that leads us of course to stop and stop just indicates that's it for the program so think that's correct and that particular
118:55
Speaker A
flowchart does happen to represent the actual code that I wrote so it's correct it does what it's supposed to do it answered the question correctly by printing on the screen X less than y but what is perhaps poorly designed about it
119:09
Speaker A
let's make this first distinction it's not enough necessarily for the code that you write to be correct and do what you intend longer term especially as our programs get longer and more sophisticated more complicated we're going to want them to be welld designed
119:21
Speaker A
too thoughts on in what way this program is arguably not welld designed even though it's correct let's see here uh khed if I'm saying that right your thoughts too many ifs I think is getting repetitive we can make our code more concise maybe yeah it
119:41
Speaker A
seems a little repetitive I'm asking if this if this if this and yet logically I should know the answer to some of those later questions once I figure one out and in short if you look at this diagram
119:51
Speaker A
here notice that no matter matter whether I go left or I go right I'm always asking three questions no matter what all of those arrows lead to the first the second and the third Diamond so I'm asking three questions no matter
120:04
Speaker A
whether any of those answers are true or false well how might I go about improving this well let me propose that we introduce another keyword to our python vocabulary namely L if and this too is kind of a succinct one it's a
120:16
Speaker A
conjunction of else if in English which allows us to ask a question that takes into count whether or not a previous question had a true or false answer well what do I mean by that well let me go
120:28
Speaker A
back to my code here and let me propose that we now improve upon this here by asking ourselves ultimately how can we ask fewer questions and let me go ahead here and propose that instead of asking if if if let's make these conditions
120:45
Speaker A
potentially mutually exclusive that is to say don't keep answering questions once we get back a true answer so I'm going to change my code up here as follows instead of asking if if if I'm going to say if x less than y l if x
121:01
Speaker A
greater than y l if x equals equals y so I'm going to implicitly just like an English take into account that I'm only going to keep a asking myself these questions if I haven't yet gotten a true response think about the logic here the
121:17
Speaker A
English if x is less than y on line four print out out X is less than y well if that's the case you're done logically because if the English is saying if x less than y else if x greater than y
121:31
Speaker A
those are going to be mutually exclusive if the answer to the first question is true you don't have to keep asking questions to which you already logically know the answer so let me go ahead now and run this program and I think the
121:42
Speaker A
behavior is going to be the same python of compare. Pi what's X let's do one what's y let's do two x is less than y now honestly I didn't really notice a difference when I ran the program and
121:53
Speaker A
honestly my Mac my PC my phone nowadays are so darn fast that these kinds of improvements aren't going to necessarily feel any faster until we're writing bigger faster programs but it's laying the foundation for writing better code longer term now what is the Improvement
122:10
Speaker A
I've just made well if previously my diagram looked like this which was problematic in so far as I was asking three questions no matter what even if I already figur out what I want to print on the screen this new version of the
122:23
Speaker A
program that says if L if L if might look a little something like this instead now it got a little wider that's just because we drew the arrows to be a bit wider here but let's focus on just
122:33
Speaker A
how many questions are getting asked let me zoom in at the top as before and let me propose that we note that the start oval is at the very top and it's asking us to ask one question first X less than
122:44
Speaker A
y is one less than two but notice here let me zoom out if one is indeed less than two we follow this long longer Arrow the down Mark true we print out quote unquote X is less than y but then
122:59
Speaker A
we immediately follow this next arrow down to the icon that says stop so that's what's implied by doing if L if L if if we get back a true answer right away to that first if we're going to
123:11
Speaker A
print out X is less than y and then stop we're logically at the end of the program so this picture is just representing graphically what the code is actually doing but suppose I typed in something else suppose that my code
123:24
Speaker A
actually ran and I typed in two for x and one for y that is to say the answer to the first question is now false but the answer to the second question is now true because of course uh one uh two is
123:38
Speaker A
greater than one well let's go back to the diagram same as before we start at the very top where it says start the very first question up here now X less than y is an answer of false because no
123:50
Speaker A
two is not less than one so we follow this arrow to the next question this diamond is X greater than y well yes 2 is greater than 1 so now we follow this left Arrow which is true we print out
124:04
Speaker A
quote unquote X is greater than y and then stop so what's the Improvement well in the first case we got lucky and we only had to ask one question and boom we're done this time we had to asked two
124:15
Speaker A
questions but then boom we're done only if x happens to equal y do we actually find our elves logically getting all the way down to this final L if in my code and pictorially only if x is equal to Y
124:30
Speaker A
do we find ourselves going all the way down to the third Diamond the third question asking is it equal to y or not now hopefully the answer at that point is not false we've included a false Arrow just so that the program itself is
124:45
Speaker A
well defined but logically we shouldn't actually be getting there anyway because it's got to be less than or greater than or equal to in this case well let me pause here to see if there's any questions now either on the code version
124:57
Speaker A
thereof here or on this diagramming of that very same logic questions here on this control flow uh AR we supposed to put an else at the end ah a good question and yes so that's going to be my my third and Final
125:15
Speaker A
Approach and if you don't mind let's pivot there right away identifying a third keyword that indeed exists in Python that allow ows us to be even better at expressing this logic to design this program even better and that's going to solve a particular
125:29
Speaker A
problem so if I take us back to our code here notice that what I've highlighted earlier L ifx equals equals y it's not wrong to ask that question in fact if you're trying to be especially thorough it makes perfect sense to check if x is
125:43
Speaker A
less than y greater than y or equal to Y but why don't I need to ask this third and and final question we don't need to ask if x is equal to Y anymore because logically if the two conditionals
126:00
Speaker A
evaluate to false there is only one um conditional that will evaluate to true and that is X is equal to Y exactly if we're all pretty comfortable with math and comparisons here of course X is either going to be less than y greater
126:14
Speaker A
than y or equal to Y but once you rule out the first two scenarios logically it's got to be the case that X must equal y if it wasn't the case that it's less than or greater than so hope propos
126:25
Speaker A
that we use this other keyword else and how do we use this well exactly as we might in English let me go back to my code here and instead of bothering to ask the third and final question let's
126:35
Speaker A
not ask a question at all let's just have this catchall so to speak a final line of code that says else just assume that X is equal to Y therefore printing it as well so what's the upside of that
126:47
Speaker A
my code is still going to work exactly the same and again my computer's so darn fast I don't even notice that it's working even faster than it was before but we would notice these kinds of things if we were doing a lot more work
126:58
Speaker A
a lot bigger programs here but let me run python of compare. piy let's do for instance one and two still works for that let's do two and one still works for that let's do one and one and it
127:11
Speaker A
indeed now works for that but in these cases now let's consider the path we just went down previously our diagram when we had if L if L if in place looked a little something like this and notice that again we might have asked one
127:26
Speaker A
question or two or worst case three whole questions but we can do better than that using else as hope proposed we can Whittle this diagram now down to this and even though it looks like the diagram is getting bigger notice that
127:38
Speaker A
it's having fewer uh building blocks inside of it there's fewer arrows and there's fewer nodes in this picture let's start at the top now start leads us to the first question still X less than y if the answer is true great we
127:52
Speaker A
can say as much X is less than y and we can stop if it's not true if it's false we can ask the next question X is greater than y true or false if it is great we can print X as greater than y
128:02
Speaker A
and stop else if it's not the case that X is greater than y the answer is false we can just immediately logically say x is equal to Y we don't have to add the third question at all we can just
128:15
Speaker A
immediately conclude there so what's the implication here you can see with these pictures a relative decrease in the comple it of a program the first one was very long and stringy with lots and lots of questions unnecessarily ultimately
128:28
Speaker A
the next one got a little shorter and this one's even shorter still and again the fewer lines of code you have the less likely you are arguably to make any mistakes the easier it is for other people to read and so generally this
128:40
Speaker A
readability this simplification is indeed a good thing well let's go ahead and add another piece of uh capability into Python and that's this one here just like in English where you can ask this question or this other question you
128:54
Speaker A
can say the same thing in Python using literally this word or so let me go back to my python code here and let's propose how we might ask a couple of questions at once this time perhaps this time
129:05
Speaker A
considering how we might ask not whether or not it's greater than or equal to and caring about the precise answer let's take a a coarser approach here and let's just try to determine is X greater is x equal to y or not well let me go ahead
129:22
Speaker A
delete some of this code and change the question we're asking let me do this well if I care about whether it's equal or not let's check the possible scenarios if x is less than y or X is greater than y let's go ahead and print
129:36
Speaker A
out X is not equal to Y now why is that no pun intended if x is less than y well it's obviously not equal if x is greater than y it's obviously not equal so we can conclude X is not equal to y so if
129:53
Speaker A
we instead want to make sure that it is equal to we can just use uh hopes else using print quote unquote X is equal to Y and again why is this well if x is less than y or X is greater than y
130:08
Speaker A
they're obviously not equal otherwise logically they must be equal in fact so let's run this let's go ahead and run python of compare. Pi what's X One what's Y 2 okay X is not equal to Y let's do it again but two for x one for
130:22
Speaker A
Y X is not equal to Y and one third time how about X is 1 and Y is One X is now equal to Y now if we want to compare that visually too let me propose that the picture looks a little something
130:36
Speaker A
like this and again this is the exact same thing logically but it's a pictoral representation thereof what's the first question well if x is less than y well then we follow the true arrow and we say quote unquote X is not equal to Y and
130:50
Speaker A
then we stop but what if X is not less than y what if it's greater than y what if it's 2 and one respectively then the answer to x less than y's first question is false so we go here we ask the second
131:02
Speaker A
question because of the or and that asks is X greater than y if so notice this we can kind of reuse some of the same parts of this picture and just say X is not equal to Y we don't need to add arrows
131:15
Speaker A
and add boxes unnecessarily we can reuse lines of code uh picture parts of the picture just as we have lines of code and then we stop lastly we have the following if we know that X is not less
131:27
Speaker A
than y we know that X is not greater than y it must be the case that x equals y we don't need to ask a third question another diamond we can just immediately print as much and then say uh stop as
131:39
Speaker A
well well what could I do here I bet I could improve this code slightly and if we really want to be nitpicky I would argue that this is now really just a minor refinement but it's a good habit
131:51
Speaker A
to get into thinking about could my code be better could my code be simpler could I improve this code further it's subtle but could I improve the design could I ask fewer questions could I tighten it up so to
132:07
Speaker A
speak what do folks think you can ask if x is just equal to Y then if you print x equal to Y else X is not equal to Y perfect recall one of the other symbols we saw on the available list earlier we
132:23
Speaker A
can check not just less than or greater than or equal to we can literally ask the question is it not equal to why are we wasting time asking if it's less than or if it's greater than well if all you
132:34
Speaker A
care about is is it not equal I think we can do exactly that let's just ask the one simple question we do care about and so let me go back up here and let me just say not both of these questions
132:44
Speaker A
let's get rid of the or let's just say if X is not equal to Y then go ahead and print X is not equal to Y and that too I think is going to work exactly the same but the picture now looks a little bit
132:57
Speaker A
different notice that this was our flowchart earlier that represented that same logic and there's a bit of complexity you got to go left you got to go right based on the answer to these couple of questions if we now take into
133:07
Speaker A
account what this version of the program looks like it's even simpler perhaps the simplest one we've seen yet when we start off the program we ask just one and only one question is X not equal to Y and if so true we go ahead and print
133:20
Speaker A
out X X not equal to Y if the answer is false then of course it must be equal to Y so we say that instead and if we really want we could invert this if I go back here to my code and if for whatever
133:32
Speaker A
reason you just prefer to think in terms of equal or not equal as opposed to not equal or equal it's really uh up to you we could change this to be equals equals but I'm going to have to change my print
133:46
Speaker A
statements to be in the opposite order so let me go ahead now and reverse these two here and move the second one first and the first one second so now when I execute this code I'm asking still just one question so
133:58
Speaker A
it's still just as good just as succinct but now the diagram instead of looking like this is going to change the not equal to equal equal and we just need to make sure that we print out the right
134:09
Speaker A
thing accordingly and again here too just as the code is getting a little more compact a little more compact with fewer and fewer characters so are these diagrams these flowcharts capturing the relative simplification of each of those programs too all right let me go ahead
134:24
Speaker A
and pause here to see if there's any questions now on any of these versions of code yeah I have a couple of questions uh what if indentation is not used uh if indentation is not used your program will not work so python is a
134:42
Speaker A
little different from a lot of languages in that it enforces the indentation requirement uh some of you who have been programming for years might not necessarily be in the best habit of indenting your code properly and one of
134:54
Speaker A
the features arguably of python is that it makes you indent your code or it will not just work and I think did you have one other question uh yeah uh is the colon necessary is the colon necessary yes the
135:09
Speaker A
colon 2 is necessary so with python what you see is what you get here and indeed it needs to be indented and the colon is necessary python does not use in the same way by Convention as C and C++ and
135:21
Speaker A
Java curly braces to canote blocks instead it relies indeed on this indentation well let me propose that we introduce one other keyword here in Python to see exactly how we might combine additional thoughts and that's going to be literally the word and a
135:35
Speaker A
conjunction of one or two or more questions that we might want to ask at once and let me propose here that we explore this kind of logic by way of another program Al together in VSS code whereby I'll go ahead now and create a
135:49
Speaker A
new program say called grade. Pi let's consider exactly what grade a student should get based on their score on an exam or a test or a quiz or some other assignment like that I'm going to go ahead and run code of grade. py to give
136:01
Speaker A
myself a new file and I'm going to go ahead and start by just getting the user score again on some assignment or test or the like and I'm going to store it in a variable called score equal the return
136:11
Speaker A
value of the int function which is going to convert whatever the user's input is when prompted for this score so again the user should just Oblige by giving me a number like zero or one or two or or
136:21
Speaker A
hopefully much higher than that like 997 98 99 100 assuming the test or assessment is out of 100 percentage points now how could I go about assigning a grade to the student score well in the US it's very commonly the
136:35
Speaker A
case that if you get between a 90 and 100 that's an A and if it's between an 80 and a 89 it's a b if it's 70 and 79 it's a c and so forth all the way down
136:46
Speaker A
to F which should be e but we'll see that there's a bit of a jump so how might I exess this well I can use conditionals and I can ask a few questions and then print out the student's grade accordingly so let me
136:57
Speaker A
express it like this if the student score is greater than or equal to 90 and the student score is less than or equal to 100 so it's in that range let's go ahead and print out that their grade
137:09
Speaker A
shall be in a because they're in the 90s above grades range L if the score is greater than or equal to 80 and the score is less than or equal to say 89 but here I have some options
137:24
Speaker A
logically I can actually express myself in any number of ways and maybe just to be a little cleaner I'm going to say in score is less than 90 so I'm using less than instead of less than or equal to so
137:34
Speaker A
I'm making sure that their boundaries between these grades are correct then I'm going to go ahead and give the student a b if it's in the 80s L if score is greater than or equal to 70 and the score is less than 80 I'm going to
137:48
Speaker A
go ahead and give them a c l if the score is greater than or equal to 60 and the score is less than 70 I'm going to go ahead and give them a d and here's where it's a little anomalous at least
138:00
Speaker A
in some schools here else I'm going to go ahead and give them uh an F so we're skipping e Al together and we're going to give an f instead for the grade so that's the catchall and I think
138:12
Speaker A
logically I've gotten this correct at least based on where I went to school growing up such that it's going to give an A or a b or a c or a d else it's going to ass assume that you got an F
138:22
Speaker A
well let's try just a few of these here let's run python of grade. Pi my score is let's let's start strong 100 all right I got an A didn't do as well the next time maybe it's a 95 still an a
138:34
Speaker A
starting to slip further so I got an 89 the next time that's now say a b and let's say I really had a bad week and it's now like a 71 that's now A C or I didn't even submited at all that's a an
138:46
Speaker A
F Al together all right so it seems to work that's not really an exhaustive test but at least based on some sampling there my code seems to work as I expect but let's see if we can't tighten this
138:56
Speaker A
up it's not wrong it's correct and indeed according to my own specifications I dare say this code is correct but can we tighten it up can we reduce the probability of bugs now or down the line can we increase the
139:07
Speaker A
readability of it and can we increase the efficiency of it can we get the computer to have to answer fewer questions and still get the same result well let's see what we might do let me just kind of switch things up if only to
139:18
Speaker A
demonstrate that we can use these symbols in different ways is I could say as I've done if score is greater than or equal to 90 but I can actually do this I can flip it around instead of saying
139:29
Speaker A
greater than or equal to let's say 90 is less than or equal to score and here let's say if 80 is less than or equal to score and here 70 is less than or equal to score and then lastly 60 is less than or equal to
139:47
Speaker A
score so it's the same thing logically I'm just kind of switching things around just like you could do on paper pencil if you really wanted but now notice this trick and this is not possible for those of you who have programmed in C or C++
139:58
Speaker A
or Java or other languages notice what I can do here is actually combine these ranges notice that I'm asking two questions two Boolean Expressions is 90 less than or equal to score and is score less than or equal to 100 well python
140:14
Speaker A
allows you to Nest these things like this and chain them together and just like you would on paper pencil the real world you can encode in Python do this which is just a little cleaner right it's tightening up the code a little bit
140:27
Speaker A
it's fewer keystrokes it's faster to type it's easier to read moving forward so that's arguably better as well so that's one Improvement it's largely aesthetic in this case it's still asking the same number of questions but it's doing it a little more succinctly still
140:43
Speaker A
well what what more could I do here next well you know what each time I'm deciding these grades I don't think I have to ask two questions I I don't have to ask is it greater than 90 and less
140:53
Speaker A
than 100 is it greater than 80 and less than 90 if I kind of rethink my logic I can maybe do this better still let me propose that we simplify this further and just do this if we know the input
141:06
Speaker A
for the moment is going to be within zero and 100 we can make some assumptions we could say something like if the score is greater than or equal to 90 well the student gets an A L if the
141:18
Speaker A
score is greater than or equal to 80 the student gets a b l if score is greater than or equal to 70 they get a c l if the score is greater than or equal to 60 they get a d else they get an F so what
141:34
Speaker A
have I done here well instead of asking two questions every time checking the lower bound and the upper bound of that range I'm kind of being a little more clever here by asking if the score is greater than 90 well they've obviously
141:48
Speaker A
gotten an A or better if your score is greater than A8 well you either deserve an a if it's really strong or a B if it's just above 80 but because of the if L if logic we've already checked is the student
142:01
Speaker A
score greater than 90 and if it's not then we're asking the question well is it greater than 80 so you implicitly know it's somewhere in the 80 to 89 range else you know it's in the 70 to 79
142:12
Speaker A
range else it's in the next range down so it's a minor optimization that allows us to ask fewer questions but again it's making the code arguably a a little more readable certainly more succinct and then hopefully more maintainable longer
142:26
Speaker A
term any questions then on these types of changes and this type of logic with our code uh what if we don't use l if at all what if we uh write the code in F yeah so that's a good question because it's
142:44
Speaker A
actually going to have an unintended effect here let me get rid of the F temporarily and just focus on a through d if we revert to where we began today's story with conditionals saying if if if if now our cleverness here of using
143:00
Speaker A
broader strokes and not using in upper and lower bound ranges is going to come back to be a downside let me go ahead and run python of grade. Pi and suppose my score is uh 95 I am so darn excited I
143:14
Speaker A
want my a but nope I just got an A a b a c and a d so logic that's broken things because if you don't make these conditions mutually exclusive every one of those questions is going to get asked
143:28
Speaker A
and therefore answered and even if your grade is above a 90 it's also logically above an 80 above a 70 above a 60 and if i' kept it in there I would have failed as well with an F really good question
143:41
Speaker A
other questions here on this form of logic like it would there be any I guess better way to kind of clean up even just this simple statement like we had before the previous one that you had with the
143:50
Speaker A
El oh I I I like your enthusiasm for simplifying things further I'm going to go out on a limb here and say this is about as good as it gets at least using only conditional statements I can if my
144:05
Speaker A
mind wanders think of a slightly more clever way to do this maybe with something called a loop or another programming construct we don't have that yet in our vocabulary but yes there's absolutely other ways to do it but I
144:15
Speaker A
think not yet if we want to restrict ourselves to just words like if and or and else uh and L if and and and the like well let me propose that we pivot now to use another approach here that
144:27
Speaker A
uses one other symbol that up until now we've not really had occasion to use let me propose that we Implement a program uh that we'll call parity in mathematics parity can refer to whether a number is even or odd and that's kind of an
144:39
Speaker A
interesting question and turns out it can be useful in other applications too to I just ask the question is a given number even or odd maybe that the user typed in and let me go ahead and write a
144:49
Speaker A
new program called parity Pi via code parody. Pi in my terminal and let me propose that we use this as an opportunity to introduce the last of those arithmetic symbols at least most of which we're familiar with addition
145:04
Speaker A
subtraction multiplication division but there's been on this list before this last one here a percent sign and it doesn't mean percentage in this case when used as an operator in programming in Python rather it represents the so-called modulo operator for modular
145:17
Speaker A
arithmetic or at least in our case we're going to use it to calculate the remainder when dividing one number by another well what do I mean by that well if you take a number like 1 divid 3 3
145:28
Speaker A
does not go into one eat cleanly so you have a remainder of one two divided three has a remainder of two three divided by 3 has a remainder of zero because it divides cleanly four divided 3 has a remainder of one because you can
145:45
Speaker A
divide it in once but then that leaves one so it has a remainder of one and then lastly something like five divided by three has a remainder of course of two so that's all we mean by remainder how much is left over after dividing one
145:56
Speaker A
number by another well if I go back now to my code and I consider how I might implement the question is this number even or odd let's consider how we might Implement that since it's perhaps not necessarily obvious how we can use this
146:10
Speaker A
additional building block but it turns out it's going to be very useful longer term well let's first just get a number from the user in a variable called X and I'm going to set that equal to the conversion to int of whatever the user
146:21
Speaker A
inputs after asking them what's X question mark and we've done that before many times how do I now determine if x is even or odd well it turns out if I have access to a programmatic operator that tells me the remainder I think I
146:37
Speaker A
can do this in fact let me just ask the group and this is just from grade school math perhaps what does it mean for a number to be even to be clear a number like 0 2 4 6 8 10 12 12 14 16 those are
146:52
Speaker A
all even numbers but what does that really mean Elena if I'm saying that right uh even numbers that can divide it exactly by two for example 2 4 6 8 and 10 and perfect and we could go on all
147:06
Speaker A
day long literally since there's an infinite number of those even numbers but it's nice that you formulated it in terms of a question that we can ask very clearly is this number cleanly divided by two that is can we divide it by two
147:19
Speaker A
with no remainder a remainder of zero well that's perfect because if we have this operator this percent sign that allows us to answer just that what is the remainder we can presumably check is the remainder is zero or is it one do we
147:32
Speaker A
have nothing left over or do we have one left over well let's ask that if x ided by 2 has a remainder of zero as Elena proposes let's go ahead and print out something like quote unquote even and
147:46
Speaker A
just say as much to the user else I think we can assume that if a number is not even it's going to be odd if it's indeed an integer so I'm going to go ahead and print out quote unquote odd
147:57
Speaker A
instead and let's go ahead and now run python of parody. piy in my prompt what's X let's start with two two is in fact even let's start with four four is in fact even let's get thing let's get
148:08
Speaker A
interesting with three three is now odd and I think we could do that all day long and hopefully get back indeed exactly that answer but what more could we do here how could we improve upon this well recall that we have the
148:21
Speaker A
ability to invent our own functions and let me just propose for the sake of discussion that we're going to eventually find that it's useful to be able to determine if a number is even or odd and so we'd like to have that
148:31
Speaker A
functionality built in and I don't think python has a function for telling me just that but I can invent it using Code like just this so let me go into my earlier version here and let me propose that we do this let me go ahead and
148:47
Speaker A
write a main function I'm going to get back into that habit of defining a main function to represent the main part of my program and I'm going to do what I did before I'm going to get an integer
148:56
Speaker A
from the user's input asking them what's X question mark and then I'm going to ask this question for the moment I'm going to naively assume that the function already exists but that's a useful problem solving technique even if
149:09
Speaker A
I have no idea yet where I'm going with this how I'm going to invent a function that determines if a number is even I'm just going to assume that there's a function called is even and I'm going to
149:18
Speaker A
call it blindly like this if is even passing in X then go ahead and print quote unquote even so if this magical function called is even returns true as its return value I'm going to print out that it's even else otherwise I'm going
149:37
Speaker A
to assume that it's of course odd now the one problem with this program even if I call Main over here is that is even does not exist and this program would break if I ran it right now but that's
149:49
Speaker A
okay I have the ability call to invent my own function so let me Define with def a function called is even I want this function to take an argument and I'm going to call it n just a number
150:00
Speaker A
generically I could call it X but again I don't want to confuse myself as to which X is which so I'm going to give it a different name and that's fine I'm just going to call it more generically n
150:09
Speaker A
for number and then I'm going to do this I'm going to say if n percent 2 equals equals z just like before then and here's the magic you the programmer can actually return what are called Boolean values we've seen in Python that python
150:28
Speaker A
has stirs or strings ins or integers Floats or floating Point values all of which are different types of data in python python also has a fourth data type called bull for a Boolean value and even though this is just adding to our
150:43
Speaker A
list the nice thing about bulls is that they can only be true or false an INT can be any number of infinite possible values a bull can only be true or false and it must be capital T and capital F
150:57
Speaker A
if you're writing itself so if I go back now to my code and I consider exactly what I want to return here well if x if n% 2 equals equal Z that is if n / two has a remainder of zero well I think
151:13
Speaker A
it's even to Elena your definition so let's return true capital T else if it doesn't have a remainder of zero I'm pretty sure mathematically it's got to have a remainder of one but it doesn't matter I know it's not even so I'm going
151:27
Speaker A
to return false and we returned false instead capital F and now that we've defined both Main and is even and I'm calling main at the bottom I think I've got this right python of parody. Pi enter what's X let's try something
151:43
Speaker A
simple like two and it's even let's do it again what's X how about four even once more what's X X how about three and it's odd now what have I done here I've just made the point that if I want to
151:56
Speaker A
create my own function called is even that answers this question for me that I can now use in this program and heck maybe future programs that I write I now have a function that no one gave me I
152:07
Speaker A
gave myself that I can use and reuse and I can even perhaps share it with others I'm using that function now on line three just to make a decision I'm using a conditional up there and my Boolean expression something that's true or
152:20
Speaker A
false is going to be not something explicit like X less than y or y greater than x or the like it's going to be a function call I'm using a function as my Boolean expression but that's okay because I know because I wrote it that
152:34
Speaker A
that function is even returns true or it returns false and that's all I need in a conditional to make a decision to print even or print odd so let me pause here to see if there's any questions now on
152:48
Speaker A
how I've implemented is even using this bull hello hi David first of all thank you for this wonderful class uh did before yesterday and today uh I have just one query like bases on my background of java uh there
153:04
Speaker A
when we used to pass the arguments we can also pass the address of the variables so is there any sort of this concept in Python uh short answer no those who are unfamiliar with Java or other languages or C or C++ there's
153:18
Speaker A
generally ways to pass values in different mechanisms that allow you or disallow you to change them in Python no everything we're going to see is actually in fact an object but more on that down the line how about time for
153:30
Speaker A
one more question here on these bulls and these is evens so I actually had a question about um defining a function okay if that's okay sure so if you define one are you like within your code like you made it up are you allowed to
153:45
Speaker A
use the dot operator like we did name. strip and use it like that good question if you've created your own function can you use other functions like strip ortitle or Capital eyes that we've seen in the past um you can use
154:01
Speaker A
those on strings those functions come with strings you can't necessarily use them on your own functions unless your function returns a string for the examples you gave I'm returning a bull bulls have no notion of white space to
154:15
Speaker A
the left or the right you can't call strip you can't call capitalize but if you were writing a different function that that returns a string absolutely you could use those functions as well well let me turn our attention if I may
154:25
Speaker A
back to this example here and consider as we now frequently do can we improve on the design of this code can I make this particular program better and I can there's a couple of ways here and I'll show you something that's now generally
154:38
Speaker A
known as something pythonic there's actually this term of Art in the python world where something is pythonic if it's just the way you do things in Python which is to say we've seen already there's so many different ways
154:50
Speaker A
to solve certain problems and in the python community of programmers there tend to be some ways that are smiled upon more than others and they tend to relate to features that maybe only python has but not other languages and
155:03
Speaker A
here's some syntax that you might not have seen in languages like Java or C or C++ if you've programmed before and if you've never programmed before this too is going to be new instead of asking a question like this if else using four
155:16
Speaker A
lines in Python you can actually collapse this into just just one more elegant line if you will instead of asking if n / 2 has a remainder of zero return true else return false let me delete all of that and just say this
155:34
Speaker A
return true if n / two has a remainder of zero else return false now those of you who do have prior programming experience might actually think this is kind of cool you can condense from four lines into one on line that very same
155:51
Speaker A
thought and one of the reasons why python is popular is that it does tend to read rather like English it's not quite as user friendly as most English or most human languages but notice now the line does rather say what you mean
156:04
Speaker A
return true if n / two has a remainder of zero else false I mean that's pretty darn close to something you might say logically in English be it about even an odd or really anything else so that program is going to work exactly the
156:20
Speaker A
same python of parity. Pi let me type in two it's still even let me type in three it's still odd but I can refine this even further and again consistent with this idea of not just writing correct code but writing better and better code
156:33
Speaker A
but still keeping it readable I can do one even better than this notice this value here is my Boolean expression and it is going to evaluate to true or false is n / two having a remainder of zero or
156:49
Speaker A
not like that is by definition a Boolean expression it has a yes no answer a true false answer well if your Boolean expression itself has a true or false answer why are you asking a question in the first place why ask if why say else
157:08
Speaker A
just return the value of your own Boolean expression and perhaps the tightest version the most succinct and still readable version of this code would be to delete this whole line pythonic though it is and just return n modulo 2 equals equals 0 if it helps let
157:29
Speaker A
me add parentheses temporarily because what's going to happen in parentheses will happen first n / by two either does or does not have a remainder of zero if it does the answer is true if it doesn't the answer is false so just return the
157:45
Speaker A
question if you will you don't need to wrap it explicitly with an if and an else and in fact because of order of operations you don't even need the parentheses so now this is perhaps the most elegant way to implement this same
158:01
Speaker A
idea now which is better this is pretty darn good and it's hard to take fault with this because it's so very succinct but it's perfectly okay and just as correct to have an if and then an else even though it might be four Total Lines
158:14
Speaker A
if that helps you think about your code more clearly and it helps other people reason about it as well so it turns out there's another syntax that you can use to implement the same idea of a conditional whereby you do something
158:26
Speaker A
optionally based on the answer to some Boolean expression and the keyword that you can now use in recent versions of python is called this match match is a mechanism that if you've programmed before is similar in spirit to something
158:38
Speaker A
called switch in other languages for instance let me go ahead here and close out parody. py and let me go ahead and create a new file called house. py and in house dopy I think what we're going to do is try to implement a program that
158:51
Speaker A
prompts the user for their name and then just outputs what house they're known to be in in the World of Harry Potter so for instance let me go ahead and do this let me give myself a variable called
159:00
Speaker A
name set it equal to the return value of the input function and I'll say something like what's your name question mark and then after that I'm just going to use a traditional if L if else construct to decide what house this
159:13
Speaker A
person is in so let me say if name equals equals say Harry as in Harry Potter well let's go ahead and print out Harry's house which is Gryffindor in the World of Harry Potter L if the name is
159:25
Speaker A
instead Hermione then go ahead and print out also quote unquote Gryffindor as she's in the same house too L if name equals equals Ron let's go ahead and similarly print out Gryffindor quote unquote and let's make this a little
159:40
Speaker A
more interesting now L if name equals quote unquote how about Draco Draco Malfoy in the books Let's go ahead and print out quote unquote Slytherin and just in case someone else's name gets inputed for now let's just suppose that
159:54
Speaker A
we don't recognize them and say by default else print out quote unquote who question mark just to convey that we don't actually have a hard-coded response to that particular name let me go ahead now and run this as python of
160:07
Speaker A
house. py enter and I'll go ahead and type in something like Harry and voila we see that Harry is indeed in Gryffindor let's run it one more time python of Housey let's type in Draco this time Slytherin and now let's type
160:19
Speaker A
in an unrecognized name let's go ahead and rerun python of house. py and let's go ahead and type in Padma enter and who because we haven't actually hardcoded with an L if condition in this case uh what house Padma is meant to be in all
160:33
Speaker A
right well it turns out there's other ways to implement this indeed there's some redundancy here in that we're checking if Harry or Hermione or Ron are all in Gryffindor I feel like we can at least tighten this code up a little bit
160:44
Speaker A
using techniques we've seen already so let me go ahead and do this let me go up here and instead do something like this let's get rid of these two blocks of L ifs leaving just Harry's for a moment
160:55
Speaker A
and let's use that or keyword again and say or name equals equals quote unquote Hermione or name equals quote unquote Ron thereby consolidating all three cases if you will into just one if statement then we still have a separate
161:09
Speaker A
L if for Draco because he's not in fact in Gryffindor and then the final El to catch anyone else all right let me go ahead now and run this version of the program python of house.i I'll type in
161:20
Speaker A
hermion this time she too is still in Gryffindor let me try it with Ron and that too still seems to be correct well it turns out there's another approach alog together that can perhaps make your code a little less verbose you could
161:32
Speaker A
imagine how complicated this code might get if we had not just Harry and Hermione and Ron but a whole bunch of other names as well for Gryffindor for Slytherin and for all of the other Hogwart toes so you can imagine that
161:43
Speaker A
code is getting pretty unwieldy pretty fast well it turns out another technique you can use is indeed this keyword called match which is very similar in spirit but the syntax is different and allows you to express the same ideas a
161:54
Speaker A
little more compactly so let me go back to house dopy and let me propose that I get rid of my current if L if else approach and instead do this literally use the keyword match and type the name
162:06
Speaker A
of the variable or value that we want to match on and then I'm going to go ahead and include a colon and then underneath that I'm going to include literally a keyword called case and the first case I
162:16
Speaker A
want to consider is going to be Harry and I'm going to put Harry in quotes because it's a string or a stir and I'm going to have another colon at the end of this line and indented under that one
162:25
Speaker A
I'm going to go ahead and for now print out Gryffindor which of course is Harry's house otherwise I'm going to have another case for quote unquote Hermione and similarly I'm going to have under that indented print quote unquote
162:37
Speaker A
Gryffindor close quote now I'm going to have another case for Ron also in quotes with a colon now print quote unquote Gryffindor and now I'm going to have a other case for let's say Draco this one gets a little more interesting because
162:51
Speaker A
Draco of course now is in Slytherin and then I'm going to go ahead and leave it as that for now so let me go ahead and save this file and go back down to my terminal window running python of house.
163:02
Speaker A
py enter and let's go ahead and try Harry and he seems still to be in Gryffindor let's run it again for Hermione enter Gryffindor let's skip ahead to Draco and type in draco's name he's indeed in Slytherin now let's try
163:14
Speaker A
another name that we haven't uh handled a case for like Padma again enter and we're just ignored there's no output whatsoever because there wasn't a case for Padma now we could of course go back in and explicitly add one for Padma but
163:27
Speaker A
what if we similarly to the else construct just want kind of a catchall that handles anyone whose name is not explicitly specified Well turns out the Syntax for that using this new match statement is to still have another case
163:40
Speaker A
but then to use this single underscore character which is used in other context in Python but for here it's meant to say whatever case has not yet been handled go ahead and print out as we did before for instance quote unquote who with a
163:53
Speaker A
question mark at the end now let's go ahead and rerun this python of house.i I'll type padma's name again and this time I think we're at least going to get an explicit response indicating who whereas previously we did not have the
164:05
Speaker A
equivalent of that now I think we've regressed a little bit we went from tightening things up by putting Harry and Hermione and Ron all in the same line and the same if statement but here we have now three case statements again
164:18
Speaker A
for all three of those well we can tighten these this code up as well but the syntax is going to be a little bit different I'm going to go ahead and delete these two middle cases for hermion and Ron and then up here next to
164:29
Speaker A
Harry's name before the colon I'm going to go ahead and use a single vertical bar and then a quote unquote hermy then another single bar and do quote unquote Ron and this is how using this relatively new match statement you can
164:42
Speaker A
say the equivalent of Harry or Hermione or Ron but more concisely than you could using an if statement alone as we implemented it previously so now one final run of the program with python of house.i let's make sure that Harry is
164:57
Speaker A
still in Gryffindor let's make sure that hermion is still in Gryffindor let's make sure that Ron is still in Gryffindor and indeed all three of them are now as always with python and programming more generally there's going to be different ways you can solve these
165:09
Speaker A
problems this is just another tool in your toolkit arguably it has tighten things up arguably it's perhaps a little more readable because there's a little less syntax going on a little less duplication of equal signs and ell if
165:21
Speaker A
and ell if and ell if all over the place but ultimately this would be an equally correct approach to that same problem but it turns out with the match statement you can do even more powerful forms of matching as well here we've
165:33
Speaker A
used it simply to implement the same idea as that if L if else construct and it's worth noting if you've programmed in some other language the syntax here is indeed correct you do not need for instance a break statement as has been
165:45
Speaker A
peppered throughout and you don't need something like default or something explicit you indeed just use this underscore as your catchall at the end of the match so just by adding in some of these new keywords here like if and L
165:59
Speaker A
if and else we have now the ability to ask questions about values we have the ability to analyze input from users and ultimately make decisions about it and these then were our conditionals lying ahead is going to be the ability for us
166:13
Speaker A
to not only use functions and variables and also these conditionals but also next Loops the ability to do something now again and [Music] [Music] again all right this is cs50's Introduction to programming with python my name is David men and this week we
166:54
Speaker A
focus on Loops this ability in python and a lot of other programming languages to do something again and again a cycle of sorts and let's see if we can't begin by motivating exactly why we have this ability to do things cyclically using
167:07
Speaker A
these Loops I'm going to go ahead here and open up VSS code and in my terminal window let's go ahead and create uh via code cat. py a Python program that meows like a cat and I'm going to go ahead
167:21
Speaker A
here in this code tab very simply perhaps I'm going to start by implementing this cat just by using prints we're going to have this cat not make audible sounds but just print meow meow meow on the screen three times well
167:32
Speaker A
I think the simplest way I can do this is just to print meow once and to print meow again and to print meow One Last Time on the screen and now let me go down to my terminal window let me run
167:45
Speaker A
python of cat. py enter and meow meow meow all right so this program works this program indeed works if my goal is to get the cat to meow three times and let me propose just to help us wrap our
167:57
Speaker A
minds around what's going on inside of the computer let me propose that we consider this flowchart so as before we have this flowchart that starts with a of this oval which just means start reading here and then notice it goes via
168:09
Speaker A
arrows to a meow meow meow and then it stops it's perfectly correct and honestly it's wonderfully simple but I dare say we can find fault with my code nonetheless why is my code arguably poorly designed now the answer is going to be
168:28
Speaker A
Loops in some way but let's see if we can identify in what way the code is actually poorly designed in some sense let's see any thoughts Alex okay so I mean repeating the same action like three times or even more um
168:45
Speaker A
it's not a good habit yeah I'm just repeating myself and honestly it's not that big a deal if we go back to my code here am I really uh doing such a bad thing by just printing meow meow meow
168:57
Speaker A
three times not really but let's consider The Logical extension of this suppose I want to meow four times or five times or 50 times or 500 times do you really think even if you've never programmed before is the solution to
169:10
Speaker A
this problem really going to be to hit copy paste 50 times like probably not we can probably do better than that and Beyond it just being ugly at that point having so many lines of identical code just imagine if you wanted to change the
169:22
Speaker A
code maybe I changed my mind and I don't want to make a cat I want to make a dog so now it has to say woof woof woof multiple times now I have to change that in like 50 different places and yeah
169:31
Speaker A
sure I could do find and replace but come on like we're programmers now there's got to be a better way than just repeating ourselves so I bet we can do better than that if we think about a little harder what we how we go about
169:45
Speaker A
structuring this program and we can do that if we augment our vocabulary just a little bit it turns out in Python and in other languages too there's a keyword called while and while is one way that we can express what's called a loop a
169:58
Speaker A
block of code that's going to do something again and again and again zero times one time two times 50 times as many times as we want but while rather leaves to us the the particulars of how we express ourselves to do something
170:14
Speaker A
again and again so let me go back over to vs code here and let me propose that I do this while is a construct that allows me to ask a question again and again and anytime we've seen a question
170:26
Speaker A
it's been in the form of a Boolean expression a question to which the answer is true or false well how could I do this how could I print out meow three times and ask three times a question to
170:39
Speaker A
which the answer is true or false well what if I did some counting right like literally on my fingers and if I'm trying to count maybe down from three I want to meow three times I can put three
170:49
Speaker A
fingers up and I can meow and then I can put like one of the fingers down and then meow and I can put one of the fingers down and I can meow put one of the fingers down and maybe the question
170:59
Speaker A
I can ask every time I meow is do I have any fingers up still do I have any fingers up still do I have any fingers up still and if the answer is true keep going if the answer is false stop so how
171:12
Speaker A
can I translate that to code well once we've added this while keyword I think we have all the building blocks already let me propose that I do this let me propose that I give myself a variable and I'll call it I for integer but I
171:25
Speaker A
could call it anything I want and I'm going to initialize it to three then I'm going to use this new feature of python while and I'm going to ask a question the answer to which must be true or
171:35
Speaker A
false and I'm going to say while I does not equal zero so I'm going to ask the question while I does not equal zero do the following notice the colon at the end of the line notice my indentation
171:49
Speaker A
and just like with functions just like with conditionals you indent the lines that you only want to execute as part of this other thing what do I want to do while I does not equal zero well I think
172:02
Speaker A
I just want to meow but it's not enough just to write this code if I were to very dangerously run python of cat dopy and hit enter right now what might happen on the screen whether you've programmed before or not
172:22
Speaker A
why is this a very bad thing potentially it's not going to break things but it might it might lose control of my computer somehow any thoughts uh yeah teimo hi uh I think it's going to continue uh to
172:38
Speaker A
print out Mel since I is always equal to three and the W is always true yeah exactly if I'm initializing I to three that is setting it equal to three on line one then I'm asking the question while I does not equal zero and that's
172:53
Speaker A
going to be true it does not equal zero it obviously equals three print meow and the way a while loop works is that the python interpreter just keeps going back and forth it goes from line one to line
173:06
Speaker A
two then to line three and then it goes back to line two to ask the question again if the answer still true it goes to line three it then goes back to line two if the answer is still true it goes
173:17
Speaker A
back to line three and to U's point if you're never actually changing the value of I it's always three you're just going to be looping literally forever and this is an accidental infinite Loop so we've got to be smarter than that and I'm not
173:32
Speaker A
going to hit enter because I don't want to lose control over my computer here such that it's printing out meow forever um fortunately if you ever do do that and you find yourself in an accidental infinite Loop control C for cancel or
173:44
Speaker A
interrupt is going to be your friend if you ever seem to lose control you don't need to like reboot or turn off the computer you can just hit contr C in your terminal window and that will likely fix it all right well what do I
173:57
Speaker A
want to do then after meowing each time I think what I'd like to do here is maybe something like this let me update I to equal whatever the current value is uh uh minus one here whoops sorry minus
174:11
Speaker A
one so if I on each iteration am updating I to be one less one less one less it should eventually hit zero at which point the answer to 9 2's question will now be false so let's see if this
174:27
Speaker A
works I'm going to go down to my terminal window and run python of caty and I indeed get three meows why because I've kind of wired this up kind of like a machine in software if you will I've
174:38
Speaker A
set I equal to three then I keep asking this question but I keep turning the gears I keep changing the value of the variable to make sure that ultimately it is actually being decremented that is decreased by one until we eventually hit
174:54
Speaker A
zero now for those of you who think a little more graphically let me pull up one of our usual flowcharts this is just a representation graphically of the exact same thing notice what's happening I first start the program and then I
175:05
Speaker A
initialize I to three and then I ask the first of my questions again the diamonds always represent questions and the answer is going to be true or false does I not equal zero well it doesn't it equals three so if I follow the true
175:19
Speaker A
line I meow and then I follow this arrow and I update I to equal IUS one at this point in the story I presumably equals two mathematically I Follow the arrow and there's the loop this is why it's
175:31
Speaker A
nice to see this graphically perhaps because you can literally see the loop back and forth now I ask the question again does two not equal zero well it does not equal zero it's two so we meow again we change I from 2 to 1 well does
175:46
Speaker A
one not equal zero well obviously it is not zero so we meow again we decrement I again I is now zero does 0 not equal zero no it equals zero so the answer is false and we stop so there perhaps more
176:02
Speaker A
so than any of our flowcharts before do you really see the structure of what's Happening inside of the program and you don't have to get into the habit of making these charts or creating these charts but just as a first pass at
176:14
Speaker A
what's going on inside of the computer that's indeed one way to visualize it instead well let me propose that like always there's many different ways to solve this problem and suppose you just like to think a little differently maybe
176:25
Speaker A
you don't like starting at three and then counting down to zero y maybe your just brain doesn't work that way and you prefer to count up instead of down totally fine let me go ahead and change my code here to set I equal to 1 instead
176:38
Speaker A
of three and here let me just change my logic rather than checking for not equal to zero like maybe you don't like thinking terms of not because it's a little confusing and it might be let's just check that I is less than or equal
176:51
Speaker A
to three so we'll be a little more explicit we'll count from one up through three each time printing meow but I'm going to need to change this line here let me see if we can't call on someone to change line four for me how do I want
177:04
Speaker A
to change line four to be consistent with counting from one up to and through three I would be plus one every time you meow yeah exactly in this case we want to add one not subtract one and in fact
177:26
Speaker A
if you think about this this two could end very poorly right if you start counting at one and you keep subtracting one subtracting one subtracting one I think we're going to find oursel with the same problem which is that we're
177:37
Speaker A
never going to stop because we're going to keep getting more and more negative as opposed to ever getting up to the number three so I think you're right I need to change this to be IAL I + 1 and
177:48
Speaker A
now notice just for Clarity 2 the equal sign is again our assignment operator from right to left logically this might otherwise strike you as strange like how can I equal itself plus one well it doesn't until you execute this code from
178:02
Speaker A
right to left you add one to I or You Subtract one from I and then you update the value of I on the left the assignment copies the value from the right to the left well how else might I
178:13
Speaker A
do this well I will say that most programmers computer scientists more generally tend to start counting from zero it's a convention and it actually has upsides even in Python and other languages where generally speaking it's a good thing to start counting from zero
178:28
Speaker A
instead of counting like we might in the real world from one let's go ahead and adopt that convention now let me set I equal to zero and I need to make a change now notice if I don't change my
178:40
Speaker A
logic this program just became buggy the cat has a bug it's now meowing four times if I run it as is but the easiest fix here would be to change my inequality to be this less than instead of less than or equal to now I'm
178:56
Speaker A
starting at zero but I'm going up two but not through three and even though this might of all the things we've seen thus far seem maybe the least familiar most of us might start at one two then three it's a good habit to get into now
179:09
Speaker A
start at zero and go up two but not through the value that you care about ultimately three in this case here well let me tighten things up a bit here not only will this now fix my counting problem it now meows three times as
179:23
Speaker A
expected there's a more succinct way to express I equals I + 1 and this is because it's such a popular thing to do in code you can instead just say i+ equals 1 and that's it you don't need to
179:36
Speaker A
put everything on the right hand side this is a special syntax that says the exact same thing increment I but it does it with a few fewer keystrokes it's just a little more pleasant to type it's a little faster to read it's it's just a
179:48
Speaker A
convention those of you who have programmed in C C++ pyth uh not python C C++ Java Java Script might have seen plus plus before or minus minus sorry python doesn't have it so you cannot use that this is a succinct as your line of
180:05
Speaker A
code might get all right let me pause here to see then if there's any questions about these implementations of while Loops um can we use stuff like four Loops which um have a certain I value initialized to it at at the start and it
180:26
Speaker A
runs from the particular condition you put into the um into the thing and increment it as as you go along short answer no you cannot do what you're describing but there is another type of for Loop that we will soon see but let's
180:42
Speaker A
come to that in just a moment other questions on Loops using while here so I had a question about the flowcharts okay uh there were c yeah there were certain symbols for the certain kind of the statements uh sir they are they
181:00
Speaker A
certainly used for that kind of statement that they are put they are so I deliber use anyone I deliberately use certain types of symbols certain shapes here uh whereby in oval is conventional for start and stop I used rectangles for any statement
181:17
Speaker A
of code like an assignment or a printing and so forth and I use diamonds to represent uh questions that you might ask uh conditions as we've seen um if you're doing this for yourself if you're just trying to make sense of your code
181:30
Speaker A
and writing it down you certainly don't need to use these formal symbols but I tried to be consistent with some PR best practices and in fact let me come back to the same picture because this was the first version of our picture but we've
181:41
Speaker A
since modified our code a couple of times this recall was the version where the question we were asking was I not equal to zero let me go ahead and just change this code now to represent the next version we did which recall changed
181:53
Speaker A
our logic to start counting from one it changed our question to check is I less than or equal to three but then everything else was the same except for the counting which is now Plus instead of minus and then we refined it a little
182:06
Speaker A
bit further by counting now from zero up two but not through three and we tightened up this code here by just incrementing one by using the slightly more succinct syntax so at this point these flowcharts might become less and
182:20
Speaker A
less useful for us because once you've wrapped your mind around the concept and hopefully the picture helps bring that concept to life it's certainly fine to focus entirely on the code and only think about or even draw something like
182:32
Speaker A
this if you need to wrap your mind around something more complicated than you're used to well let me go ahead if I may and propose that we transition to another approach of types of Loops using another keyword here namely a for Loop
182:46
Speaker A
and this is a word that does exist in other languages but doesn't necessarily have as many features as other languages might use it for but there is a different type of loop not a while loop but a for Loop and a for Loop is going
182:57
Speaker A
to allow our allow us to express ourselves a little differently but to do so I'd propose that the easiest way is if we introduce one other ID in Python which is that of a list and here too no
183:08
Speaker A
pun intended we're adding to the list of data types that python supports we've seen stirs or strings ins or integers Floats or floating point value use bulls or Boolean Expressions python also has lists which is another type of data but
183:24
Speaker A
wonderfully this one's probably pretty familiar a list of things in the real world is a list of things in Python it's a way of containing multiple values all in the same place all in the same variable so what do I mean by this well
183:38
Speaker A
let me propose that we go back to our VSS code here and let me kind of start fresh with my code here and not use a while loop at all but let me use this new keyword for the way the for Loop
183:49
Speaker A
works is that it allows you to iterate over a list of items so what does this look like it might look like this for I in the following list of items 0 1 2 this is my starting point and on each
184:04
Speaker A
iteration of this Loop that is on each execution of this loop again and again I want to print out meow now I'll admit I kind of like the look of this code already even though there's some new syntax here because it's just short
184:18
Speaker A
order than the while loop right the while loop had multiple lines a moment ago and it was entirely up to me to decide what i is I have to check a condition I have to increment or decrement I like I was doing a lot of
184:29
Speaker A
work relatively speaking to make that thing turn to make that Loop go and go it was very mechanical in a sense you can kind of in your mind's eye maybe see the gears turning as all of these variables are uh changing and these
184:43
Speaker A
questions are being asked a for Loop kind of simplifies all of that and it just says if you want a variable like I a number and you know in advance how many times you want this Loop to execute
184:55
Speaker A
three times we'll just kind of specify what it is you want I to take on as values explicitly in this loop I will be automatically initialized by python to be zero then meow will be printed then python will automatically update I to
185:10
Speaker A
equal 1 then meow will be printed then python will automatically update I to B2 and meow will be printed and because that's it for the values in that list python will stop and it will only me meow a total of three times what is the
185:24
Speaker A
list the list in this program is exactly that 0 comma 1 comma 2 and notice the square brackets those aren't parentheses those are square brackets that represent a list that's how you know visually as the programmer that's how python knows
185:38
Speaker A
as the language that you intend for that to be a list so let me go ahead and run this python of cat. piy and it works just the same but it's only two lines it's pretty readable once you have
185:50
Speaker A
familiarity with that construct but to my constant point about correctness not necessarily being the same as design in what sense is this program perhaps poorly designed It's seems to work it meows three times but why might this not be the best
186:10
Speaker A
way to solve this problem even if you've never programmed before again think about Corner cases things that may or may not happen think about extreme cases that really test the quality of this code okay I think that because like we
186:25
Speaker A
can we are saying 0 one two which is three times and then like if you want to print a million you say one two three yeah exactly and that's what I mean about thinking about the extreme cases if you're trying to decide for
186:40
Speaker A
yourself if your own code is good or someone else's code is good it might look so at first glance but think about the extreme well what if it's not three things it's a million things I mean are you really going to write out one Z
186:53
Speaker A
through a million or 0 through 9 uh you know 999,000 uh 999,999 like no you're not going to write that many numbers on the screen there's got to be a better way so let's do the better way from the get-go rather
187:09
Speaker A
than set the stage for doing something poorly and the one way we can solve this problem to improve the design is don't just manually specify ify the list of values use a function someone else's function that comes with python that
187:23
Speaker A
gives you the list you want and the easiest way to do that in Python is to use a function called range that returns to a range of values it expects as input at least one argument and that number is
187:34
Speaker A
going to be the number of values you want back those values are going to start at zero and go to one to two and so forth but they will go up to but not through the number you specify so by
187:46
Speaker A
specifying range three you're essentially being handed back one two three values and by default those values are zero one and two and that's it but what's brilliant about this is that now to Hope's point if I do want to meow a
188:01
Speaker A
million times I mean that is an angry cat I can now do a million by just typing a million I don't have to literally type zero comma one comma 2 comma 3 comma four all the way up to
188:14
Speaker A
999,999 I just do this so that's to be a better way long term so that's indeed one Improvement we can indeed make here still using a for Loop but now using this range function and just to show you
188:27
Speaker A
something else that's pythonic this is not strictly necessary but it's commonly done there's a minor Improvement we can make here even if we're just meowing three times and notice that even though I'm defining a variable I I'm not ever
188:43
Speaker A
using it and it's kind of necessary logically because python Pres presumably has to use something for counting right it has to know what it's iterating over but there's this convention in Python where if you need a variable just
188:56
Speaker A
because the programming feature requires it to do some kind of counting or automatic updating but you the human don't care about its value a pythonic Improvement here would be to name that variable a single underscore just because it's not required it doesn't
189:11
Speaker A
change the correctness of the program but it signals to yourself later it signals to colleagues or teachers are looking at your code too that yes it's a variable but you don't care about its name because you're not using it later
189:23
Speaker A
it's just necessary in order to use this feature this Loop in this case here so just a minor uh Improvement or change there but to really get you intrigued by what's possible in Python let's take this one step further so if we really
189:39
Speaker A
want to be pythonic this one if you've programmed before is kind of going to blow your mind so to speak whereby if I want the cat to meow three times what if I actually do this print open parenthesis quote unquote meow times
189:56
Speaker A
three all right you have to be kind of a geek to think this is cool but this is kind of cool so you can literally just print what you want multiply it by the number of times that you want it and you
190:08
Speaker A
will get back exactly that result now I've kind of made a mistake here so let's see what this does it's not quite as beautiful as this code might look to to to you to some of you to me let me
190:21
Speaker A
run python of cat dopy enter okay it's a really like Hungry Cat or something it's meowing really fast but I can fix this I bet let's think about now some of the basic building blocks we've discussed the problem is clearly that literally
190:35
Speaker A
meow meow meow is being repeated three times but it's not as pretty as I want it I want it to be meow meow meow on separate lines what might be a possible solution here while still using this multiplication operator and think back
190:51
Speaker A
we've used plus to concatenate strings you can apparently use multiplication to concatenate strings but more than once again and again and again how could I clean this up without reverting to my for Loop or my while loop and still use
191:03
Speaker A
multiplication in this way uh we can use a escape sequence which should did back slash n amazing yes think back to back sln which is the way you as the programmer can express a new line in code and I think
191:18
Speaker A
if I take your advice I put a back slash n there inside of my quotes So that at the end of every Meo W there's a new line let's see how this looks Let Me Clear My screen and run python of
191:29
Speaker A
caty okay so close I like this let me call on someone else the only thing I don't like and I know I'm being really nitpicky now is that it's meow meow meow on separate lines but there's kind of
191:40
Speaker A
this extra blank line which I'm just not loving aesthetically I think we can uh make end equal to column uh column not back n yeah so here too like all of these things we've seen in past weeks are kind
191:55
Speaker A
of coming together right recall that the print function lets you control what the line ending is by default it's back slash n itself which is why at the very end of this print the cursor is being moved again to the next line well we
192:08
Speaker A
need to just override that so let me go into my code here and let me change this to comma n equals quote unquote so that it's no longer the default back sln it's instead now going to be uh nothing
192:22
Speaker A
whatsoever that should eliminate then hopefully that additional uh blank line so let me run this one last time here python of caty enter and there we have it so now you know at least as programming goes it's kind of cool that
192:36
Speaker A
I can distill this into a short line and express myself all at once now to be fair it's a little less readable like now I've got back sln I've got time three I've got n equals quote unquote so
192:47
Speaker A
you don't have to do things this way my previous approach with a for Loop totally fine my previous approach with a while loop totally fine and in some sense perfectly welld designed but this is just yet another way to do it but
193:00
Speaker A
it's not a good thing if you or your teacher your colleague your friend are going to struggle to read your own code but this is a feature of python that some languages do not in fact have all right well let me propose that things
193:13
Speaker A
get more interesting still if we're not just swing three times only but we're meowing some variable number of times let's ask the user how many times this cat should meow so let me clear the screen here and let me figure out well
193:27
Speaker A
how do I get a number from the user the catch here is that if I want the user to give me a number I'm not doing math per se I'm meowing and therefore the user has to give me a positive value the user
193:38
Speaker A
has to give me a positive value so how can I insist on this well if I just do this n equals int of input uh what's n question mark well I want to check like I could say if n is less than Z like if
193:56
Speaker A
it's negative well I could do this well then ask again int input what's n question mark okay well what if the user still doesn't give me a positive number what if they're being really difficult they're not paying attention and they
194:09
Speaker A
typed in two negative numbers well if n is less than zero well let's do it again n equals right this does not end well you can't infinitely many times keep checking is it negative is it negative is it negative right the program would
194:24
Speaker A
never be done written so we can do this I think better maybe with a loop so let me propose this a very common Paradigm in Python when you want to get user input that matches a certain expectation you have that it's all positive that
194:39
Speaker A
it's all negative or just something like that you just immediately say while true you deliberately and a little dangerously but a very conv intentionally induce an infinite Loop now what is an infinite loop it's just one that goes forever and we've seen how
194:53
Speaker A
that can happen accidentally mathematically it's absolutely going to happen when you say while true why well the answer to the true question is always true so this is a way of deliberately inducing a loop that by default is going to go forever so we're
195:07
Speaker A
going to need a way of breaking out of this Loop when we have the number we want the convention though inside of this otherwise infinite Loop is to ask the question you care about like give me an in
195:17
Speaker A
by prompting the user for input like what's n question mark and then just ask your question so if n is less than zero then I think we want python to just continue to prompt the user again that is we want the code to stay in the loop
195:32
Speaker A
recall the input function and hope that the user gives us a better answer if this time around it's less than zero so let's just literally use Python's keyword continue which says just that continue to stay within this Loop else
195:44
Speaker A
if it's not less than zero let's go ahead and just break out of the loop altogether using another keyword in Python break break will break you out of the most recently begun Loop in this case if it's not the case that n is less
195:56
Speaker A
than zero so this will work and it will allow us to get a value that's zero or greater from the user but I think we can tighten it up further so it's to not bother having an if and an else why
196:07
Speaker A
don't we instead just say if n is greater than zero go ahead and break in fact it's not that interesting a program if we even allow the user to type in zero so let's wait and until they give
196:17
Speaker A
us an integer that is greater than zero and then break out of this Loop and what can I now do down here for I in range of whatever that value n is print meow and honestly I don't need I here so let me
196:33
Speaker A
come back to that principle before and let me just change it to an underscore just to be pythonic if you will so what's going on lines 1 through four deliberately Implement an infinite Loop that otherwise by default is going to go
196:46
Speaker A
forever but I'm asking a question inside of that loop after getting an INT from the user on line two I'm then checking is it greater than zero or is it zero is it negative none of which makes sense
196:58
Speaker A
for a meowing cat like I want the cat to meow at least one time so if it is greater than zero break and this break statement even though it's indented indented twice has the effect of breaking out of the most recently begun
197:12
Speaker A
while loop so once the user gives you a positive value then we get to line six at which point we meow that many times because of line six and seven so if I run this now python of cat. Pi enter
197:27
Speaker A
well what's n let's start with three where we begin meow meow meow well this time let me go ahead and increase the size of my terminal window just temporarily let me run python of cat.
197:36
Speaker A
let me do it 10 times meow 10 times now appears on the screen and the takeaways here are not just that we can meow 10 times or do something again and again but this is a very common Paradigm in
197:48
Speaker A
Python when you want to do something again and again and again but only until the user actually gives you a value that you care about here and let me propose actually now that we practice a little more what we've been preaching
198:01
Speaker A
especially when it comes to say especially when it comes to say writing your own functions you know now that I'm doing all this meowing it might be nice to actually have a meow function that the inventors of python didn't Envision
198:15
Speaker A
so let me do this let me actually get rid of this code and let me go ahead and do this let me go ahead and say Define a main function as I've done before and let me just blindly call meow 3 meow
198:26
Speaker A
doesn't exist yet but when it does that'll be great so let me go ahead now and Define meow so my meow function should take as input a parameter called n or anything I want and this part's pretty easy now how do you meow in times
198:41
Speaker A
well for underscore in the range of n Go ahead and just print meow so same code AS before nothing new here I'm just putting that logic inside of a meow function that's going to have this side effect of printing meow and now as
198:55
Speaker A
before let me go down here and let me make sure I call Main and if I now run this code python of cat. meow meow meow it's always going to do three because I've hardcoded the three well let's make one Improvement
199:08
Speaker A
here let me go ahead now and maybe do this uh let me ask the user for a number so let's say something like this number equals get number all right unfortunately there is no function in Python called get number that gets a
199:22
Speaker A
positive number from the user but I can invent that so Define get number open paren close per n and then inside of this function let me do this while true go ahead and get a number from the user
199:34
Speaker A
converting it to an INT asking them what's n question mark and then if n is what I want it's a greater than zero value a positive number I don't want to break this time necessarily although I could I instead want to
199:50
Speaker A
return the value so I can actually do this instead and this two is a feature of python this ability not to just break out of a block of code but also to return a value in code to actually
200:03
Speaker A
return a value gives you the ability ultimately to return explicitly a value so that your function has not just a side effect necessarily but it actually hands back just like input does just like int does just like float does an
200:17
Speaker A
actual value to the user now to be clear I don't have to return n here I can still break out of the loop as I've done in the past with code like this but then after the loop I still have to return n
200:30
Speaker A
and so what's happening here is that if you use break to get out of the loop but you need to hand back a value from a function you still have to use the return keyword now explicitly either in
200:41
Speaker A
the loop as I did or now outside of the loop but still inside of the function the last thing I'm going to do here now is change that three which we hardcoded earlier to actually be the value of the
200:53
Speaker A
variable we've gotten from the user so that now down here if I run python of cat. py enter what's N I can type in three I get my three meows or if I only want one I now get one meow instead all
201:07
Speaker A
right so if we now have this ability to do things again and again in these Loops let's see if we can't solve some other problems via which to express ourselves cyclically but get back some interesting answers as well let me propose for
201:21
Speaker A
instance that we look a little more closely at these lists it turns out that in Python and really in programs in general it's useful to have a list of values because we're going to be able to work with more and more data larger and
201:32
Speaker A
larger data sets so let me propose that we come back to vs code here and let's do something that's perhaps a little familiar to some folks um the world of Hogwarts and let me go ahead and code up
201:41
Speaker A
a file called Hogwarts and let's see if we can't have a list of students at Hogwarts here so I have a new tab called hogw Works sty and let me go ahead and propose that I just Define in this
201:54
Speaker A
program a list of students whose names I know in advance so I'm not going to get user input for now I'm just going to know from the GetGo that the three students I want to consider are these a
202:03
Speaker A
variable is going to be called students it's going to equal as I've done in the past a square bracket which means hey here comes a list and those values are going to be Hermione in quotes because it's a string uh Harry in quotes cuz
202:15
Speaker A
it's a string and then WR in quotes because it's a string as well so this is a list of length three it's similar in spirit to my list of length three earlier but that had three ins 012 now I
202:27
Speaker A
have a list of three strings instead and this isn't very useful at the moment but let me just do something as a check for myself let me print out each of these students well wait a minute how do I
202:40
Speaker A
print the contents of a list well in the past when we've printed a variable we've just printed out the name of the variable but I don't want to print out all of Hermione and Harry and Ron all at
202:52
Speaker A
once maybe I want to print out Hermione first then Harry then Ron so I need a way to express more precisely which value do I want from this list and the way you do this in Python is you use
203:04
Speaker A
square brackets in another way if you have a variable in this case called students and you want to go inside of that variable and get a specific value that is to say you want to index into the list you use square brackets this
203:18
Speaker A
way using numbers inside of the square brackets and here's where we see that it is useful to think and count in terms of zero on up instead of one on up these lists in Python are shall we say zero
203:31
Speaker A
indexed the first item in a list is at location zero the second item in a python list is at location one and the third is at location two so you're always kind of off by one mentally but you get used to it if you've never
203:44
Speaker A
programmed before over time so let me print out all three students so let me print out students bracket zero then students bracket one then lastly let me print students bracket 2 and this is my third and final line and of course if I
203:56
Speaker A
run this code it probably does what you would guess if I run python of Hogwarts stpy there's Hermione Harry and Rob each on their own lines there but there's got to be a better way right especially if I
204:07
Speaker A
don't know in advance who's going to be in this list if next year there's some new students at Hogwarts we can use a loop to do something automatically without having to manually type out zero and then one and two well here's another
204:19
Speaker A
feature of python you can use a for Loop not just to count from zero to 1 to two you can use Python to just iterate over anything not just numbers but strings so I could actually do this for student in
204:33
Speaker A
students colon and then indented underneath that I can say print student now it doesn't matter if I have three students or four or 400 this two lines of code this Loop will print all of those students for me one at a time so
204:48
Speaker A
if I now run python of Hogwarts there's the same list but I don't need to know in advance how long that actual list is now notice I made a conscious decision here I didn't call this variable underscore because this time I'm using
205:03
Speaker A
the variable and while I could do this now no no no no your code is getting way too cryptic if you're naming the variable underscore and you're using the variable underscore now you're helping no one now you're confusing the reader
205:16
Speaker A
yourself in the down the line you should call your variables what they are so an very appropriate name though I'm sure you could come up with others would be student and here you could say you would say student as well if you'd prefer to
205:29
Speaker A
be more succinct it's not unreasonable to do something succinct in a loop like this for s in students using maybe the same letter that the list itself begins with but again why bother python is meant to be more readable if you have a
205:41
Speaker A
list of students iterate over them one student at a time let me pause here to see if there's now questions about lists as I've now defined them a list of strings in this case or using a for Loop
205:53
Speaker A
now to iterate over and print each of those names yeah uh so is it not necessary to initiate student in this case or we can just declare a variable in the loop good question you do not need to manually initialize it python
206:07
Speaker A
takes care of initializing the student variable to Hermione first then Harry second then Ron third unlike other languages you don't need to initialize it to something yourself it just exists and it will work other questions on loops and lists in this way since you
206:23
Speaker A
describe break so is there any concept of continue so that we can skip a particular case in Loops yes you can continue using another syntax as well we haven't shown that for now we focused only on break H okay sure uh can can
206:36
Speaker A
this follow work with either hash tables or different kind of fight tables or arrays uh indeed so we're getting ahead of ourselves there but there are yet other types of data in Python and indeed you can use a for Loop to iterate over
206:49
Speaker A
those as well anything that is iterable so to speak is a piece of data that can be used with a loop like this but more on those more on those soon in fact let me transition here to show just another
207:00
Speaker A
way of solving the same problem because up until now when we've used Loops we really have relied on numbers and that's fine if you prefer to sort of stay in that space suppose I did want to iterate using numbers like I and 0 1 2 and so
207:14
Speaker A
forth let me propose that we could change this code AS follows if you would prefer to think about or if the program you're trying to implement requires that you use numbers like this you might do this for I in well I don't want to just
207:27
Speaker A
say students because then I is not going to be a number I is going to be literally Hermione then Harry then Rob I need to iterate from zero to one to two right if I know a list with three
207:42
Speaker A
elements has these locations 0 1 2 I need to create a loop somehow that starts at zero and ends at two previously when I wanted to do that I needed range but this two is not going to work I can't just say in the range of
207:55
Speaker A
students because students is not a number it's not an integer so you can't pass it to range range expects an integer but there is a solution here it turns out that there is a function in Python called length or Len Len that
208:11
Speaker A
will tell you the length of a list and other things down the line too and now I think I can assemble these building blocks in a way that can allow me to use numbers in this way so range doesn't
208:23
Speaker A
take a list of strings it takes a number and ideally that number is going to be three so I get a range of values 0o 1 and two so I think I can Nest my functions like this if I first get the
208:35
Speaker A
length of the student list that's going to be three then I pass that return value as the argument to range that's going to give me back a range of value zero then one than two and what that's going to allow me to do then in code if
208:49
Speaker A
I want is not just this I could do print now students bracket I and this is now where the syntax we're seeing is getting very expressive new and perhaps unfamiliar but if I can do Open Bracket zero close bracket or Open Bracket one
209:07
Speaker A
close bracket or Open Bracket 2 close bracket turns out I can actually put a variable in there and I can express any number inside of those brackets so it's to print these all out dynamically in a loop let me do this python of Hogwarts
209:20
Speaker A
enter there's Hermione Harry and Ron and now if I'm just curious I I just want to poke around or maybe I want to do a ranking like who are the top three students in the school or in Gryffindor
209:32
Speaker A
well I can print multiple things at a time we've seen let me print out not just the students at location I but rather let's print I first and then the student at location I so two things to print and we know that print can take
209:45
Speaker A
two arguments we've seen that before they'll be separated by a space let me go ahead and rerun this now I see that okay hermion is the top student but she's in zero place that's a little weird like we don't need to show the
209:57
Speaker A
human using my program that we started counting at zero I can clean this up I can just add one to the eye up here and now we see sort of a top three list of students hermion is number one Harry's
210:08
Speaker A
number two and of course Ron is number three so we can get access to all of those same values as well all any questions now on on these lists any questions now on these lists this length these ranges or
210:23
Speaker A
otherwise my question is uh for I in range can you explain this once more uh sure still so let me rewind in time we started off doing this for I in 012 and then we print it out meow three
210:43
Speaker A
times in that way the way that the for Loop works is that it creates for you a variable that I've called I but I could call it anything I want it then assigns I initially to the first thing in the
210:54
Speaker A
list it then automatically assigns I to the next thing in the list and then it assigns I to the third thing in the list and each time it does all of the indented code underneath we realize though that this
211:06
Speaker A
is not going to scale well if I want to do something like a million times so we introduced range instead that has the effect of doing the same thing it returns to me a Range of values a list
211:17
Speaker A
of three things really so the behavior is exactly the same if we now fast forward to this Hogwarts example now though what I'm doing is just combining these smaller ideas I'm still creating a for Loop I'm still creating a variable
211:31
Speaker A
called I I want to do it over a range of values but how many values well if I use the length function and pass to the length function the list of values lengths purpose in life is to tell me
211:42
Speaker A
how long is this list and it's three so that's almost as though before I had just done something like this but I don't want to hard code three I want to dynamically figure out how many students are at Hogwarts so I'm just composing
211:55
Speaker A
composing composing or nesting all of these various ideas all right if I may let me transition now to hog in Hogwarts still to introduce one final type of data before we combine everything with a few final programs it turns out in
212:10
Speaker A
Python there's not just strings not just ins not just floating Point values not just bulls not just list there are also what are called dictionaries or dicts which are a data structure that allows you to associate one value with another
212:26
Speaker A
literally a dictionary like in the human world if you were to open an a dictionary be it in English or any other human language what's inside of a dictionary well it's a bunch of words and definitions a computer scientist
212:37
Speaker A
though and a programmer would describe those more generically as keys and values something associated with something else that's all a dictionary is it allows you to associate something with something else and notice this is already more powerful more interesting
212:52
Speaker A
than a list a list is just a set of multiple values but a dictionary is sort of two-dimensional if you will just like a human dictionary a book it Associates something with something else like words with their definitions now what does
213:06
Speaker A
this actually mean in practice well suppose that we wanted to keep track of who is in what house at Hogwarts well I could do it using lists alone let me go back to vs code here and let me just
213:20
Speaker A
temporarily but in a way that I'm not going to like ultimately let me create another variable called houses set it equal to uh Gryffindor corresponding to herm's house uh Gryffindor corresponding to Harry's house and Gryffindor corresponding to Ron's house and let's
213:35
Speaker A
add Draco in there so we now have four instead of three students just so we have a little variety and he was in uh Slytherin so now we have two lists and we could just agree amongst ourselves that whoever is first in the students
213:50
Speaker A
variable lives in the first uh value in houses whoever is second in students lives in the second house whoever third in students lives in the third house we could do that but honestly that is going to break down quickly when we have a lot
214:05
Speaker A
of students when we have a lot of houses and what if we want to keep track of more things than that what if we want to keep track of every student's house and the Patronis this uh this image that
214:15
Speaker A
they conjure up magically well then we need a third list like this is just going to get messy quickly if we're just on the honor System using multiple lists where everything lines up logically it doesn't end up well when
214:28
Speaker A
your code gets more complicated but I do want to implement this idea I want to associate something with something a student with a house a student with a house a student with a house and so forth so how can I go about doing this
214:39
Speaker A
well let me go back to my code here and let me propose that we do this using a python dictionary and this is the last of the new syntax really that we'll see here's the new syntax instead of using
214:51
Speaker A
square brackets we're going to use curly braces for dictionaries as well we've seen curly braces in the context of f strings completely unrelated sometimes you run out of keys on the keyboard and the authors of a language need to start
215:04
Speaker A
reusing symbols in different ways that's what's about to happen we're using curly braces in a different way now so let me create a variable called students and let me go ahead and set it equal to open curly brace and Clos curly brace this is
215:17
Speaker A
an empty dictionary at the moment and here's how a dictionary works it allows you to associate something with something else and you do that like this Hermione quote unquote colon and then the value thereof what do you want to associate with
215:32
Speaker A
Hermione well Gryffindor what do I want to associate Harry with well I want to associate him with Gryffindor what do I want to associate Ron with well I want to associate him with Gryffindor well this is actually not going to this is
215:47
Speaker A
going to get very ugly quickly once we add in Draco and Slytherin my code is going to get too long it's going to start wrapping so this is purely aesthetic it is perfectly acceptable in Python and other languages to format
215:57
Speaker A
your code a little more readily and just add new lines if it makes it more readable and one way of doing this might be as follows I still have my curly brace up here I still have my curly
216:07
Speaker A
brace down here but notice it's a little more readable now in that I have my keys on the left my something and my values on the right my other something it's just a little easier to skim top to
216:19
Speaker A
bottom you could format it differently as well but I'm going to go ahead and add in now uh Draco who lives of course in in Slytherin so now I have each of these keys on the left and values on the
216:31
Speaker A
right which is really again just a code implementation of this idea a little chart that you might write up with paper pencil when associating something with something else so how do I now use this code in an interesting way the syntax is
216:45
Speaker A
almost the same if I want to print out the very first student herm's house I could do this print out the name of the variable but I need to go inside of the variable I need to index into it and
216:57
Speaker A
what's neat about dictionaries is that whereas lists have locations that are numeric zero 1 2 Hermione Harry Ron respectively dictionaries allow you to use actual words as your indices so to speak your indexes to get inside of them
217:16
Speaker A
them so if you want to print out herm's house the key you care about is quote unquote Hermione and what this syntax here will do notice it's not a number zero or one or two it's literally herm's name this is like going to the Chart
217:31
Speaker A
earlier and saying all right give me uh Hermione is my key Gryffindor is the value that's what we're doing here syntactically we're looking up hermion and getting the value thereof so if I go back to my code that should print out
217:44
Speaker A
Gryffindor and if I do this a few times students bracket quote unquote Harry should give me Harry's house print students Open Bracket Ron that should give me Ron's house and then lastly if I do this with students bracket Draco that
217:57
Speaker A
should give me draco's house now it's a little manual still I'm bet we can improve this but let me run python on Hogwarts sty and we should see Gryffindor Gryffindor Gryffindor Slytherin which is exactly what we'd expect now all we've done again is we've
218:11
Speaker A
just now moved from having just a simple list of names to again sort of two Di ions associating like we would on paper pencil something with something else keys with values respectively allow me if you will even though I realize this
218:24
Speaker A
is getting a little fancy allow me to escalate things slightly here and transition from looking at just for instance uh that pattern there just hardcoding those values there to actually printing these out more dynamically let me go ahead and use our
218:40
Speaker A
Loop and this question came up earlier as well let me go ahead and say for each student in students go ahead and print out for instance the students variable at well let's just say student first let's keep it simple so this is not going to be
218:58
Speaker A
that interesting yet but when I run python of Hogwarts upy and hit enter notice what should I see let me take a question here to see what am I going to see when I hit enter now when I'm doing
219:10
Speaker A
for student in students yeah I think we we we will only see Keys perfect so good intuition it could have gone both ways could have been values the houses but when you use a for Loop in Python to
219:22
Speaker A
iterate over a dictionary by design it iterates over all of the keys so we should see I think Hermione Harry Ron and Draco let me hit enter now enter and indeed you're exactly right we see just the keys but that's not really that
219:37
Speaker A
useful if what I really care about is who lives where can I print out both well I think I can let me go ahead and do this let me print out not just the students name the key but let me use the
219:49
Speaker A
key their name to index into the dictionary right if I know the word in the dictionary let me look up its definition if I know the student's name let me look up their house and the Syntax for this just like a list is
220:02
Speaker A
students bracket and just like in the past we used I when I was a number we can also with a dictionary use a string so if the student's name is the key then this syntax students Open Bracket student close bracket will go to hermion
220:23
Speaker A
location and get back her house we'll go to Harry's location and get back his house and so forth so if I do python of Hogwarts enter now I see Hermione Gryffindor Harry Gryffindor Ron Gryffindor Draco Slytherin now it looks
220:36
Speaker A
like I've given them all new last names but I can clean that up this is just a print thing let's go ahead and change our separator from the default space to maybe a space comma and just using print
220:47
Speaker A
features now let me run the same program again enter now I've just got some nice pretty commas in there to make clear that herm's last name is not in fact Gryffindor but that's just a print detail any questions then on these
220:59
Speaker A
dictionaries and what I've just done questions on these dictionaries and this looping over them here um I just can't get my head around the uh for student in students does uh if I'm just correct me if if I'm right does that mean it
221:20
Speaker A
Imports the list of students and uses the indexes in other words herione Harry and Ron as the indexes in the actual um the list of students correct so this is just a feature of python when you use a
221:37
Speaker A
for loop with a dictionary what happens is this if this is the dictionary here with the keys on top and the values on bottom you get to choose what the variable called I called my variable student just because it makes sense
221:48
Speaker A
because I want one student at a time and what the for Loop does just like it did with numbers before the zero the one and the two it allows me to for instance set student equal initially to herm's name
221:59
Speaker A
and then the next iteration of the loop the next cycle sets student equal to Harry's name then Ron then Draco it just kind of happens automatically like that is what the python interpreter does for you when it sees a for Loop like that so
222:12
Speaker A
it's very similar in spirit to iterating with a for Loop Loop over a list but rather than iterate over the numeric location 012 it iterates over the boldfaced keys in this representation here graphically and allow me to give us
222:28
Speaker A
one other example on Hogwarts before we look at one other familiar uh domain at the risk of things escalating a little bit let me propose that we continue the story with one final Hogwarts example like this what if we have more
222:42
Speaker A
information about each of our students and this is kind kind of inevitable right if you're implementing a program that's a database with people or customers or employees or anything else you can imagine having a lot of data about anything you're representing in
222:56
Speaker A
your program here for the sake of discussion suppose that every student at Hogwarts of course has a name they have already a house but they also have a Patronus for those unfamiliar this is the animal or entity that comes out of
223:08
Speaker A
the end of their wand when they make a Certain Magical spell the point here being is that we want to associate not just one one thing with the student but multiple things as well their name their house and their petronus in this case
223:23
Speaker A
well what might code like this look like well let me go back to Hogwarts toy and let me start fresh for just a moment and let me propose that I enhance this with a bit more data and this data is going
223:35
Speaker A
to look as follows my students variable now I'm going to propose we think of it as a list what if we have a list of dictionaries as follows indeed I want to literally implement this picture here so notice that my previous picture just
223:50
Speaker A
represented a single dictionary but suppose I wanted to compose a list of dictionaries that is four students so a list of four students and suppose that each of those students is itself a dictionary a collection of key value
224:08
Speaker A
pairs keys and values something and something else well here's one other way we can do this in code let me go back to s code here and let me Define a variable called students that is equal to a list
224:21
Speaker A
and I'm going to preemptively move my cursor onto separate lines because I know this is going to be long and I want to fit all of the elements of this list inside of it I'm now going to create a
224:32
Speaker A
dictionary one dictionary per student and how do I create a dictionary I just use those curly braces but it's up to me to Define what those keys are and let me propose that one key this time won't be
224:42
Speaker A
the student's name explicitly it will literally be the word name and they're going to have the name Hermione this same student is going to have another key called house and the value is going to be Gryffindor and the same student's
224:55
Speaker A
going to have a third key called petronis and the value of that is going to be I had to look it up in otter according to the book now I'm going to create a second dictionary inside of this list and again a dictionary is like
225:08
Speaker A
literally like the human dictionary of words it's a book that contains keys and values words and definitions what are the three words I'm storing in each of my dictionaries name house and petronis what are the definitions of those words
225:21
Speaker A
for Hermione Hermione griffindor and Otter respectively for Harry the definitions are going to be different in this new dictionary let me give myself another pair of curly braces and say this name quote unquote colon Harry uh house here is again going to be
225:38
Speaker A
Gryffindor and this one I I knew his Patronis is going to be in this case a stag all right next a third dictionary the name here will be Ron and I'm going to go ahead and do that just like this
225:51
Speaker A
next I have the house and he too was Gryffindor lastly had to look this one up Ron's petronis was a Jack Russell Terrier lastly is Draco in a third in a fourth dictionary now so another pair of curly
226:08
Speaker A
braces the name of the student is of course Draco the house of this student is Slytherin and dra interestingly enough at least according to the internet has no Patronus was never revealed in the books or the movies so it turns out this is actually
226:24
Speaker A
a wonderful teachable moment there is a special keyword in Python that is literally none n o n e with the first letter capitalized this represents officially the absence of a value so I could a little sloppily do something
226:39
Speaker A
like quote unquote but does that mean I didn't get around to typing it or not it's a little clear semantically to say literally none a special keyword in Python to make clear that I know uh Draco has no Patronis it's not just an
226:53
Speaker A
oversight on my part now that I have this what do I have in the computer's memory I have a list how do I know it's a list because I see a square bracket at the beginning and another square bracket
227:06
Speaker A
at the end that's just my visual clue okay I don't know necessarily what else is going on here but there's a list of something what is in that list well here two the syntax is our clue because this
227:17
Speaker A
line two starts with a curly brace and ends with a curly brace I just know that is a dictionary a collection of key value pairs now this all fit on my screen perfectly so I didn't bother moving all of the key value pairs onto
227:31
Speaker A
new lines it would have made it really tall so I I kept it all together here this time but how many keys does this first dictionary have put another way in her mayane physical dictionary how many words are in that dictionary three the
227:44
Speaker A
words are name house and petronis what are the three definitions or values of those words in herm's dictionary Hermione Gryffindor and Otter respectively and the same story goes for Harry then for Ron then for Draco I have by Design chosen to give them
228:04
Speaker A
dictionaries that have all the same Keys all the same names but they all have unique values and that's my design That's My Prerogative as a programmer so why is this useful at the end of the day now I have access to a whole collection
228:18
Speaker A
of interesting data about all of these students and I can still do a loop I can say for student and students that's going to allow me to iterate over this list of students and let me go ahead and
228:30
Speaker A
print out just one thing at a time let me print out the current Student's name so as complicated as the dictionary is this should be pretty comfortable four student and students is just going to iterate over every student in the list 1
228:42
Speaker A
2 3 4 total the next line is just going to print out the value of the name key it's like opening a physical dictionary looking up the word name and giving us Hermione Harry Ron and Draco respectively from each dictionary so if
228:56
Speaker A
I run this version of Hogwarts and hit enter there I get all three of their names but what if I want more information than that I want both their names and their houses well just add to prints arguments student Open Bracket uh
229:10
Speaker A
House close bracket all right let's go ahead and run this python of Hogwarts dopy and hit enter so I now see Hermione Gryffindor Harry Gryffindor and so forth well we can aesthetically clean this up a little bit by adding a separator with
229:23
Speaker A
print like a comma in a space just so that when I run this again I now see some commas separating these values but recall that students have not just a name not just a house but also that Patronis so if we want to print out that
229:35
Speaker A
too we now have the syntax via which to go into that same dictionary for each student and output their Patronus as well as their house and their name so if I run this program one final time now I
229:48
Speaker A
see all of the data in this here dictionary so this is a lot to absorb all at once I'm sure it's the last of our new data types on top of lists we have these dictionaries but again a
229:59
Speaker A
dictionary at the end of the day is just a collection of values similar to these values here that allow you to associate keys with values and the first version of this program Associated literally the students names with their houses but
230:13
Speaker A
then I realized in my next version wait a minute what if every student has not just a name in a house but a Patronis let's actually standardize the names of our keys to be name house and Patronus and then the values of those keys can
230:27
Speaker A
actually be the data like Hermione Gryffindor otter and so forth questions now on these dictionaries and iteration thereof I just was wondering if the suppose the dictionary is very huge and if I want to look up for a specific
230:45
Speaker A
student so how do I know uh where to look that student from like can we sort it out in alphabetical order or numeric order or anything like that in short answer yes one of the features of python is that it makes these dictionaries very
231:00
Speaker A
highly performant for you that is even if they're very large as they will be in future weeks when we manipulate more data python will find the data you care about quickly for you and in fact that is a feature of the language that is a
231:14
Speaker A
feature of a dictionary to get you the data quickly and there are functions that you can use you can sort the data you can sift through it you can do very performant operations as we eventually will allow me then to propose as we wrap
231:28
Speaker A
up these Loops that we solve just a few final problems that will perhaps evoke fond memories of yester here at least for me where in one of my favorite games growing up was this one here on the original Nintendo and this is a
231:40
Speaker A
two-dimensional world where the characters move up down and right not so much to the left in jumping over pyramids and obstructions like these and allow me to propose that we use this just for inspiration not to do something
231:52
Speaker A
that's quite as colorful or graphical as this but just to focus on for instance this barrier in the middle of the world here that Mario or Luigi had to jump over and so this here seems to be like
232:04
Speaker A
three bricks stepped on top of one another and we won't do things quite graphically but let's just Implement a very simple python based version of this textually using maybe just hashes for bricks because there's a pth pattern here one on top of the other and I bet
232:17
Speaker A
we can solve this in any number of ways well let me switch back over to vs code here and let me propose that we create a program called mario. using code in the terminal window and then up here let me
232:29
Speaker A
start by implementing that same picture as simply as I can printing out just literally the hash and then the hash and then a third final hash this is going to be a very textual approximation of it but I think if I run python mario. I've
232:44
Speaker A
got a very simple version of that same column of bricks so to speak but you can imagine that certainly in a game where maybe these uh The Columns get higher or lower it would be nice to write code
232:56
Speaker A
that's actually a little more Dynamic than that and doesn't just use print print print which is literally copy and paste it would seem so let me at least adopt some of today's Lessons Learned and instead do something like this for
233:08
Speaker A
underscore in range of three let's now print out just one of these at a time but the fact that I've now used a three to range means if I want to change it to something bigger or smaller I change it
233:20
Speaker A
in one place not in three or more places and this code two of course if I got it right is just going to print out the exact same thing so we're iterating here but let's see if we can't now integrate
233:32
Speaker A
our discussion of writing functions of our own to begin writing something a little more Dynamic and solving more complicated problems ultimately one of the nice things about functions is that they allow us to not just write code that we can use and reuse they allow us
233:45
Speaker A
to create abstractions if you will an abstraction is a simplification of a potentially more complicated idea and we've seen this a few times over the course of the weeks for instance we had a function called hello which granted
233:58
Speaker A
didn't do all that much it just printed hello but it allowed me to think about the function as exactly what it does not generically printing something but literally saying hello I've been able to get a number using something similar by
234:11
Speaker A
defining my own function like get number well let me go ahead and for instance assume for the moment that I've had the forethought to uh in my function main use a function called print column that seems as good a name as any to use a
234:26
Speaker A
function that prints a column of bricks well how can I go about now implementing this abstraction this simple idea print column with actual code well we've seen before with def we can do just that let me Define a function called print column
234:40
Speaker A
let me accept as its input uh generically speaking a parameter called height I could call it n or H but I'll be a little more explicit now with height just so I remind myself what it's doing and now I think I can just borrow
234:52
Speaker A
some of that same code from before for underscore in range of height go ahead and print out a single hash and then at the end of this whole program let's just call Main so I've kind of complicated the code it doesn't do anything more
235:08
Speaker A
just yet but it's setting me up for solving what I think are going to be more sophisticated problems if I run python of Mario up high we're back where we began but I now have a function an abstraction print column that's going to
235:21
Speaker A
allow me to think about printing some chunk of the world of Mario at a time and I can do this in different ways too notice that if I really want I could do something like this I could reimplement
235:33
Speaker A
now print column in different ways especially if I am using print column all over my code or maybe still a colleague of mine a friend someone else on the Internet is using my print column function what's also nice about
235:46
Speaker A
functions you've written is you can change the underlying implementation details of them but so long as you don't change the name of the function or its parameters or what it returns if anything no one else knows the difference you can change the internal
236:01
Speaker A
implementation as much as you want if you want to improve it or make fixes over time so for instance another way we could Implement print column recall would be something like this a bit clever with one hash and then a new line
236:12
Speaker A
and then maybe we could do multiplication strings and then end this line with quote unquote again it's okay if you're not comfortable with this syntax this was a more clever approach we saw in the past but if I run python
236:24
Speaker A
of myoy here I'll still see a column of three but what's important here is that main does not need to know that the underlying implementation of print column has changed well let's transition to a different dimension if you will and
236:40
Speaker A
rather than print out just these vertical bricks let's fast forward in the game to this part of the world here at some part mar Mario encounters these bricks in the sky that if he jumps up underneath they become coins and so he
236:51
Speaker A
he gains to a score but let's go ahead and focus only on those coins and let me propose that we print out oh just these four question marks here and let me go back to VSS code here and let me propose
237:02
Speaker A
that within VSS code here just like before we try to abstract this away so let me go ahead and get rid of this version cuz we're now going horizontal instead of vertical with our output and let me just say well print row four
237:16
Speaker A
times let me just abstract away the problem at hand I don't know yet how I'm going to print those four question marks but let's call it print row four and I'll assume I'll now solve this problem let's now go down that rabbit hole of
237:29
Speaker A
solving the problem Define a function called print row it's going to take a width instead of a height because it's horizontal instead of vertical and how can I do this well now we have an opportunity to do string multiplication
237:42
Speaker A
even more elegantly I can say quote unquote question mark times with and this is a very pretty pythonic way of printing what could otherwise be a loop and that's fine but this is going to go ahead and print those question marks for
237:56
Speaker A
me let's do python of mario. enter and now I've got four question marks it's not nearly as pretty as the more graphical version but it is at least uh a building block toward having now a reusable function like print row and why
238:11
Speaker A
am I doing all this like why are we over engine engering the solution to these problems by having print column and print row well it's a useful problem solving technique as soon as your world does not look one-dimensional like this
238:24
Speaker A
or with the column version but what about this later in Super Mario Brothers does Mario have to jump down into this world where there's a lot of these underworld barriers and this one here for instance looks like a square it's
238:37
Speaker A
two-dimensional there's a height and a width to it and that is to say there's a bunch of different ways we could implement this thing if maybe for discussion it's like a 3X3 grid a 3X3 square of sorts well how can we go about
238:51
Speaker A
solving this here problem well let me propose we come back to vs code and let me propose that we think about this in a couple of different ways I could do this H like this if I if I know where I'm
239:04
Speaker A
going you know maybe I'm a seasoned programmer let me go ahead and do this let me print out a square the width and the height of which is three that's an abstraction I'm just taking for granted for moment that there is already a
239:15
Speaker A
function called print Square that's going to be width three and height three as well but someone's got to implement this and at the moment there's only me at the keyboard so let's go ahead and Implement that square let me go ahead
239:27
Speaker A
and Define a function called print square that takes in a specific size both for height and for width and here's where we have an opportunity to use some of those loops and we can use those Loops in a way we haven't yet if I want
239:40
Speaker A
to print out all of these rows but also all of these columns I now have to think not just cyclically like a loop allows but I need to think two-dimensionally and if you're familiar with like an old school typewriter or even a printer
239:54
Speaker A
nowadays It generally prints from top to bottom so even if you have multiple columns you print out one line at a time and while you're on that line the printer or the typewriter prints from left to right and that's kind of the
240:07
Speaker A
mental model to have with your black and white terminal window all of the output for every example thus far starts at the top and goes down to the bottom from top to bottom left to right so we have to
240:18
Speaker A
generate our output our Square in that same way so let me propose that we do this let me propose that we know we need to iterate this many times three or more generally size so let me do this for I
240:31
Speaker A
in the range of size what do I need to do three times Well I want to print out what one two three rows of bricks but within each row of bricks what do I want to print one two three bricks
240:46
Speaker A
specifically so if we go back to our diagram here and I stipulate that it's indeed meant to be a 3X3 Square three wide and three tall what do I want to do to print the first row I want to print
241:00
Speaker A
brick brick brick brick brick what do I want to print on the second row brick brick brick and the third row brick brick brick so I'm doing three things three times there's a lot of printing that must happen so so let me go back to
241:15
Speaker A
my code here and let me propose now that we think of this outer loop that I've just started as representing each of our rows for I in range of size is going to ensure no matter what I do next that I
241:29
Speaker A
can print out one two three rows or more generally size where size could be three but it could be smaller or larger what do I want to do on each of the rows well just like an old school typewriter or
241:43
Speaker A
printer on each row I want to print out brick brick brick brick brick brick brick brick brick well that sounds like a cycle some kind of loop so maybe I can have inside of one Loop another loop I
241:55
Speaker A
don't want to use I again because I don't want to use the same variable and mess up my counting so I'm going to by convention use J very common to use I and then J maybe K but after that you
242:06
Speaker A
shouldn't keep nesting inside of each other let me go ahead and say for J in range of size two because it's a square and then each of these rows let me print out a single hash but no new line but
242:19
Speaker A
after each row let me print only a new line so there's a lot going on here especially if you've never touched python let alone Loops but notice what I've done here too and I'll add some comments for clarity for each row in
242:38
Speaker A
square for each uh brick in row print brick and here is where comments and more generally pseudo code can really help explain to yourself and others what your lines of code are doing on line eight I'm iterating from I
242:57
Speaker A
equals 0 on up to side so 012 on line 11 I'm doing the exact same thing but using J from 012 but that's good because I represents now each of my rows and while I'm on each of those rows
243:11
Speaker A
inside of this outer loop I'm going to do brick brick brick 1 two 3 1 2 3 1 2 3 but I don't want my cursor to keep moving to the next line while I'm on a row so I'm just overriding that line
243:24
Speaker A
ending but let me ask a question of the group now why on line 16 do I have a print here all by itself why do I have a print all by itself notice that it's below the inner loop but inside of the Outer Loop so to
243:45
Speaker A
speak what is that loop on line 16 doing ultimately every time you finish a line you have to add a new line and at the end of it so print it prints a new line perfect I don't want a new line after
244:03
Speaker A
every brick I only want to do that at the end of the row and that's why my comments now are perhaps enlightening notice that this Loop here is just iterating for each brick in in the row once I'm done with that inner loop so to
244:17
Speaker A
speak once I'm done with these highlighted lines here to Evelyn's point I need to print out one blank new line and we've not done this before but when you call print with no arguments all you get is that automatic line ending the
244:29
Speaker A
back slash end where the cursor moves to the next line so if I now roll go back to my terminal window and run mario. I think I should get a 3X3 square and it doesn't quite look like a square on my
244:42
Speaker A
screen because these hashes are a little taller they are wide but it is in fact 3x3 but let me propose as we've always done here how we might tighten up this code further just for clarity sake let me get rid of my comments for a moment
244:55
Speaker A
just so we can see how many lines of code we have total and let me propose that we maybe do this let me propose that you know what this inner loop especially if you're having trouble wrapping your mind around one Loop
245:08
Speaker A
inside of another loop you don't strictly need it what if we do this trick again what if we print out out inside of the outer and only Loop each of those hashes times the number of times we want them right we draw
245:22
Speaker A
inspiration from an earlier approach and we run python now of Mario same result but now print square is really nice and compact it has one explicit Loop and it's still printing out using string multiplication all of the hashes at once
245:37
Speaker A
on that row if you like abstraction and you'd like to wrap your mind more around what the code is doing well let's do this if you're not quite clear on what's going on let's propose that you implement a function called print row
245:50
Speaker A
passing in size and let me propose that this print row function it simply take in that width and print out the individual hash times that many times in other words here's an opportunity for abstraction whereby well what does it
246:07
Speaker A
mean to print a row well when you're implementing print Square I don't really care what it means to print a row I just need to know that someone's taking care of printing the row you can kind of pass
246:18
Speaker A
the buck to another function Al together and how does print row work well it could use a for Loop it could use this string multiplication trick this is a way to take a larger program and this is probably the most complicated one we've
246:30
Speaker A
looked at thus far and to decompose it into these smaller components that once assembled achieve your final idea seeing no questions that's the end of our look at Loops in Python this ability to do things cyclically again and again and
246:46
Speaker A
when we combine those with conditionals this ability to ask and answer questions and combine them with our functions and variables we really now have most of the building blocks we need to solve much larger much more interesting much more
246:58
Speaker A
personal questions so in the weeks to come we'll start to see exactly what could go wrong though when we do so but we'll introduce you to all the more tools via which you can troubleshoot those same problems [Music]
247:25
Speaker A
[Music] all right this is cs50's Introduction to programming with python my name is David men and this is our week on exceptions exceptions in python as well as in other programming languages refer to problems in your code indeed when something is
247:48
Speaker A
exceptional in your program it actually doesn't mean it's a good thing it means something has gone wrong that ideally you will somehow solve so what are some of the things that can go wrong so I'm going to go ahead and open up VSS code
247:59
Speaker A
on my computer here and in the terminal window I'm going to go ahead and run code of hello.py that's going to of course open up a brand new tab for me hello.py in which I can write my code
248:09
Speaker A
and let me go ahead and write some very simple code just to say hello to the world let's go ah head and say print quote hello comma world and then let me go ahead and I'm forgetting to close
248:22
Speaker A
that quote so a mistake that you yourself might have already made or might surely in the future make and it's a little subtle because you might not necessarily notice that you've just missed that one character well let me go
248:31
Speaker A
ahead and somewhat optimistically go down to my terminal window now and run python of hello.py and hit enter and that's the first of my errors my gosh I've only written one line of code and I seem to have more lines of error errors
248:44
Speaker A
on the screen but the Salient point is this bottommost thing here notice where it says syntax error a syntax error is a problem with the code that you have typed your syntax just like English and other human languages have syntax
248:56
Speaker A
associated with them so does my code and it's not quite correct something is ay I didn't follow the instructions properly and it does elaborate for me unterminated string literal now that's a bit Arcane that is a bit of a confusing
249:09
Speaker A
error message but unterminated would generally mean that I started something but didn't stop it I didn't terminate it string of course is a sequence of text like we've discussed before or stir in Python and literal generally refers to
249:22
Speaker A
something that you literally typed it's not a variable it's something like quote unquote or just quote hello world so the fix here of course is going to be to go ahead and terminate that string and actually close the quote and if I now go
249:35
Speaker A
back down into my terminal window and rerun python of hello.py now I'm saying hello to the world so the catch withd syntax errors here is that syntax errors are entirely on you to solve a syntax error is a problem that you've got to go
249:50
Speaker A
back into your code and fix from the Geto you can't just kind of hope that it's going to resolve itself or expect that other parts of your code will catch it for you syntax errors just must be fixed but there's a lot of other types
250:02
Speaker A
of errors in Python that might be described as runtime errors that happen while your code is running and it's really up to you to write some additional code defensively to detect when those errors happen because you don't necessarily know for instance what
250:16
Speaker A
input humans are going to type into your program and so you better be ready defensively to accommodate things that they type or even mistype so for instance let's go back over here to vs code and let me propose that we take a
250:29
Speaker A
look at a a new file Al together I'm going to close hello.py and I'm going to write code of say number. piy so let's play around with some numbers in Python and the first thing I'm going to go
250:40
Speaker A
ahead here and do with number. py after opening the this new tab is I think I'm going to go ahead and print uh type up a relatively simple program that maybe prompts the user for an integer like X
250:51
Speaker A
and then just prints out what x is so we're going to start super simple but again in starting simple we'll be able to really see where I've done something wrong well here we go I'm going to go ahead and say a variable called X is
251:02
Speaker A
going to get assigned the value of the return value of input quote unquote what's X question mark and I'm going to include a space to move the cursor over a little bit and then ultimately I'm going to go ahead and oh wait a minute
251:16
Speaker A
if I'm wanting to get an INT from the user recall that I need to do something proactively I need to actually convert that input to an integer using the int function in Python so now I'm passing the return value of input as the
251:29
Speaker A
argument to in and that will store in X ultimately an integer not a string that looks like an integer all right let me go ahead now and just quite simply print out what this is I'm going to go ahead
251:39
Speaker A
and print out uh quote unquote X is X but I don't want to literally say x is X I want to plug in the value of x so maybe the easiest way to do that is to surround it with curly braces and then
251:51
Speaker A
if I'm using these curly braces and I want python to interpolate the value of that variable that is substitute what x actually is in between those curly braces recall that I need to use a format string or an F string by
252:02
Speaker A
prefixing this whole thing with an F now that I've done that let's go ahead and see what happens I'm going to go ahead in my terminal window and run python of number. Pi I hit enter and so far so
252:14
Speaker A
good all is well and being prompted for X let me go ahead and type in a number like 50 all right that seems to work program seems to be correct or is it what could go wrong in this program
252:27
Speaker A
even though nothing did just go wrong but if I run it and run it and run it again during the running of my program what could still go wrong especially if I'm not the human interacting with it but some other Human Instead any
252:41
Speaker A
volunteers here for this one what could go wrong and in what way is this program not really correct even though at first glance it seems so what what is an inter we code in in a integrated ID we can't code in a interpreter so I'm
253:04
Speaker A
not calling an integer I'm still having trouble hearing you but what I think I heard is that if the what the user types in is not in fact an integer I can't just blindly convert it to an int if I'm
253:14
Speaker A
not putting too many words into your mouth I think what I should perhaps do here is be a little defensive and let me see if I can't simulate exactly the problem that could go wrong here let me go ahead and run again python of number.
253:28
Speaker A
piy let me try another number and in fact when testing your code generally it's a good idea to test Corner cases maybe numbers that aren't quite as plain as 50 or 49 or 51 let's choose some numbers that might be a little more
253:40
Speaker A
interesting if only mathematically like zero all right Z seems to work my code still prints out that X is Zer what might be another Corner case to consider well let me go ahead and try a negative number that too is pretty different in
253:52
Speaker A
spirit from 50 negative 1 okay that works too well let me try it one more time I've tried positive numbers negative numbers zero let me try something like a cat so literally C A typing in a string that doesn't even
254:05
Speaker A
look like a number and yet let's see now what happens when I hit enter all right we'll see now we've got another kind of error it's not a syntax error because I didn't make a typographical mistake I didn't forget some piece of syntax I
254:18
Speaker A
actually now have a error with one of my values and it's a value I didn't even anticipate the human me in this case typed it in long after I wrote the code so what does this refer to a value error
254:30
Speaker A
well let's see what the explanation is invalid literal for INT with base 10 quote unquote cat now this to is a bit of a mouthful and unfortunately in python and a lot of programming languages the error messages are written
254:41
Speaker A
for pretty comfortable program and of course when you're learning programming for the first time you might not be so comfortable with the programming language let alone the error messages but let's see if we can't glean some insight so invalid literal well again a
254:54
Speaker A
literal is just something that's been typed in it would seem for INT what is int exactly well int is the function I'm using to convert the user's input to a corresponding integer base 10 that refers to the decimal system uh which is
255:08
Speaker A
this the default that Python's using and it looks like at the end of the day what python really doesn't like is that I passed Cat quote unquote to the int function so how do I go about actually fixing this problem well I could just
255:22
Speaker A
add instructions in my program maybe I could add a line of print telling the user more explicitly be sure to type an integer or please don't type cap please don't type strings of course the user might still not oblig they might not be
255:34
Speaker A
reading the instructions so that too is probably not an effective strategy what we really want to do is write our code with error handling in mind we want to write lines of code that not only accomplish the problems we care about
255:45
Speaker A
but that also handle errors that might unexpectedly happen and in general when programming programming defensively assume that the users aren't going to be paying attention or Worse they're malicious they're trying to crash your program so we want to handle as many
255:59
Speaker A
errors as we can now how do we go about doing that in Python well it turns out whether you want to catch a value error or other types of errors as well though not syntax error python actually has
256:10
Speaker A
this keyword called try and it's sort of aptly named if you want to try to do something in Python you can literally use this keyword and you can check whether or not something exceptional something erroneous has happened so
256:23
Speaker A
using both try and this other keyword except can I go and try to do something except if something goes wrong I can do something else instead so let's consider how can I go about trying to convert the user's input to an INT except if
256:38
Speaker A
something goes wrong well let me go back to my code here and let me propose that I now modify this example as follows let me go ahead and above my first line of code I literally write try and a colon
256:50
Speaker A
telling python try to do the following I'm going to go ahead and indent my existing lines of codes here by the same number of spaces four in this case and then I'm going to add one more new line
257:00
Speaker A
down here that literally says accept value error and notice it's important that I've capitalized the V and I've capitalized the E these uh symbols are case sensitive and this is now an opportunity after this colon to tell python what I want to do in exceptional
257:16
Speaker A
cases when the number or the input from the user is not in fact a number and I'm going to say something plain like print quote unquote X is not an integer I'm at least going to tell the user roughly
257:28
Speaker A
what the problem actually is so notice another detail the indentation is important because I have try on line one and I've indented lines two and three those are the two lines of code that I'm trying except if I see a value error
257:41
Speaker A
line five because it's indented is what is going to get executed in cases of those errors let me go ahead now back to my terminal window and run python of hello of python of number. piy enter and let's go ahead and type in 50 again
257:57
Speaker A
still seems to work and of course I'm trying and succeeding let me go ahead and try once more this time though with the word cat or really anything that's not a decimal number and now you'll see much more cleanly X is not an integer
258:10
Speaker A
I'm not seeing some scary error message that I of a user am have going to have no idea how to handle now you the programmer have anticipated that something exceptional can happen and you've gone about actually handling the
258:20
Speaker A
error for the user giving them an appropriate error message instead let me pause here and see are there any questions now on what we've just done by introducing try and accept to handle this value error is value error the only
258:37
Speaker A
type of error you can get or the other types is value error the only thing you can catch there are other errors as well and we'll a few of them today and there's many many more honestly that if
258:46
Speaker A
you continue programming and programming in Python you're going to see a lot of them over the the weeks the months the years to come but the technique for handling them is going to be largely the same other questions on try accept or
258:58
Speaker A
these exceptions more generally uh yes sir actually to use the accept log you need to know the type of error right like here you knew it was a value error what what if you can't anticipate this particular type of the error a really
259:12
Speaker A
good question so I'm being very good about catching so to speak the very error that I know might happen I don't know when it might happen because it's going to depend on the user but I know what kind of error will happen from the
259:24
Speaker A
int function there is a way in Python where you can say except if anything goes wrong and you can literally omit value error and just catch everything the problem with that is that it sometimes hides other bugs in your code
259:38
Speaker A
because you don't necessarily know what's going wrong and if you don't necessarily know what's going wrong how can you possibly handle it correctly so bad practice and it put another way it's lazy to do that to just say catch
259:48
Speaker A
everything and I'll deal with it here so a much better practice would be to figure out what kind of Errors could happen and include mention of them explicitly as I've done now with that said if you read Python's official
260:01
Speaker A
documentation as you'll eventually invariably do it is not great about telling you proactively what kinds of Errors can be raised in this way so it's a bit of contradictory advice you should do it this way but it's not always
260:16
Speaker A
obvious what you should be checking for but you get better at it with practice and some of the times the documentation does spell out what could go wrong let me turn our attention now back to this and point out that even though this is
260:27
Speaker A
better code it is more correct in the sense that I'm not just leaving it to the user to see some really ugly default python error message that most people are going to have no idea what to do with I'm at least handling it more
260:39
Speaker A
elegantly and I'm printing out X is not an integer so it's at least more instructive but this isn't necessarily the best way to implement this code why well here too I'm actually still being a little lazy so notice that I'm trying to do not one
260:52
Speaker A
line of code but two lines of code and this isn't a huge deal because we're only talking about two lines of code but in the interest of PR uh preaching best practices you should really only be trying to do the one or very few lines
261:06
Speaker A
of code that can actually raise an exception that can actually fail in some way I am pretty sure that calling print here is not going to raise a value error whether X is an INT or a string or a
261:19
Speaker A
float or anything else the format string feature of python is going to handle printing it just fine so really what I'm going to do is this I'm going to move this line three down to the bottom of my
261:31
Speaker A
code I no longer need to indent it I'm just going to execute it at the bottom of my file here unfortunately by doing this I've done a good thing by now only trying to do the minimal amount of work
261:43
Speaker A
necessary that might raise the exception a value error but I fear I've introduced a new mistake well let's see what is now in correct let me go ahead and again run python of number. enter let me go ahead
261:55
Speaker A
and do it correctly with 50 and all seems to be well but again let's try those Corner cases the zeros the negative numbers or in this case the cat let me go ahead and type in C A again
262:05
Speaker A
enter now I have a name error so now it's yet another type of error in my code that I've introduced here and what is this name error mean well just as a value error refers to that the value of
262:16
Speaker A
some variable the value that someone has typed in is incorrect name error tends to refer to your code like you're doing something with the name of a variable that you shouldn't and why might that be well let me turn our attention back to
262:29
Speaker A
the code here and consider what is it complaining about well the name error is what I see down here and it's telling me name quote unquote X is not defined and notice if I look further here it is
262:41
Speaker A
mentioning line six so I know the problem is with my code on line six and that worked a moment ago and I'm defining X on line two but let me ask the group here why does X not in fact
262:56
Speaker A
exist on line six why is it not defined even though I'm pretty sure I was intending to Define it on line two maybe the scope of the variable is between the tri block so good terminology scope refers to the portion of code in which a
263:15
Speaker A
variable exists that to though isn't quite right in Python that would be true in cc++ in Java where indentation or curly braces tend to define the scope of a variable but again here in general and this worked a moment ago X exists once
263:30
Speaker A
it's defined on line two because remember I printed out X is 50 a little bit ago let's try one more hypothesis here one more hand why is X somehow still not defined um yeah so is it because it's loo
263:46
Speaker A
variable meaning that like it doesn't Define outside of scope CU like what people have mentioned it's it as it promps it input in try right but outside of it it's undefined so still good instincts in good terminology too
264:00
Speaker A
there's this notion of local variables which tend to exist inside of functions for instance Global variables which tend to exist in entire files in this case too though that's not quite the case What's Happening Here boils down to
264:12
Speaker A
order of operations let me come back to the code here and recall that anytime we've discussed the assignment operator the single equal sign that copies a value from the right to the left but consider for a moment at what point
264:23
Speaker A
something is going wrong well the input function is probably working just fine because we've used that a lot now to get users input it always returns a string or a stir in Python but what could be going wrong well if I'm passing that
264:37
Speaker A
string to the int function as its argument it's probably the int function that's airing and indeed if you think back earlier when we had the value error it was in fact the int function that did not like quote unquote cat as input so
264:53
Speaker A
this is all to say that this portion of my code highlighted now to the right of the equal sign that's the code that's creating a problem that's the code that was creating a value error and in this case we're catching the value error but
265:07
Speaker A
because the value error is happening on the right of the equal sign there's no value being copied to the left the error is interrupting that whole process so even though we see x equals dot dot dot on line two the portion of that line to
265:22
Speaker A
the left of the equal sign isn't getting evaluated ultimately because the value error is happening too soon and so when we finally get down to line six even though it looked like I was defining on line two and I would have defined X on
265:35
Speaker A
line two if all had gone well we didn't get to the part where the value is copied from right to left because the value error happened first so this code is just incorrect now so how do I go
265:45
Speaker A
about solving something like this well it turns out that there's another feature of the try and accept syntax that python supports which is that it also supports the keyword Els now we've seen Els before if you think back to our
265:59
Speaker A
discussion of conditionals we saw if we saw L if we saw Els which was kind of this catch all what you should do in the event that nothing else is relevant that's kind of the same intuition here for the TR accept feature of py
266:13
Speaker A
what you can do is this you can try to do the following as I've done except if this goes wrong but if nothing goes wrong else go ahead and do this so this is one way I can solve this same problem
266:26
Speaker A
now no matter what now python is going to try to execute line two if something goes wrong it's going to execute lines three and four to handle that value error however if you try and this code succeeds then there is no exception to
266:42
Speaker A
to handle so you're then going to execute this line here so it's a little confusing perhaps in that we're now using Els both for conditionals if L if L if L if Els and we're also using Els with these Tri accept blocks but that's
266:56
Speaker A
okay that's part of the language that's one of the features so now if I rerun this code in my terminal window python of number. piy let's do something correct like 50 I see that X is 50 so line one is executed we're trying to do
267:11
Speaker A
the following line two is executed because the conversion happened successfully and the number 50 gets copied from right to left the exception does not happen so we ignore lines three and four we jump immediately to line five and six which prints out the result
267:26
Speaker A
by contrast though let's do this one last time python of number. piy let's type in cat or again any other word and hit enter now we don't see what x is rather we see quote unquote X is not an
267:39
Speaker A
integer which is what's being handled in my except Clause all right let me pause here because that's a lot of new syntax and see here if there's any questions on try on accept on else name error or value error can you please repeat try
267:56
Speaker A
function repeat the name error what's the problem with the name error yes yes yeah so let's let's just rewind a couple of lines here before I fix this problem by now getting rid of the Els a moment ago we had code that looked like this
268:10
Speaker A
whereby I was getting a name error python of number. piy enter typing in cat that looked like this where name X is not defined and the problem was on line six according to this output in Python well let's think about this now
268:23
Speaker A
deductively let's try a different approach on line six I'm seeing an error that name X is not defined okay Python's already telling me X does not exist at that point so how could that possibly be well where should X be defined well
268:37
Speaker A
presumably X is defined on line two up here so what could go wrong well if the user has inputed something that doesn't look like a number like the word cat passing cat the return value of input as the argument to int to convert the word
268:54
Speaker A
to an INT makes no sense you can't convert a cat C A to an integer at all so the int function is raising a value error at that point and the error is being handled with this code here but
269:09
Speaker A
notice this line six is not indented it's left aligned with the rest of my code which means no matter what line six is going to execute it's going to execute whether I typed in 50 or I typed in cat but if I typed in cat again X
269:24
Speaker A
never gets a value so it's not defined here on line six so when I introduced finally the Els statement that makes sure that these things are mutually exclusive I only execute the Els if I tried and succeeded up above well let me
269:41
Speaker A
propose that we we refine this just a little bit further as well and consider how we might improve this example a little bit more it's a little it's a little unfriendly of me to be rejecting the user's input after they fail to
269:56
Speaker A
provide an integer and just quitting the program really right it'd be more userfriendly if I just prompt or reprompt the user again and again and in the chat if you could what's the feature of python that you can use if you want
270:09
Speaker A
to do something again and again and again until such time as the user cooperates and gives you what you're looking for like a number so yeah loop loop loop so a loop is something that happens again and again and again and
270:23
Speaker A
maybe we can use that same mechanism a loop in order to prompt the user for x and if they don't give us a number prompt them again and if they don't prompt them again and again and again we
270:32
Speaker A
don't need to just quit out of the program so quickly so let me propose this let me propose here that I improve this code by deliberately doing this let me induce a infinite loop at the very top of my code
270:45
Speaker A
with while true recall that the while keyword induces a loop a cycle that behaves like this and it asks a question a Boolean expression that needs to evaluate either to true or false well if I want this thing to Loop Forever at
270:57
Speaker A
least initially we'll just say while true because true is true so this has the effect of doing something no matter what forever unless we break out of it early now I'm going to go ahead and do this I'm going to go ahead and move my
271:11
Speaker A
triac C code indented underneath this Loop so that I'm trying to get an X if I have a value error instead I print that X is not an integer but this time what do I want to do if the user does try and
271:26
Speaker A
succeed in giving me a number well I can do this I can just break out of my code here and down here now I can use that same line of code from before an F string that says X is and then in curly
271:39
Speaker A
braces X again so what's going on here I think this codee now because I've added the loop is going to have the effect of trying at least once maybe a second time maybe a third time maybe 500 times until
271:53
Speaker A
the user finally gives me what I want which is an integer and once they do once there's no value error happening then I break out of the loop and line nine executes as I would hope so let me
272:05
Speaker A
go ahead and try executing this version python of number. piy enter what's X let me go ahead and type in the easy thing first 50 x is 50 what just happened in terms of the control flow of this
272:17
Speaker A
program the flow of my logic well I first found myself on line one inside of a loop hopefully I'll get out of this Loop what did I then do on lines two and three I tried to get input from the user
272:28
Speaker A
and convert it to an INT well I was a nice guy this time and I typed in 50 which looks like and is a number so the int function converted it just fine and stored it from right to left in X except
272:39
Speaker A
value error there is no value error because if I typed in a number there's there's nothing exceptional happening this is a boring good execution of my program so what happens I break out of the loop so again the else Clause is
272:52
Speaker A
associated with the try not with the accept and once I'm out of the loop of course I'm just printing out what x is well let's try the other scenario that might happen python of number. piy enter what's X let's try cat or any other word
273:06
Speaker A
enter ah this is now a new feature I'm being informed what I did wrong X is not an integer so I'm getting some useful user feedback but notice again I'm prompted what's X well let me try typing in dog X is not an integer what's X let
273:22
Speaker A
me try bird enter X is not an integer what's X and suffice it to say this will happen now forever if I'm in an infinite Loop until I try and succeed at which point I break out so let's try again 50
273:35
Speaker A
enter now I'm out of the loop and I'm printing out what x actually is all right let me pause here and see if there are any questions the logic is almost the same but what is different now is
273:47
Speaker A
I'm in a loop and I'm using the keyword break in Python to deliberately break out of the loop when I'm ready to once the user has cooperated do we really need to break can't we just print or what what keeps us from just printing uh
274:05
Speaker A
good question so let me try that couldn't I just print well let's see what happens if I do that let me move this print line at the end in into my Loop here thereby shortening the program and in general that's been a good thing
274:16
Speaker A
python of number. piy enter let me go ahead and type in 50 okay X is 50 what's x uh okay maybe it's 49 x is 49 uh okay maybe 48 unfortunately I think you're you're laughing you see it I never break
274:30
Speaker A
out of the loop which maybe that's a feature maybe you want this to be your program but I didn't I'd eventually like this game to stop so I need to break out in that way but I can do it a little
274:39
Speaker A
differently and let me propose that we modify this a little bit but first any other questions on this syntax here let me rewind to the prior version he uh can I use break uh all in exception except in else for example in
274:58
Speaker A
another uh print and when you use print in the else you can use print together with break or something like this yeah you so you can use break inside of Loops to break out of loops and you can use it
275:10
Speaker A
inside of a conditional like an if an L if or an else you can do it inside of a try accept else statement too anytime you're in a loop that you want to break out of you can use this keyword break
275:21
Speaker A
I'm using it in the context of exceptions but it's not restricted to that and let me show you too it doesn't even have to be in the Els if I wanted to I could actually do this I could get
275:31
Speaker A
rid of my elt and I could go back to line three add another line that's indented line four and break out here now why is this logically okay well well consider what I'm now trying to do I'm trying to execute line three and
275:47
Speaker A
converting the user's input to an INT and I'm trying to store the result from right to left in X if something goes wrong the code we've already seen is immediately going to jump to line five and then six to handle the exception but
276:02
Speaker A
if nothing goes wrong my code presumably should just keep on executing line by line so I could technically logically put the break here and watch what happens when I run this version python of number. Pi 50 enter it worked I broke
276:17
Speaker A
out of the loop now which way is better honestly I think it could go either way at this point this program is so relatively short that even though I'm trying to do two things now one of which the break is not going to fail like you
276:30
Speaker A
either break or you don't there's no piece of data from the user that's going to influence that we don't strictly need to have those two lines of code there but it's only two lines so I think it's okay and if you recall our discussion in
276:41
Speaker A
the past not just of correctness does the code work as it should but design I think you could argue it either way if you prefer the readability of this and the fact that you don't have an El that's fine if though you prefer to
276:52
Speaker A
minimize just how many lines of code you're trying to execute in case something goes wrong the else is a reasonable approach too well allow me to propose too now that we refine this further I think we're at the point where
277:04
Speaker A
it's pretty darn correct but suppose now that I find myself today and tomorrow trying to get numbers from the user quite a bit it would be nice as we've seen to maybe just invent my own function get int to get an integer from
277:18
Speaker A
the user both today and tomorrow and Beyond and heck maybe I can even share that function with other people if they want to write programs that get integers from users so how might I go about doing this well let me go ahead and propose
277:29
Speaker A
that we do this let me get rid of the print line but keep most of my Loop here let me Define a function called get int that takes no arguments for now and I'm going to go ahead and indent all of the
277:39
Speaker A
code I already wrote underneath get in so now I have a function called get int that tries to do the following try to get an in from the user if something goes wrong and there's a value error yell at them with X is not an integer
277:53
Speaker A
else break but it's not just breaking that I want to do here now that I'm in a function recall our discussion of return values if you're inventing your own function whose purpose in life isn't just a print something on the screen
278:06
Speaker A
like a side effect but is to hand back a value to hand you back value like on that same Post-It note from our discussion of functions well you need to return X explicitly how do I now use this function well as soon as we start
278:20
Speaker A
making our own functions it tends to be convenient to Define our own main function as well that's the main part of our program and I'm going to keep this simple I'm now going to say x equals get int and then on the next line I'm going
278:32
Speaker A
to do that print from before quote unquote X is in curly braces X and at the very bottom of my program recall I'm going to call Main so that no matter what I'm invoking my main function after everything's been defined well let's see
278:45
Speaker A
how this works let me go ahead and run python of number. Pi enter let's type in 50 and it seems to work as before let's go ahead and run it again typing in cat C A this time X is not an integer and
278:58
Speaker A
I'm being prompted dog and I'm being prompted bird and I'm being prompted fine fine fine 50 that's an INT and so it is printed so what's worth noting here well I'm manifesting a couple of good properties here one
279:12
Speaker A
I've kind of abstracted away this notion of an getting an integer and even though I just artificially hit enter a whole bunch of times just to hide that function for now it needs to be there but we don't need to see it at this
279:22
Speaker A
point notice that now this entire program really boils down to just these three lines of code now why because I've abstracted away that whole process of getting an INT from the user into this new function of my own called get int
279:35
Speaker A
but can I improve upon this well let me go ahead and undo all of those blank lines and pull this up just so we can see more on the screen at once can I tighten up my implementation of get int
279:45
Speaker A
it is correct I claim this is correct it's handling errors and it's returning X but I don't strictly speaking need to write the code as long what else could I do well let me propose that if all you're doing on this line 13 is breaking
279:59
Speaker A
and then immediately after that per the indentation you're executing return X on line 14 why are you wasting everyone's time once you know you're ready to return the value you could just return X and so in my else I could break out and
280:13
Speaker A
return a value so here too return is used to return values from functions break is used to break out of Loops but it turns out that return is sort of stronger than break it will not only break you out of a loop it will also
280:29
Speaker A
return a value for you so it's doing two things for once if you will but can I make this even more compacts if if if my goal is to just tighten the code up even though it's already correct can anyone
280:43
Speaker A
think of a further refinement whether you've programmed in Python before or not can I shorten this implementation further just a little bit if only to decrease the probability that I've made a mistake by having fewer lines and just
280:56
Speaker A
make it a little easier to read because it's shorter any suggestions for tightening up my implementation of get int you can just return the value on the try function when you're trying uh at you take you take the input X and then
281:12
Speaker A
done X good we can just return x a little higher up and let me correct folks as we go it's not a tri function it would be a tri statement technically a function typically has a parenthesis and another one in this case it's just a
281:23
Speaker A
statement so but we can do exactly that I don't technically need the else if I really want I could do this right after line nine I could return X here or recall our discussion of defining variables unnecessarily sometimes like
281:38
Speaker A
why Define a variable here if you're immediately going to use it here and then never again so we could avoid a new line here and I could avoid even defining X explicitly I could just say something like this I could return int
281:51
Speaker A
input quote unquote what's X I can do it all at once now which is better I don't know I mean again this is where reasonable people might disagree I'd argue that on the one hand we're tightening up the code we're using fewer
282:04
Speaker A
lines it's easier to read lower probability that I've made a mistake on the other hand it's a little more complicated to understand perhaps it's a little less obvious where I'm returning from so I think arguments can be made
282:16
Speaker A
either way at the end of the day what's important is that you've done this consciously you've made a decision to do it this way or this way and you can justify it in your mind not that your answer is uh it worked so I left it
282:27
Speaker A
alone like have a good reason come up with a good reason and that will come with experience and practice well let me propose too that we make one other refinement here suppose that you're finding your programs to be a little
282:38
Speaker A
noisy and it's a little obnoxious that you keep telling the user X is not an integer X is not an integer X is not an integer what if you want to make things a little gentler and just prompt the
282:49
Speaker A
user again with the same words what's x what is X what's X again and again well you can do that as well and it turns out that if you want to handle an exception in Python but you want to pass on doing
283:02
Speaker A
anything with it so you want to catch it but you essentially want to ignore it you don't want to print anything you don't want to quit the program you just want to silent ently ignore it like if you're talking in a gr full of people
283:14
Speaker A
and you're it's your turn to talk and you're just like pass they're still calling on you but you're not doing or saying anything more well we can add this keyword to our code here let me go back to my program here and instead of
283:26
Speaker A
printing out again and again X is not an integer I could just do this I could pass on handling the error further I'm still catching it so the user is not going to see a scary message even mentioning value error my code is
283:39
Speaker A
catching it but I'm passing on saying anything about it I'm going to stay in the loop I'm going to stay in the loop and keep prompting and repr prompting the user so now the effect looks a little something like this python of
283:49
Speaker A
number. piy let's type in cat what's X again let's type in dog what's X again type in bird so it's just a little maybe more user friendly and that you're just reminding the user what you want maybe it's worse maybe it would be helpful to
284:03
Speaker A
tell the user why you're prompting them again and again it's not obvious so it could go both ways but again it's just another mechanism now for handling these errors we use the accept keyword to catch a specific error but we don't have
284:16
Speaker A
to handle it more than that we can just pass on doing something further let me pause here and see if there's any questions now on try accept else or pass okay yeah know I was just kind of curious I guess about uh the idea of
284:32
Speaker A
when you were indenting with uh the get in function for example um because I'm noticing you know obviously going through it with the whole logic and breakdown the entire uh the entire function you know while true do this but
284:45
Speaker A
I'm just kind of curious on elaborating with the indentations for the uh code more yeah so the indentation is deliberate logically some languages don't require as rigorous indentation you can use curly braces or other symbology to make clear what is
284:59
Speaker A
associated with what in general anytime you indent something in Python on this line so rather anytime you write a code a line of code in Python that's here and the lines below it are somehow indented that means that those lines are somehow
285:13
Speaker A
associated with that first line and presumably those indented lines should only be executed if the first line told the uh uh told the computer to do so so concretely what does this mean on line six here we're defining a function
285:27
Speaker A
called get int that takes no arguments colon everything that's indented by at least four spaces Hereafter is part of that function why that's just the design of the Python language frankly I think the designers got tired of seeing really
285:42
Speaker A
ugly code in languages like C and C++ and Java uh that uh don't necessarily enforce uh indentation to this extent so now it's baked into the language and my chronology might be a little off there but there's been many languages that are
285:56
Speaker A
looser than python when it comes to indentation the indentation is Meaningful on line 72 notice that because the while true is indented by four spaces that just means it's part of the get in function but notice below the
286:09
Speaker A
while true statement there's eight there's 12 there's eight there's 12 spaces here and I'm just quickly counting the dots that means that all of the lines I've just highlighted are inside of that while loop while true means to execute lines 8 through 11
286:23
Speaker A
potentially again and again and again and now lastly on line eight because we have try and indented below it is line nine that just means that what you should try is what's on line nine and similarly on line 10 below it we have
286:38
Speaker A
indented line 11 you should only pass when there is an exception of a value error so the indentation just means what is associated with what and once you get comfortable with that you'll see that it helps the indentation alone helps
286:52
Speaker A
explain the logic of your program and it has a wonderful side effect that for yourself the next morning for your colleagues your family your friends your teachers your code is much more readable as a result it's not one big mess of a
287:05
Speaker A
blob of text other questions now on try except else or pass yeah thanks um two question uh question one um uh once you say pass can the caller still um learn anything about this error um through a system variable or whatever and question
287:25
Speaker A
two problem set zero referenced some string Methods including is numeric is it any different to um go via isomeric here good question so on the first question if I'm handling the error in this way the caller is not
287:42
Speaker A
going to know anything about it that's the point of my handling it so that Maine or other callers don't know that anything technically went wrong on the second question is numeric is another function that you can call that can look
287:53
Speaker A
at a string and determine is this in fact a number I could use a mechanism like that I could use a conditional if this looks like a number then pass it to the int function and go ahead and
288:05
Speaker A
convert it to an integer that's totally fine I would generally say that the pythonic way of doing things is often For Better or For Worse to try things hope they work but if they don't handle the exception so other languages are
288:20
Speaker A
more in favor of checking if if if if L if else and all of these conditionals python tends to be a little more of the mindset eh try it but just make sure you're handling the error so this would
288:32
Speaker A
be the pythonic way of doing it your way though checking with a conditional is it a number first is totally reasonable too if you want to go that way well let me propose some final refinements to this program that really just kind of tighten
288:44
Speaker A
things up one additional step to improve the implementation of this get in function let me propose that we not hardc code so to speak that is type manually X all over the place let's make this function get int a little more
288:58
Speaker A
reusable right now notice that I'm just kind of using the honor System that well main is defining a variable called X and get int is asking for a variable called X but it would be nice if the caller
289:12
Speaker A
main doesn't have to know what the call is naming its variables and vice versa so caller to call a function means to use it the caller is the function that's using it the call E is just the function
289:23
Speaker A
being called it would be nice if I'm not just hoping that X is the same in both places so let me propose this let me propose that we actually add a parameter to get int like this what's X that is to
289:39
Speaker A
say if main wants to use the in function well then main should probably tell the get in function what prompt to show the user just like the input function recall that comes with python it's up to you to
289:50
Speaker A
pass in a prompt that the user then sees when the human is asked for input so how do I make this work here I can go down to my definition of get int and I can say all right get int is going to take a
290:02
Speaker A
parameter now called prompt I could call it anything I want but prompt in English is pretty self-explanatory it means what do you want the message the user will see and now down here when I actually use input I don't have to presumptuously
290:15
Speaker A
say what's X because what if the program the caller wants to ask for y or Z or some other variable I can just pass to input whatever prompt the caller has provided so now I'm making more reusable code it still works just the same I
290:30
Speaker A
haven't changed the functionality per se but now it's a little more dynamic because now get int doesn't have to know or care what variable is being asked for what's being asked for it just needs to know what prompt it should show to the
290:43
Speaker A
user so if I now run this program down here again prompt number. piy enter what's x 50 still seems to work let's run it again let's type in cat it still seems to work and if I type in cat dog
290:55
Speaker A
bird or anything else it will keep prompting me with that same prompt making this code therefore all the more usable now it turns out too you can even raise exceptions yourself using Python's raise keyword but more on that another
291:09
Speaker A
time so in the coming days the coming weeks the coming months as you write more code in Python you'll see that errors are inevitable sometimes there's syntax errors which you got to just fix if you even want to run your program at
291:20
Speaker A
all but they could be name errors for instance variables that you meant to Define but somehow didn't value errors where maybe the user didn't cooperate and provided you with something that you weren't expecting or a whole list of
291:32
Speaker A
other possible errors or exceptions but now hopefully you know how you can handle these errors and respond to them in any way you like this then was our look at except and we'll see you next [Music] [Music] time all right this is cs50's
292:12
Speaker A
Introduction to programming with python my name is David Meen and this is our week on libraries so libraries are generally files of code that other people have written that you can use in your own programs or a libraries code
292:25
Speaker A
that you've written that you can use in your own program but maybe not just this program but another and another as well so python supports exactly this idea this ability to share code with others share code across your own projects and
292:37
Speaker A
it does so by way of what it calls module a module in python is just a library that typically has one or more functions or other features built into it generally the purpose of a library or a module specifically is to encourage
292:51
Speaker A
reusability of code if you find yourself using the same types of functions again and again the same functionality if you find yourself copying and pasting from an old project into your new project odds are there's an opportunity there to
293:05
Speaker A
factor out that code that you keep copying and pasting that you keep reusing and put it into a library that you can then load into your programs moving forward so as to not just copy and paste it and have all these
293:16
Speaker A
different copies all over so what are some of the modules or libraries that python comes with well python comes with a random Library literally which is to say that when you install the python interpreter on your Mac or PC or
293:29
Speaker A
somewhere in the cloud not only do you get python you get a whole bunch of modules as well now these modules provide you with functions that you don't have access to just by default like you do print and input print and
293:41
Speaker A
input and other such functions just work in Python but sometimes functions are tucked away in these modules so you have to be more deliberate about loading them into the computer's memory so somewhere on the computer's hard drive once you've
293:54
Speaker A
installed python there is also it turns out a file probably called random. py that someone else wrote probably long ago but that you have access to and in that random. piy file there's probably one or more functions that you yourself
294:07
Speaker A
can use in order to do things randomly that is to say how could you flip a coin in a program in Python how could you pick a a random number between 1 and 10 in Python well you need a bit of
294:19
Speaker A
Randomness and while you could figure out mathematically how to write functions like that yourself it's a lot easier to stand on the shoulders of others who've already solved that problem for you so you can focus on the problem that you yourself want to solve
294:33
Speaker A
so for documentation on most any python module you go to the official python docs and you go to a URL like this where the documentation for that specific module lives and within the documentation you'll see a list of the
294:45
Speaker A
functions or other functionality that some module provides but how do you go about loading a module into your own program so that you can use the functions in that module well we need a new keyword in Python and namely it's
294:59
Speaker A
import the import keyword in Python allows you to import the contents of the functions from some module in Python well how might I go about using using this in practice well let me propose that there exists in that random module
295:15
Speaker A
this function among others so I have copied and pasted from the documentation uh this uh summary of a function called choice now the function exists in the random module so to speak not a random module the random module and so
295:31
Speaker A
generally the documentation describes it fully like this random. choice is how you would technically call this function though we'll see alternatives to that in parenthesis there is a parameter called seq for sequence and sequence generally means a list or something that is list
295:47
Speaker A
like if you have a list of numbers or strings or anything else and the documentation elaborates well how can I go about using this function to solve perhaps a a familiar problem well let me go ahead and open up vs code here and
295:59
Speaker A
let me propose that we Implement a program that simulates flipping a coin a coin that in the US heads heads or tails the idea of which is to pick a decision with 50/50 probability 50% probability of heads 50% probability of Tails or you
296:15
Speaker A
can use some other mechanism like that well let me go ahead and open a program with code called generate. piy because I want to start generating a whole bunch of random information the first of which is just going to be a coin toss now how
296:27
Speaker A
do I go about using that function well I first have to import the random Library so literally the first or among the first lines of my file should be import random and that just gives me access to all of the functions in that specific
296:40
Speaker A
specific module now suppose I want to flip a coin well I can do random. Choice per the documentation a moment ago and that again takes a sequence what's a sequence it's a list or something that's list like and we know about lists we've
296:54
Speaker A
used lists to iterate over numbers we've used list to iterate over students at Hogwarts let's go ahead now and list iterate over just a list of two sides of a coin heads quote unquote or tails now I could call these anything I want these
297:08
Speaker A
are my strings I just want to simulate tossing a coin so I'm just going to say in all lower case heads and tails but notice the syntax I have heads and tails in double quotes that's because they're strings I could also use single quotes
297:20
Speaker A
so long as I'm consistent there's a comma between them which means the list has two elements there's square brackets to the right and the left which indicates that this is indeed a list that's the syntax recall for defining a
297:32
Speaker A
list in Python and then lastly there's something more familiar there's the parentheses outside of those square brackets but those are just the parentheses that belong to the choice function and specify where its parameter gets passed in but again unlike ped
297:46
Speaker A
functions I have to specify what module this function is in at least for now and so I do random. choice to call this specific function all right well it's one thing to flip a coin picking between those with 50% probability and that's
298:00
Speaker A
what random. choice does it takes in a list and it returns to one of those values randomly with equal probability because I've passed in two items I've got a 50/50 chance if I passed in three items it'd be a 33% chance for each of
298:13
Speaker A
those items and so forth python does the math for you but I want to store the value of this in a variable so let's Define a variable called coin equals whatever the return value is so this is indeed like flipping a coin I'm going to
298:25
Speaker A
store in a variable called coin whatever that value is heads or tails and now just so I can see what's going on let's go ahead and print out the value of that string coin all right let me go ahead
298:36
Speaker A
now and run this program in my terminal window python of generate. P enter and it looks like the first coin toss was the heads let's go ahead and run it again and it looks like it was heads again maybe you want to chime into the
298:49
Speaker A
chat here if I run it a third time what's it going to be this time if you want to type your thoughts in the chat you might think there's a bug here but this is probability in action if I
299:00
Speaker A
go ahead and hit enter a third time there it's actually now tails and again tails and again tails and again tails and again tails and again heads now if we did this in infinite number of times it would indeed work out to be 50/50 if
299:13
Speaker A
we only do it a few times it might not work out as cleanly but that's how probabilities indeed work all right so I've got that now working could I have implemented this in a different way well let me show you an alternative to
299:25
Speaker A
actually using the import keyword alone and let me introduce the keyword from in Python so from is a keyword in Python that you can use when importing functions from a module but it allows you to be a little more specific than
299:39
Speaker A
import Al Lo so if I go back to my code here it's worth noting that what technically I'm doing here by importing random is I'm technically importing everything that's in that module so not just the function called random. choice
299:54
Speaker A
but a few other functions as well so instead of using this line of code at the top of my file import random which will technically give me access to all of the contents there in a downside of that is that I have to type in random.
300:06
Speaker A
choice random. this random. that because all of the functions I'm calling have to be associated with the scope of that module well suppose that I just want to call the function as its name choice I can do that as well let me replace this
300:19
Speaker A
first line here with from random import choice and what this does effectively is it loads the functions name Choice into my current name space into the scope of the file I'm working in what that means is that I now know longer have to
300:35
Speaker A
specify Which choice function I mean I can just say choice and so it loads it into the local namespace that is into my local vocabulary if you will so I can just now say choice this might be advantageous in what cases do you think
300:50
Speaker A
when might you want to import the name of the function explicitly like this as opposed to just saying random. choice random. choice throughout your code when calling a function any instincts here for this alternative import using from um hello I'm Mohammed from Egypt and
301:09
Speaker A
maybe if we have a variable that its name is basically like choice if I have a variable called the choice so I need to differentiate Which choice I choose so I'm gonna choose random DOTA Choice yeah really good instincts by using the
301:24
Speaker A
first approach by just importing random you're making sure that all of its contents are associated with are scoped to the random module so that you can have your own choice function you can have your own choice variable you can
301:37
Speaker A
use the same names as all of the functions or variables that are stored inside of that file without them colliding so to speak and this is a good thing in older languages it was the case that if you imported someone's Library
301:48
Speaker A
you better hope that you're not using the same functions or variables as they are because you might in fact have some kind of conflict Python and certain other languages allow you to scope the names of those functions and variables
302:00
Speaker A
to the file or the module that they come from so that's a good thing but honestly this is such a short program or equivalently maybe I'm using the choice function in so many places calling random. choice random. choice random.
302:14
Speaker A
choice it's just making my code longer and longer and longer marginally so but it just getting ugly and annoying I can simply import choice and now tighten up my code a little bit so as with so many decisions in the past there's not
302:26
Speaker A
necessarily one right approach or another it depends but I think for those very reasons sometimes it's better to do what we did the first time which is only import the module so as to retain the scope therein well let me propose that
302:39
Speaker A
we transition to to another function that comes with Python's random module and that's this here from the documentation Rand int it's a bit hard to say but it implies get back a random int and if you read the documentation
302:51
Speaker A
it's a random int that's between A and B inclusive so if you were to pass in one for a and 10 for B you would get back a number between one and 10 inclusive including the one and including the 10
303:03
Speaker A
potentially each with a 10% probability so how might I go about using a program like this well let me come back to my generate. piy file and why don't we go ahead and try generating a random number between 1 and 10 you might do this
303:15
Speaker A
frequently in the real world when you just want someone to pick a random number you tell them as much and the human responds let's get the computer to do the same here let me go ahead and delete my two lines of code at the
303:25
Speaker A
bottom but keep my import random and let's go ahead and Define a variable this time called number set it equal to the return value of random. randint and now pass in a a value of one and B a
303:37
Speaker A
value of 10 and now let's go ahead and print the number I'm going to go ahead in my terminal window and run python of generate. Pi and hit enter four python of generate. Pi and hit enter eight again nine again s again 10
303:55
Speaker A
again two again and we can do this all day long and if we add all of those up they should end up being with 10% probability each now how might you use this information well maybe we're playing a guessing game or maybe we're
304:07
Speaker A
trying to randomize the behavior of some character in the game you can imagine using very simple building blocks like this just kind of spicing up your program by getting it to do things a little less predictably because you're
304:20
Speaker A
choosing these values seemingly randomly and you're deferring to python to actually do the generation of these numbers uh using its own algorithms and its own math well what more could we do here let me propose that we introduce
304:31
Speaker A
another function that comes from this random Library yet another that you yourself have don't have to implement Shuffle if you read the documentation for Shuffle in the same random module you'll see that it takes in a list for
304:43
Speaker A
instance of values and just shuffles them up it randomizes them like a a deck of cards here you might shuffle them so it's to put them into seemingly random order well how do I use this based on this function's name well let me propose
304:55
Speaker A
that we go back to vs code here and let me go ahead and this time do the following because I need to shuffle something like a deck of cards let me go ahead and not just import random but let
305:05
Speaker A
me give myself a variable called cards that's going to be of type list and just so I have something to shuffle I don't need all 52 cards in a typical deck I'm just going to shuffle three cards a jack
305:16
Speaker A
a queen and a king I could call those strings anything I want but I just wanted a list of some values so as to shuffle them up that is randomize the order therein well how does this now work if you read the documentation for
305:27
Speaker A
random. Shuffle you'll see that it shuffles the argument in place that is unlike many of the functions we've seen it doesn't return to a value that contains the shuffled cards in this case it actually shuffles the list it's given
305:42
Speaker A
itself so what this means for my code is that I need to do something like this random. Shuffle and pass in the variable containing those cards and then on a final line here how might I go about printing the cards well I could do this
305:58
Speaker A
and I could say print cards but if I do that I'm actually going to see python Syntax for lists and it's just going to format in its own way using commas and the like I want to print these cards out
306:08
Speaker A
one at a time just because I think it'll look a a little better so we can use some of our syntax from loops and say something like this for card in cards go ahead and print out the current card so
306:19
Speaker A
what's now Happening Here line three I'm defining a list of three cards in this order Jack queen king I'm then shuffling those same cards on line four and then on line five I'm using a for Loop for each of the cards in that list print it
306:35
Speaker A
out one at a time and because I'm using print one line at a time well let's see the results down here in my terminal window I'm going to run python of generate. and hit enter queen king Jack seemingly shuffled cuz that's not the
306:48
Speaker A
order I defined earlier let's do it again queen king Jack H okay that happens to be the same but let's see this could just be bad chance there we go Jack queen king doesn't look like it's shuffled but at least we're getting
307:02
Speaker A
back different orderings now again jack queen king hm not so good Jack queen king not so good this is someone you you probably want to play against with cards Queen Jack King there we go but of course we only have three cards here so
307:15
Speaker A
there's not that many permutations we might see and if we do this over time we will see all of them but if we had of course 13 or 52 cards we'd see a lot more permutations instead so we have now
307:26
Speaker A
these three ways to Generate random information one is simple coin toss if you want to start some kind of athletic event one pick a number between one and 10 if you want to decide something based on that and now using Shuffle we can
307:38
Speaker A
even take in a list of things and shuffle them about so that we get some kind of random Behavior let me pause here and see if there's any questions yet on random on modules or any of these three
307:51
Speaker A
functions yeah uh can we increase or decrease the probability uh of costs if you want to for example there is three there is a 33% chance of probability so is there any chance to increase or decrease the probability can
308:08
Speaker A
you set these probabilities not using these same functions uh can you set the probabilities but you can absolutely Implement some of your own functions or use more sophisticated functions that do exist in this library and others to exercise more control these are meant to
308:22
Speaker A
be very userfriendly and simple functions certainly the ones we looked at that give you equal probability for all of those but absolutely you could skew things though hopefully if you're implementing a gambling game or the like you're not actually making some cards
308:34
Speaker A
more probable than others allow me to turn back now to our implementation here of this Randomness and consider how we might leverage other types of functionality that aren't necessarily in this specific Library here well it turns out that python also comes with a
308:49
Speaker A
statistics library and this contains all sorts of functions for doing things more statistical in nature namely calculating means or medians or modes or other uh aspects of a data set that you might want to analyze so how might we use the
309:03
Speaker A
statistics module on python well we might first just take a look at its documentation like any other module on Python and we'll see Within that library that there's a whole bunch of functions and one of those functions is one that's
309:13
Speaker A
quite simple it's average a function that allows you to calculate the average of some numbers that you've passed in let me go ahead and nvs code in my terminal window open up a new file called average. piy and at the top of
309:26
Speaker A
this file I'm going to import a different Library this time namely the statistics module in Python and now I'm going to go ahead and call a function that I know comes in that module namely mean for the average of some values and
309:39
Speaker A
I'm going to call Stat statistics. mean and I'm going to pass into this function mean a list of some values and let's suppose that I'm quickly trying to calculate what my current grade average is in school and I did really well on my
309:51
Speaker A
first test and I got 100% And on my second I did well but not as well and I got a 90 and ironically I'm not very good with math so I'd like to figure out what my average now is between those two
310:01
Speaker A
tests so let me go ahead now and in this list type in the number 100 comma 90 thereby passing in a list of two values to ins one 190 and in outside of those are the parentheses because of course
310:13
Speaker A
this is now the argument I'm passing to the function called mean and this function mean is in the module called statistics well it's not that interesting to just calculate the mean if I don't actually see what it is so
310:25
Speaker A
let me additionally pass the return value of that mean function to the print function as usual let me now in my terminal window and vs code Type in Python of average. piy and hit enter and voila as you might expect my average is
310:38
Speaker A
95% so the difference here is that I'm just using a different module that still comes with python but I need to import it instead of for instance the random module instead and this time I know from the documentation that there exists a
310:50
Speaker A
function called mean well it turns out there's even more functionality that comes with python and that comes with other modules in Python and there's this feature generally known as commandline arguments this is a feature not just of python but of languages more generally
311:05
Speaker A
that allow you to provide input not when prompted inside of a program as happens whenever we call the python function input but rather there's this feature command line arguments of programs that allows you to provide arguments that is
311:20
Speaker A
input to the program just when you're executing it at the command line so up until now for instance Rec call that we've generally run python of something.
311:28
Speaker A
py for instance python of hello.py and I've never once really executed any words or phrases after the name of the file but I could in fact when you're running programs in a command-like environment like we are you can provide
311:43
Speaker A
any number of words or numbers or phrases after the command that you're typing and all of those will somehow be passed in as inputs to the program itself you don't have to prompt the user for one thing at a time by manually
311:58
Speaker A
calling that input function so what does this mean in real terms well let me go ahead back into VSS code here and let me propose that we consider how we might leverage a certain module I'm going to go ahead and create a file called uh
312:12
Speaker A
name. pi and I'd like to use a new module this time that's going to give me access to values that have been typed at that command line but what's this module going to be well this one's going to be
312:23
Speaker A
called CIS and CIS short for system contains a whole lot of functionality that's specific to the system itself and the commands that you and I are typing the documentation for this module is at this URL here and it lists all of the
312:36
Speaker A
various functions and variables and the like that come with that module but we're going to focus on something a little more specific namely this thing here it turns out in the CIS module in Python there is a variable that just
312:49
Speaker A
magically exists for you called argv it stands for argument Vector which is a fancy way of describing the list of all of the words that the human typed in at their prompt before they hit enter all of those are seemingly magically
313:04
Speaker A
provided to you via python in a variable called cis.org V this variable is a list which means that the first element is going to be the first word that you typed the second element is going to be the second word that you typed and so
313:17
Speaker A
forth and by way of this list then can you figure out what words did the human actually type at the prompt and maybe use that to influence the behavior of your own program so what does this mean now in real terms well in this new tab
313:29
Speaker A
called name. piy let me go ahead and import CIS within that CIS module is going to give me access to cy. RV but how might I want to use it well let's do this instead of writing a hello world
313:42
Speaker A
program that all of these times has just looked for the return value of input to figure out what the user wants me to print let's go ahead and just expect the user to tell us when they run the Python
313:53
Speaker A
program itself what their name is and suppose this time I'd like to generate a whole bunch of name tags initially just one and in the US here it's very common to wear a sticker on your lapel that says hello my name is David so I want to
314:05
Speaker A
print out some text that resembles that the idea being maybe I could enhance this program someday to even send that text straight to the printer and dynamically generate those name tags well let me go ahead now and do this let
314:16
Speaker A
me go ahead and print out as always hello but I'll say a little something more this time to make things more interesting hello my name is quote unquote and then after that I normally have been in the habit of calling input
314:29
Speaker A
storing the return value in a variable and passing in the name of that variable here but I'm going to instead jump right to this sis. RV bracket1 and that's it I'm going to have a program here that says hello my name is followed by
314:44
Speaker A
whatever is in sis. arv bracket one and notice sis. argv again is a list and recall from our discussion of loops and in turn lists we use this square bracket notation to get at the various elements inside of a list all right let me go
314:59
Speaker A
down now into my terminal window and run python of name. py but this time rather than just hit enter and wait for the program to prompt me for my name let me proactively just tell this prr program what my name is at the so-called command
315:11
Speaker A
line here we go David separated with a space from the name of the file so that now when I execute python name. py David I see on the screen voila hello my name is David So based on this demonstration
315:26
Speaker A
alone I think we can infer exactly what's going on in cy. RGV even though it sounds certainly at first glance uh rather complicated here let's look up at cy. Arvy I'm going to bracket one here so clearly cy. RV bracket one is storing
315:44
Speaker A
David but it's one in the past when we looked at Loops recall that we said that they were zero indexed that is the first element is zero the next element is one the next element is two and so forth and
315:58
Speaker A
yet here I am treating it as though my name is at the start of the list one well let me ask this question what is probably insist. arv of zero what is probably insist. Arvy of zero the very
316:14
Speaker A
first element actually in that list oh yeah uh I think uh it's like in C uh the name of program indeed it's indeed like in C and other language is the name of the program well if we consider what it
316:28
Speaker A
was I typed I certainly typed python because that's the name of my interpreter and we don't really need to know that because we're using python itself but after that I did type two things I typed name. as I've done so
316:40
Speaker A
many times anytime I want python to interpret a program I've written and it turns out by convention what python does is it stores in cy. arv the name of the file that you're executing or interpreting followed by any number of
316:54
Speaker A
other words that you type so all this time we could have been accessing the name of the program which frankly isn't all that interesting but we can also now access words that are typed after that prompt as well but of course if I don't
317:08
Speaker A
type anything in what might happen here this might be naive of me to assume that there's always going to be something at location one in cy. RV let me go ahead and try this python name. pi and no I'm not
317:20
Speaker A
giving you my name because at this point I might not even know that you want my name to be typed so let me hit enter now and uhoh we see now an error a so-called exception in Python this one's a new one
317:31
Speaker A
this one's an index error that elaborates list index out of range and turns out this is actually one of the most common mistakes in programming whether using a list in python or arrays or vectors in other languages is to try
317:45
Speaker A
to access some element that does not exist you try to go too far to the left or you try to go too far to the right in this uh in this object that is just a list of some values so of course the
317:57
Speaker A
mistake here is that I'm assuming there's going to be something at location one when really it's location zero that's the only one that has a value but fixing this is not going to amount to doing bracket zero because now
318:09
Speaker A
if I go ahead and rerun this program with no other words after name. it says hello my name is name. which is fine if we're making a name tag for the program but that's not of course what my goal
318:20
Speaker A
here is instead so if the fix is not just to change the one to a zero how else might I handle this error how else might I handle this error this index error that happens if the user just doesn't remember to or doesn't
318:36
Speaker A
know to type their actual name at the prompt we could always put an exception into the program saying if there is um if there's nothing at location one we just come out the say okay we haven't got a parameter or something but if
318:52
Speaker A
there is we continue along with the program perfect so if I might simplify we can try to execute this line of code except if there's an error we'll deal with it in some other way now ideally and once I'm a strong enough programmer
319:05
Speaker A
I would have anticipated this and written the following code from the get go but when you're learning it's certainly reasonable to see an error oh I didn't realize I should detect that and then go back and improve your code
319:15
Speaker A
but of course if you read the documentation you ingrain some of the Lessons Learned From the Past you'll get into the habit of trying and checking for some of these exceptions yourself so let me solve this in one possible way as
319:26
Speaker A
you proposed here let's try to handle this exception as follows let me go ahead now and instead of just blindly calling this print line let me try to print out hello my name is such and such except if there is an issue
319:39
Speaker A
specifically an index error then what do I want to go ahead and do I'm going to say something like two few arguments I could be more explanatory than that but for now I'm just going to explain to the
319:50
Speaker A
user that they gave me too few arguments too few words at the prompt so now it's still not going to work in quite the way I want I'm still not going to be able to generate their name tag but at least
320:00
Speaker A
they're not going to see some cryptic error message and think that they themselves broke the program let me go ahead now and run python of.pi enter and too few ARG ments okay let me go ahead now and do python of name. and type in
320:13
Speaker A
my name David and now we're back in business and I see that my name is on the screen too but strictly speaking I don't have to try to do this I could actually be a little more defensive in
320:25
Speaker A
writing this code and maybe I could check whether or not the user has indeed provided a name or multiple names at the prompt so as to give them more refined error messages as well so how might I do
320:38
Speaker A
this well let me go and and undo the exception handling I've added and why don't I instead more modestly try to do this let me go ahead and introduce a conditional here if the length of cy.
320:50
Speaker A
argv is less than two or equivalently equal to just one value but I'll just stick with less than two for now then go ahead and print out two few arguments so I want ultimately two arguments I want the name of the program at location zero
321:07
Speaker A
and I want the name of the human at location one so that's a total of two arguments so if I have fewer than two arguments let's tell the user with this print line L if the length of cy. RGV is
321:18
Speaker A
say greater than two like they typed in too many words at the prompt well let's tell them print quote unquote too many arguments else if they did get it right and they gave me exactly two arguments else let's go ahead and print what I
321:32
Speaker A
actually care about all right let me go down to my terminal window here and run python of name. and voila uh oh a completely different type of error this one a syntax error which we've seen in the past now a syntax error recall is
321:45
Speaker A
May aopa like I messed up here and I wrote invalid syntax and so no amount of conditionals or exception handling is really going to catch this one I need to go back and just get my program to work
321:55
Speaker A
because it's not running at all well let me go up here and see line four is the issue and indeed it looks like I have an unterminated string here I need to go ahead and now add this double quote so
322:08
Speaker A
let me go ahead now when with that red herring gone let me rerun python of name. piy and hit enter and now we see too few arguments okay maybe it wants my full name let me go ahead now and run
322:18
Speaker A
python of name. py David maen typing in both words after the name of the file and hit enter and now of course it's too many arguments fine now I'll oblige and do python of name. py and just David and
322:30
Speaker A
there we have it my name tag printed on the screen so strictly speaking we don't have to handle exceptions if we can be a little smarter about it and just check for the things that we're worried about especially if we want to give the user
322:42
Speaker A
more refined advice we don't want to just tell them no something went wrong or we don't want to pass we want to tell them no that's too few or no that's too many we have conditionals in our vocabulary already via which we can now
322:55
Speaker A
Express that well let me pause here and see if there's any questions now on how we handled the error before with the index error or how now we're just proactively avoiding all index errors Al together by just checking first first is
323:09
Speaker A
it too few is it tooo many or is it exactly what we want hi thank you um so I was wondering you you touched upon kind of using your full name um could we could we then um is there a way going
323:24
Speaker A
forwards that perhaps we uh have people that want their full names and want their just their first name that we separate that into like oh this person has full name this person has just the one name absolutely and allow me to is uh
323:39
Speaker A
allow me to propose we come back to that support for multiple names um but indeed we could do that and I should note too though we can support full names right now if I do this instead of typing in
323:50
Speaker A
David space mailin which is problematic because again by definition of how argv Works each word ends up in a specific location in the list but if I add quotes single quotes or double quotes at the command line now python will view this
324:05
Speaker A
as two total things the name of the file and this full name name and now when I hit enter I don't see the quotes the whole thing is passed in as my full name and if I want to adapt this further for
324:15
Speaker A
multiple people we'll be able to do that as well other questions now on this version with if L if else or on accept before hi I want to I want to ask you uh can we use multiple else statements can
324:29
Speaker A
you use multiple El's statements no else is the last catchall statement that you can have you can have multiple L if statements in the middle but not multiple elses all right all right well let's turn our attention back now to this code
324:46
Speaker A
and see if we can't refine it a bit more by adding in some additional functionality that we get with modules like the CIS module one of the things I don't love about this version of the code even though arguably it is now
324:57
Speaker A
correct is that the essence of my program which is just to print out the name tag is kind of relegated to this else clause and that's fine logically it's correct but generally speaking there's something nice about keeping all
325:11
Speaker A
of your error handling separate from the code that you really care about having all of these ifs L ifs perhaps at the top of your code that are checking to make sure that all of the data is as
325:22
Speaker A
expected but then it would be nice if only for design sake not to sort of hide in this El statement the actual code that you care about I would prefer for instance to do something logically like this I could check for errors up top and
325:37
Speaker A
then down here print the name tags it would be nice if those are sort of distinct blocks of code all of which are here left aligned but there's a problem with what I've just done here logically what bug did I just introduce by getting
325:52
Speaker A
rid of the Els and introducing line 10 on its own with no indentation outside of the conditional what bug have I just introduced what mistake to be clear um name error ironically it's a name error but not a name error
326:10
Speaker A
exception it's an error with my name but I think you're Frozen for me it's going to raise an exception because even though I'm checking the length of cis.org V up top and even though I'm checking it again for being greater than
326:24
Speaker A
two not just less than two but greater I'm still then blindly and incorrectly assuming it's now going to exist so just to be clear if I run python of name. and I don't type any arguments I've got too
326:36
Speaker A
few I think I'm going to see that I have have too few but I'm also going to see that same exception at the very top of my terminal Windows output there's my error message to few arguments but again
326:47
Speaker A
on line 10 I blindly proceed to still index into my list at location one which does not exist so it turns out there's a better way to handle errors like this especially if you're writing a program in Python that's just meant to run
327:01
Speaker A
briefly and then exit anyway but maybe we could start to exit prematurely if the program itself just can't proceed if the user has not given us the data we want perhaps we should just exit the program earlier than we might otherwise
327:15
Speaker A
so let me go ahead and do this let me go ahead and remove my comments so as to focus only on the code here and let me propose that instead of just printing quote unquote twoo few arguments I'm
327:27
Speaker A
going to use one other function that comes with the CIS module I'm going to go ahead and call cy. exit and as the name suggests it's going to do exactly that with the system's help it's going to exit my program then and there on
327:41
Speaker A
line 4 why is that okay well if you gave me too few arguments I have nothing more to say to you the user I might as well exit a bit prematurely and I can do this as well on line six let's go ahead and
327:51
Speaker A
not just print that but sis. exit quote unquote too many arguments print out that message and just exit right there now I can trust that by the time I get to line eight every error condition has been checked for and so it's safe for me
328:06
Speaker A
to assume that there is in fact and a item at location one in cy. argv so let me go ahead now and run this python of name. py enter too few arguments but I'm back at my prompt nothing more has
328:21
Speaker A
happened let me run it again python of.pie David maen with no quotes enter too many arguments is now printed here finally python of name. py just David enter hello my name is David so we have then insist two forms of functionality
328:37
Speaker A
now we have access to this variable sis. arv this argument Vector that gives me all of the words that were typed at the prompt including the program's own file name and it turns out if we read further in the documentation there's an exit
328:49
Speaker A
function that can take different types of inputs but if I pass it a string like this it will indeed print that string for me and then exit from my program then and there questions now on exiting from programs like this to be clear all
329:05
Speaker A
of this time once python gets to the bottom of your file it's going exit anyway so I'm using cy. exit now just to make sure that I exit earlier than otherwise um my question is about the cis.org arv so is that capable of accepting or
329:22
Speaker A
taking multiple elements at once let's say for example uh python name thatp David Malon I'm a male uh 20 years old and if let's say I only want to access your name which is at the first index and then your your your age is pro say
329:43
Speaker A
at the sixth index can I say sis. RV one and another one for six to access what I just want is that possible for CIS RB uh short answer yes I think if I understand your question correctly whereby you're
330:00
Speaker A
proposing to have many words at the end of the command and you want to access those individual words absolutely at some point it gets a little fragile I would say if you're typing so many words at the prompt that the order really
330:13
Speaker A
matters and so it turns out there's a lot of programs and there's functionality in Python that can allow you to provide those values like name or age or any number of other fields in any order you want but pass in a bit more
330:27
Speaker A
information textually that tells the program how you want to use it so in short what you're describing is possible and let me do a small incarnation of it as follows let me propose that we go back to my code here and let's propose
330:41
Speaker A
that we actually now want to support multiple values at the prompt so there's going to be no such thing as too many arguments suppose that I want to generate name tags not just for David but for David for Carter for Rong Shin
330:52
Speaker A
for others in the group who all want their name tags as well so I'm going to go ahead and do this I'm going to get rid of my L if condition because I don't want to limit the maximum number of
331:01
Speaker A
words that are typed at the prompt anymore I instead want to iterate over every name at the prompt so I'm going to say this for Argin sis. argv go ahead and print out this time ARG so what am I
331:18
Speaker A
doing here well even though the syntax is a little different the idea is the same as before when we've had Loops I'm using a for Loop to iterate over a list the list in question here is cy. argv
331:30
Speaker A
ARG is a variable that I'm creating on the Fly the for Loop is going to make sure that the first time through this Loop AR is set to the first word on the command line the second time through the
331:40
Speaker A
loop Python's going to make sure that ARG is now set to the second thing on the command line and so forth that's just how a for Loop works it updates the variable for us I don't have to call it
331:48
Speaker A
ARG I could call it name so long as I change it to name in both places but ARG is reasonable if I'm iterating over arguments more generally if I now run this program though unfortunately there's a little bit of a bug even if I
332:02
Speaker A
type in David and Carter and wrong Shin I'm not going to get just just three name tags in your mind does anyone see the bug I'm about to trip over it's not a huge deal if I've got enough name tags
332:18
Speaker A
to go around but I'm going to be wasting one because this is going to print not three but four name tags whereby the first contains the name of the program itself maybe not a big deal maybe that's the sticker we don't bother handing out
332:31
Speaker A
but it's wasteful and it it does look wrong so how could we get access to not all four elements of argv but just a a slice of Arvy and this is actually a technical term in Python and some other
332:43
Speaker A
languages to take a slice of a list means to take a subset of it maybe from the beginning maybe the middle maybe the end but a slice is a subset of a data structure like a list well how do I
332:55
Speaker A
actually do this in code well in Python it's actually very easy to take a slice of a list that is a subset thereof you can simply do this at the end of the list name cy. Arvy in this case you can
333:06
Speaker A
use square brackets and then in those square brackets you can specify the start and the end of the list that you want to retain I want to start at element one not zero I want to start at element one and I want to just go to the
333:21
Speaker A
end so I'm actually going to Omit a second number altogether it's not necessary to have a second number but I do need that colon because this is going to give me a slice of the list it's going to give me a slice of the list
333:32
Speaker A
that starts at location one not zero and the colon and then a blank just means it's going to give me everything else so this is equivalently going to slice off the first element of the list and give me a new list that contains just those
333:44
Speaker A
three human names not the name of the file itself let me try running this again I'm going to run python of name.
333:51
Speaker A
py David Carter wrong Shin this time hopefully I'm going to get three and only three name tags hitting enter and indeed I've done now just this so again using some relatively simple syntax in Python we can use square brackets not
334:05
Speaker A
just to go to specific elements like bracket zero or or bracket one we can also get subsets of the list slices of the list by doing bracket something colon Something where each of those somethings is a number the beginning or
334:18
Speaker A
the end and they're optional depending on whether you want all of them or just some any questions now on this version which adds the loop and these slices with that new syntax can we slice starting from the end of the argument argument Vector you
334:36
Speaker A
can you can slice something from the end of the argument vector and this might uh this might blow one's mind a little bit let me go ahead and do this uh let's see let me go ahead and do negative one at
334:48
Speaker A
the end using a negative number here and running the same command we've just uninvited wrong Shin from receiving a name tag here so if you use a negative number it has the effect of counting to the uh in the other direction from the
335:01
Speaker A
end of the list a good question there other questions now on slices on looping over cis.org V hi uh so I remember very early on uh when we were talking about uh only having two decimal places in uh in an um
335:16
Speaker A
float value um does this is is that in the same vein like um because we use the the colon 2f uh so that's is that the same thing then uh why would the F be included then in the point 2f as opposed to here when
335:35
Speaker A
you just have the numbers a really good question and it's just the short answer is that context matters so there's only so many keyo keys on our keyboard and so we sometimes use the same symbols for different things so what you're alluding to is the
335:50
Speaker A
format code in in F string for actually formatting a number using a colon using a period using a number using the letter F and so forth and that is very specific to the F string feature of python this
336:03
Speaker A
case has nothing to do with any of that syntax per se this is just using a colon in a different context to solve this problem to implement a slice the authors of python could have chosen another symbol but honestly looking down at my
336:15
Speaker A
keyboard here we don't have that many to choose from that are easy to type so sometimes they have different meanings a good question as well allow me to propose now that we take things further and move away from using only those
336:27
Speaker A
modules those libraries that python comes with to talk about more generally packages that exist one of the reasons that python is so popular and Powerful these days is that there's a lot of third-party libraries out there as well
336:40
Speaker A
otherwise known as packages strictly speaking python itself has a term of art called a package which is a module essentially that's implemented in a folder not just a file but a folder but more generally a package is a
336:56
Speaker A
third-party library that you that I can install on our own Mac or PC or our Cloud Server and gain access to even more functionality that other people have implemented for us now one of the locations you can get all of these
337:10
Speaker A
packages is called the pii uh website the python package index which lives at this URL here and this is a website that is searchable via the command line as well as via the web that allows you to download and install all sorts of
337:24
Speaker A
packages even cs50 has some of its own packages um in services like these now there's a fun one out there that's a throwback to a command that's been around for years in command line environments called cow c is a package
337:37
Speaker A
in Python that allows you to have a cow say something on your screen if curious to read up on it its own documentation is on p.org specifically at this URL here but how do you actually get the package into your system well
337:52
Speaker A
technically you could figure out how to download the file and maybe unzip it and put it into the right location on your Mac or PC but nowadays a lot of languages python among them has what's called its own package manager this one
338:04
Speaker A
here called pip which is just one so pip is a program that generally comes with python itself nowadays that allows you to install packages onto your own Macs or PCS or Cloud environment by just running a command and then voila you have access
338:19
Speaker A
to a whole new library in Python that didn't come with python itself but now it's available on your system for you let's go back to vs code here and in my terminal window I'm going to go ahead and type pip install cow now what's
338:34
Speaker A
going on here pip is the command the package manager and I want to install what package the package called cow I'm going to go ahead and hit enter here and after a little bit of output it has successfully installed C now what does
338:47
Speaker A
that mean that means I can now go about importing this into my own code well let's go ahead and see what this means let me go ahead and create a new file with code called say dopy because I want
338:57
Speaker A
something to be said on the screen and in my new tab here I'm going to go ahead and import C which presumably is now installed I'm now going to import CIS as well because I'd like to use some
339:08
Speaker A
command line arguments in this program just so that I can run it quickly and without using the input function I can get the user's name immediately from The Prompt and let me go ahead and do this I'm going to do a bit of error checking
339:20
Speaker A
proactively this time and rather than use less than or greater than I'm this time going to say if the length of cis.org V does uh does equal two so if the human is provided just the name of the program and their own first name
339:33
Speaker A
we're good to go I'm going to do the following I'm going to call a function called cow in the package called coway and I'm going to pass in a string hello comma and then as in the past I'm going
339:48
Speaker A
to pass in just one string because according to its documentation it's not like print I can't pass in comma this comma that I can only pass in one string so I'm going to concatenate the contents of sis. argv bracket1 so long as then I
340:02
Speaker A
type in my name David after the name of this program it should end up in cy.
340:07
Speaker A
arv1 one in which case this line five of code should concatenate hello with my name with a space in between and apparently a cow is going to say it so let's see what happens here let me go ahead and clear my screen and increase
340:20
Speaker A
the size of my terminal window let me go ahead and run python of say. py and type my name David and enter there is the program called coway it literally has a cow say something on the screen and this
340:33
Speaker A
is a throwback to a program from yester year that tended to come with a lot of syst sys um this is otherwise known as asky art it's a textual way using just keys on your keyboard to print pictures
340:45
Speaker A
of sorts on the screen now we can really go down the rabbit hole here and there's questionable academic value of doing so so I'll do so just once turns out the coway package comes with other functions as well one of those functions for
340:57
Speaker A
instance is T-Rex and if I now increase the size of my terminal window we'll perhaps see where we're going with this let me now run again python of.pi this time let me not provide my name just to see if it's broken it's still okay
341:10
Speaker A
because we have that if condition if the length of cy. RGV equals equals two and only if it equals equals 2 do we do anything that's why we're not seeing anything here let me go ahead and cooperate now say. piy space David and
341:24
Speaker A
it's no longer a cow but if I zoom out on my screen a T-Rex why just because these are the things you can do once you know how to program you can even package them up and make them freely available
341:36
Speaker A
to others as open source software for us it's demonstrative of a feature more generally here namely being able to install these thirdparty packages and how you might do so in Python now I'll leave this up on the screen for a moment
341:49
Speaker A
and see if there's any questions about cows or Tyrannosaurus Rexes or packages more generally I'm really qualified to speak to just one of those hi um I've got two questions it's a bit earlier than what it's supposed to
342:05
Speaker A
be um so the first question is the the packages that you calling um U to uh use in the program are they the same as um let's say because I'm doing Java um the same as calling a class of a
342:27
Speaker A
Java file in order to use its functions and my second question is what's the actual purpose of using command arguments as you used because it's not really the best way to uh as you say be user friendly where
342:48
Speaker A
as in let's say the person who's using the program doesn't know what it what they want what the the program's asking them really good questions the first question about the comparison with Java python packages are similar to Java
343:04
Speaker A
packages where you have something do something do something at the top of your program that gives you access to a class or something else python itself supports classes more on those down the road and you can do very similar things
343:15
Speaker A
in python as you can do with Java but the analog really is python packages to Java packages here as for command line arguments you ask a good question why do we use them especially if they're a little less user friendly they're a
343:28
Speaker A
little less user friendly to people who aren't in this Zoom to be honest you and I as we learn more and more about programming and more about command line arguments I dare say will become more comfortable with and tend to prefer the
343:41
Speaker A
ability to customize commands using these commandline arguments why productivity it tends to make you faster because you get into the habit of knowing exactly how you can configure your software without having to manually answer questions and case in point all
343:54
Speaker A
of this time uh have we been running python of something. py you could imagine not doing that you could imagine typing only python hitting enter and then you're prompted for the name of the file you want to run so you type in
344:07
Speaker A
something piie and then it runs not a big deal but I I would argue that over time you're going to get a little tired of that tedium and you would much prefer to just automate the command again and
344:16
Speaker A
again and again especially with little conveniences like being able to hit up and down in your keyboard history so as to rerun those same commands automation is Big too if you emerge from a class like this and start using python to
344:29
Speaker A
automate processes at work or for personal projects or the like the ability to specify all of your inputs on the one line just means you can get work done more quickly so so hands down absolutely using commandline arguments
344:40
Speaker A
is a more Arcane uh feature of systems that most of us are no longer as familiar with because of Windows and Mac OS and other operating systems that have buttons and goys and menus but the more comfortable get you get with programming
344:53
Speaker A
I dare say the more you will tend to prefer these capabilities because they allow you to do things more quickly with that said allow me to propose that we take a turn toward yet another package that's particularly popular and just as
345:09
Speaker A
easy to install all toward an end of using apis now apis are not something that's python specific more generally an API is an application programming interface and it can refer to python files and functions but often apis really refer to third-party services
345:26
Speaker A
that you and I can write code that talk to many apis but not all live on the internet these days so that so long as you have a browser or so long as you have some experience with Python
345:37
Speaker A
Programming or programming in any language you can write code that in effect pretends to be a browser connects to that thirdparty API on a server and download some data that you can then incorporate into your own program now
345:51
Speaker A
how do you do this well python has a very popular package that you can install via pip called requests the requests Library allows you to make web requests internet requests using python code essentially as though you were a
346:07
Speaker A
browser yourself you can automate therefore the retrieval of URLs that start with HTTP or https the documentation for this library is at a URL like this but it too can be installed at the command line and even though it's third party it's one of the
346:20
Speaker A
most popular and commonly used packages out there in Python and this too is one of the reasons again that python is so popular there's just so many solutions to problems that you and I have or are invariably going to have when we write
346:34
Speaker A
projects of our own there's just a really vibrant EOS system a really Vibrant Community of Open Source software that's that easy for us to install let me go back to my terminal window now and run pip install requests
346:46
Speaker A
in order to install this package on my own system and after some lines of output I'll see that it's successfully installed now let's go ahead and create a new file here for instance itunes. it turns out that Apple has its
346:59
Speaker A
own API for their iTunes service the software that provides you with the ability to download and search for music and songs and other information as well and it turns out that let me go back over to my computer here and open up a
347:10
Speaker A
browser like Chrome and let me go ahead and visit this URL here https col itunes.com search question mark entity equals song Ampersand limit equals 1 Ampersand term equals Weezer now I constructed this URL manually by reading the documentation
347:29
Speaker A
for Apple's API application programming interface for iTunes and what they told me is that if I want to search for information about songs in their database I should specify entity equals song so that it's songs and not albums
347:42
Speaker A
or artists or something like that if I just want to get back information on one song I'm going to provide limit equals one and if the band I want to search for the artist is Weezer I should specify
347:52
Speaker A
term equals Weezer so with this if I go ahead and hit enter and visit this URL I actually end up with a text file in my downloads folder on my Mac if I go ahead and open that text file that my browser
348:03
Speaker A
just downloaded we'll see all of this text here which at first glance might look a c bit cryptic but it actually follows a pattern notice this curly brace at the start and notice this closed curly brace at the end notice
348:14
Speaker A
this open square bracket here and notice this closed square bracket here and in between those pieces of syntax are a whole bunch of strings and values in fact a whole bunch of key value pairs what we're looking at here is a standard
348:27
Speaker A
text format known as Json JavaScript object notation which yes is technically related to yet another programming language called JavaScript but Json itself is typ typically used nowadays as a language agnostic format for exchanging data between computers by language agnostic I mean you don't have
348:45
Speaker A
to use JavaScript you can use python or any other language to read Json or write it as well and it's a completely text-based format which means that if I visit that URL with my browser what gets downloaded is just a bunch of text but
348:58
Speaker A
that text is formatted in a standard way using curly braces and square brackets using quotes and some colons that ultimately contain contains all of the information in Apple's database on Weezer song at least the first one CU I
349:12
Speaker A
limited it to one in their database and that's an API an application programming interface a mechanism whereby I can access data on someone else's server and somehow integrate it into my own program now of course my browser Chrome is not
349:27
Speaker A
something I wrote I should actually write some python code that perhaps pretends to be a browser to grab the same data so let's do that let me go back to vs code here and let me write a program with code itunes. and we're
349:39
Speaker A
going to write some code via which I can then use the iTunes API and in turn python to get information about any band that I might want I'm going to go here and import first the requests Library which I installed earlier in order to
349:54
Speaker A
make those HTTP requests I'm going to go ahead and import the CIS Library via which I'll have the ability to use command line arguments like specification of the band that I want to search for if not Weezer and then down
350:07
Speaker A
here I'm going to go ahead and insert some error checking to say if the length of cy. argv does not equal to so if the user does not provide me with the name of the file they want to run and the
350:20
Speaker A
name of a band and that's it you know what let's just go ahead and exit for now I could provide a more explanatory message but for now I'm going to keep things simple and just exit the program prematurely so that I can trust
350:31
Speaker A
Hereafter that cy. arv has what I want and now I have the opportunity to use the requests library to write some python code that effectively is pretending to be a web browser so as to connect to that same https URL on
350:47
Speaker A
Apple's own server so now that I've guaranteed that the user has typed in not just the name of the file but also the name of a band at the prompt giving me a length of two for cis.org V let's
350:58
Speaker A
go ahead and execute requests.get which is a function inside of the requests package that will literally get some response from a server and the URL that I want to get is the exactly the same as before https itunes.com search question mark
351:15
Speaker A
entity equals song Ampersand limit equals 1 Ampersand term equals previously Weezer but let's make this program a little interactive and actually allow the human to specify at the command line what artists they'd like to search for so I'm going to go
351:30
Speaker A
ahead and close my quote early and just append using the concatenation operator as in the past sis. Arvy bracket1 and now it'd actually be nice to store the response from the server in a variable so I'm going to go
351:45
Speaker A
ahead and say response equals and to store all of the response that comes back from the server in a variable called response down here now I'd like to just understand what the server is returning to me to make sure I know how
351:57
Speaker A
next to proceed so this isn't going to be very pretty yet but I'm going to go ahead and print out response. Json which ensures that the data I'm getting back is formatted on my screen as is exactly that Json the same text format as we saw
352:10
Speaker A
on my screen it's not a useful program yet I'm really just learning along the way but let me go ahead now and increase the size of my terminal window and run python of itunes. and type in the name
352:21
Speaker A
of a band like Weezer and hit enter and what we see on the screen formatted almost the same as before is exactly that same text but what you'll see here is that this has been standardized now as a python dictionary what indeed
352:37
Speaker A
Apple's returning is technically adjacent response JavaScript object notation but python the request library is converting it to a python dictionary which happens to use wonderfully coincidentally almost the same syntax it uses curly braces to represent the dictionary here and a closed curly brace
352:55
Speaker A
to represent the end of it here for any lists therein it uses a square bracket here and a closed square bracket down here it uses quotes single quotes in this case or equivalently double quotes to represent the keys in that dictionary
353:09
Speaker A
and after a colon it stores the value of that key and so you'll see that indeed we have a result count key whose value is one but then a more interesting result key called results whose value is this entire list of data now honestly
353:25
Speaker A
this is such a big blob of text that it's going to take me forever to wrap my mind around what I'm seeing so let me propose temporarily we use another library in Python that will allow me to format my data a little little more
353:37
Speaker A
cleanly it turns out that python also comes with a special Library uh called Json that allows you to manipulate Json data and even just printy print it that is format it in a way that's going to be way easier for you and I to understand
353:50
Speaker A
so let me go back to my code here let me shrink my terminal window and let me propose that just temporarily again we do this let me import this additional Library Json which comes with python so I don't need to install it manually with
354:04
Speaker A
Pip and let me go ahead now and not just print out response. Json which was that Big Blob of hard to understand text let me go ahead and use one other function here called json. dumps for dump string
354:18
Speaker A
and pass to that function that response. Json return value so again I'm just introducing another function who I claim it has a purpose in life of pretty printing nicely formatting on the screen the exact same information and I know
354:32
Speaker A
this from the documentation having done this before but I'd like things to be nicely into Ed and according to the documentation if I pass in a named parameter of indent equals 2 that's going to indent everything at least two
354:44
Speaker A
spaces I could do four or something else but it's going to be enough to help me wrap my mind around what the data is I'm getting back because again I'm just learning along with you so let me increase the size of my terminal window
354:56
Speaker A
again let me run python of itunes. and again let's search for Weezer and hit enter and now notice it's still a little bit cryptic because there's a lot going on here but my gosh I can totally read this more easily now notice now that I
355:11
Speaker A
still see the first curly brace which means hey this is a dictionary in Python a collection of keys and values the first key is called result count it happens to be displayed in double quotes now but that's just an issue of
355:22
Speaker A
formatting it could be double or single so long as we're consistent the value of that key is one why well I told the URL to only limit the responses to one Weezer song so I've gotten a result set
355:33
Speaker A
of one if I increase that limit I could probably get more then the interesting part of this response is really the data itself notice in the res results key here there's a really big value the value is a python list as
355:49
Speaker A
implied by this square bracket what does this list contain well I know from skimming it earlier that this contains one dictionary and that's why we see another curly brace here so again if this gets a little more complicated keep
356:04
Speaker A
in mind that a dictionary is just a collection of key value Pairs and python uses curly braces to indicate as much it is perfectly reasonable for a dictionary to be inside of another dictionary if the value of some key itself is another
356:20
Speaker A
dictionary so this is a common Paradigm and even though it might seem a bit cryptic it's just something that allows us to associate more keys with more values now most of this information I probably don't care about for instance
356:31
Speaker A
according to Apple the unique identifier for Weezer is apparently 115,000 234 that might be useful if I'm making my own database and I want this to be searchable but for today's purposes all I care about is the name of the track
356:45
Speaker A
otherwise called track name as key and the first song and only song because we limited it to one that we got back from iTunes here is the song that you might know by Weezer called Say It Ain't So so
356:58
Speaker A
now I have a bit of a clue if my goal here is to implement a program called itunes. that doesn't just dump the response from the which is admittedly very cryptic but to print out all of the songs that iTunes has for the band
357:12
Speaker A
called Weezer maybe I can iterate over this somehow so let me backtrack here's the key called track name it is inside of a dictionary that is the value of results here so how can I go about getting this well let me go ahead and
357:28
Speaker A
try this let me go ahead and Shrink my terminal window back down and let me propose now for one final flourish we don't just lazily print out the contents of that response because that's not interesting or pretty for anyone let's
357:41
Speaker A
do this let me go ahead and create a new variable just for the sake of discussion called o for object and I'm going to go ahead and call uh o equals response.
357:51
Speaker A
Json just to store that Json response specifically in a variable called o but I could name it anything I want and now I'm going to do this for each result in that object's key called result go ahead and print out that results
358:10
Speaker A
track name and notice I have used exactly the same capitalization track name has a capital N results is all lowercase and let me rewind before we run the actual program in line eight we are making an HTTP request using python
358:24
Speaker A
to the server just like you and I as humans type URLs into a browser and hit enter this is the python equivalent there of I am then on line 10 just grabbing from that variable that contains the server's respon
358:37
Speaker A
the Json object that I care about the thing between those curly braces at the very top and the bottom but because we've poked around and because I read the documentation earlier I know that that object has a key called results and
358:52
Speaker A
that results key again is a list now at the moment that list contains only one song Say It Ain't So because I limited my response to one but even so my Loop will work it's just going to iterate
359:02
Speaker A
once and each time through that loop it's going to print the current results track name if I want to make this even more interesting let me change this limit now from one to 50 so I'll at least get back 50 track names instead
359:15
Speaker A
let me go ahead now and increase the size of my terminal once more and go ahead now and run python of itunes.
359:21
Speaker A
searching again for a band like Weezer and here we go and voila there are 50 songs that iTunes has for Weezer and if we scroll back up to the top here we'll see that the very first one there is
359:35
Speaker A
indeed say it ain't so but now we got undone The Sweater Song Buddy Holly apparently another rendition of Say It Ain't So perhaps from another album another Buddy Holly undone my name is Jonas and so forth questions now on this
359:49
Speaker A
program which integrates python with a real world third party API yeah hi uh can we use breake instead of system. exit exit good question but no um break again is used to break out of things like Loops like we saw ear
360:06
Speaker A
clear cy. exit is used to break out of the whole program itself use break for Loops for now and use cy. exit to terminate the whole program good question other questions now on this program are others from where we bring
360:20
Speaker A
the name of the key results from where do we get the name of the key uh results itself yeah can we change the results name you cannot so we could in our program so the keys that come back in
360:32
Speaker A
that Json response to be clear come from itunes. apple.com some engineer some team of Engineers decided for us what all of those keys would be called including track name results result count and everything else you and I can
360:46
Speaker A
absolutely store those same values in variables just like I'm doing here with o just like I'm doing here with result you can rename those keys anything you want using python variables but the Json response is coming from that thirdparty
360:59
Speaker A
server other questions yes sir sir uh I have a question related to to C package so like uh yes so sir what sort of ask Graphics is it capable of outputting the coway package um I would refer you to
361:17
Speaker A
the URL in the slides earlier uh if only because it's more thorough they have not just cows but Tyrannosaurus Rexes and several other animals as well I should emphasize that this is not a package I suspect you will use much in the real
361:29
Speaker A
world it's really just meant to be representative of the types of packages you can install but allow me to refer to the documentation for what more is there but aski artart uh is the all we had before there were emojis let alone gifs
361:41
Speaker A
and jpegs and pings but it's what's is immortalized in C well allow me to transition us back now to one final capability of python which is that you yourselves have the ability to make your own libraries up until now we've been
361:58
Speaker A
writing all of our functions in our one file hello pi and everything since and now that we've introduced modules in Python like random and statistics we can import those that come with python but that's other people's code as well and
362:12
Speaker A
we've now used Pip this package manager to install third- party packages as well in the system and using other people's code still but to come full circle what if you yourself find yourself implementing the same kinds of functions
362:25
Speaker A
again and again or you find yourself opening up old programs copying and pasting code you wrote into new programs because you have the same problem yet again a good practice would be to somehow bundle up that code you keep
362:37
Speaker A
reusing and make your own python module or package you can keep it local on your own Mac or PC or Cloud Server or you can go through the steps of actually bundling it up making it free and open
362:49
Speaker A
source and putting it on something like pii for others to use as well okay I'm going to go ahead and run code of sayings. py to create a brand new file called sayings dopy which is going to be
362:59
Speaker A
my own sayings module and I'm going to define a couple of simple functions in there I'm going to define a hello function that's going to take name parameter is input and that function is simply going to print out an F string
363:11
Speaker A
that contains hello comma and then in curly BRAC whatever that person's name actually is then I'm going to go ahead and Define one other function a goodbye function that has def goodby also takes a name as its input and then that prints
363:25
Speaker A
out by contrast an F string that says goodbye comma and then in curly brace's name and now just for good measure just so I can be sure that these functions are working as expected I'm going to go ahead and Define a main function in here
363:38
Speaker A
too just for the purposes of testing and I'm going to go ahead and Define a main function that simply does a couple of tests for instance it calls uh hello of quote unquote worlds shall we say and then it's going to call goodbye of quote
363:53
Speaker A
unquote world as well and hopefully what I'll see on the screen then is hello world and goodbye world when I run this program of course as always I need to explicitly tell python to call that function so I'm going to call Main at
364:04
Speaker A
the very bottom of this file all right all right let's try it out python of sayings. py enter and indeed I see Hello World and goodbye world and so I think it's reasonable for me to assume that these functions albeit simple are pretty
364:17
Speaker A
correct at this point but now suppose that I want to use these functions as though I've indeed created my own Library my own python module that makes available a hello function for me or anyone else who wants to use it or a
364:29
Speaker A
goodbye function as well well let me go ahead and open up again say. py but start fresh and rather than have the C say anything let me go ahead and have my own Library do the talking so I'm going
364:41
Speaker A
to go ahead and as before import CIS so that I have access to command line arguments and from my own module called sayings I'm going to import hello so because I created a file called sayings.
364:53
Speaker A
py I can say from sayings and it's inferred by python that I mean sayings.
364:58
Speaker A
py at least in this current directory but I specifically going to import just one of the functions for now namely hello and now I can do something like this if the user obliges by giving me two command line arguments which I can
365:10
Speaker A
check by just checking the length of cy. argv I'm going to then go ahead and call this new hello function passing as its input assist. arv bracket one which should hopefully be the person's name which I'm going to expect them to type
365:23
Speaker A
at the prompt so here we go I'm going to go down to my terminal window run python of s.p and my own name because I want my own name to end up in the command line arguments and therefore be part of the
365:34
Speaker A
hello so when I hit enter and just a moment I should hopefully see hello comma David so here we go enter and huh I see Hello World Goodbye World and then I see hello David so why is this
365:49
Speaker A
happening well it turns out even though I've done everything according to our own past practice it's not really the right way to go about calling Maine after all if I'm blindly calling Maine here at the bottom of my file that means
366:03
Speaker A
whenever this file is loaded by python Maine is going to get called and unfortunately that's true even if I'm importing this file or just a function from this file as I am here in my s.p program this is to say on line three
366:16
Speaker A
here when I say from sayings import hello this effectively tells python to go find that module sayings. py read it from top to bottom left to right and then import specifically the hello function unfortunately by the time python has read the file from top to
366:30
Speaker A
bottom left to right that last line of code recall is to call Maine Maine gets called no matter what so really the right way to go about using a main function which does solve that problem of ensuring that we can order our
366:44
Speaker A
functions however we want and all the functions will be defined at the time they're invoked I shouldn't be unconditionally calling main at the bottom of this or really any of my programs I should instead use this technique I should say if underscore
366:57
Speaker A
underscore name underscore underscore equals equals quote unquote underscore uncore maincore uncore close quote then and only then should you actually call Main well it turns out that this variable is a special symbol in Python underscore uncore name underscore
367:15
Speaker A
underscore and notice that vs code because of its font isn't quite showing those two underscores but they're indeed there to the left and the right this is a special variable whose value is automatically set by python to be quote
367:26
Speaker A
unquote main when you run a file from the command line as by running python of sayings. piy so Watch What Happens now with this additional conditional in sayings. py if I run python of sayings.
367:40
Speaker A
py it still works as before because name will be automatically set to underscore uncore maincore uncore when I run this file using python ofs sayings. py but notice this name is not going to be set to quote unquote main it's going to be
367:58
Speaker A
set to something else technically the name of the module when I instead import the file like I do here so this highlighted of code even though it will cause python to go find sayings. py read it from top to bottom left to right it's
368:11
Speaker A
going to ignore the call to main this time because it's wrapped in that conditional in this case when I'm importing a file and not running it directly at the command line Maine will not get called by definition of name's
368:23
Speaker A
value so let me go ahead and try this instead of running python of sayings. py which is the module which contains that conditional main let me go ahead here and run python of say. py which is the program here before me that Imports
368:38
Speaker A
hello from sayings but because of that conditional it's not going to say hello to anyone else except me in this case all right we're here at the end of our week it's only appropriate I think to import something other than hello why
368:51
Speaker A
don't I go ahead and import not hello but goodbye from here let me go ahead and call goodbye instead of hello and this time when I run python of sayy I'm not going to type my own name allow me
369:02
Speaker A
if I may to type in the whole world so that our final sentiment today is goodbye World indeed that's it for this week we will see you next time [Music] [Music] all right this is cs50's Introduction to programming with python my name is David
369:43
Speaker A
men and this is our week on unit tests up until now we've been writing a lot of code and you might have been testing your code by running your program and passing in some sample inputs and running it again and passing in some
369:54
Speaker A
sample inputs or you might have been waiting for us to test your code instead but it's actually much better practice to get into the Habit sooner rather than later of testing your own code using Code of your own in fact whether you're
370:06
Speaker A
writing a personal project or working in industry it's very common nowadays to not only write code to solve the problems that you want to solve but also to write a little extra code to test the code that you wrote and that's what
370:17
Speaker A
we're going to focus on today writing our own test so as to be all the more confident all the more certain that the problems we have been trying to solve are in fact solved correctly so let's rewind a few weeks now to a program we
370:30
Speaker A
wrote a while back namely to to calculate uh numbers and specifically we left off with this calculator on trying to compute the power of a number like X squar or uh where X might be two or three or some other number as well well
370:45
Speaker A
let me go ahead and resurrect that file by going into my terminal window here and running again code of calculator. Pi and let me go ahead and pick up where we left off way back when by defining a
370:57
Speaker A
main function here and then in my main function I did something like this I said x equals int of input and I asked the user what's X question mark and then I immediately went ahead and printed out something like x^2 is and then I passed
371:12
Speaker A
in as a second argument to print the result of calling a function called Square passing in that value X now of course I haven't yet implemented the square function so let's define that as well let me go down a couple of lines
371:25
Speaker A
and Define square and it takes an argument recall a parameter that at the time I called n for number so I'll do that again though I could technically choose any name for this variable and I call did this I returned n * n and there
371:39
Speaker A
were multiple ways to do this the squaring a number is multiplying it by itself so I could also use other syntax here but this is what we ultimately settled on and then recall that I ultimately called Main in order to kick
371:51
Speaker A
off the process of running this program so just as a test manually let me go ahead and run python of calculator. piy and hit enter what's X let's start with two all right x^2 is 4 I think that's
372:03
Speaker A
correct so let's run it again just for good measure of calculator. Pi let's type in three for X this time x^2 is 9 and I think that's correct and I might be feeling pretty good at this point and
372:14
Speaker A
I go off and submit my code to a course or I post it on the internet for others to use but I haven't really methodically tested this code and it's not necessarily the case that it works entirely in fact I haven't really
372:24
Speaker A
considered a number of corner cases I went with some pretty obvious numbers like two and three but what about zero what about negative numbers what about any number of other infinite numbers well we're not going to test infinite
372:36
Speaker A
number of inputs to this because the program would never halt but we should test some representative inputs ultimately but before we do that let's get into the habit of making sure that Maine isn't always called let's adopt this habit again of doing if underscore
372:50
Speaker A
uncore name underscore underscore equals equals quote unquote underscore uncore maincore underscore only then should we execute Main and I'm doing this now proactively because I want to make sure that when I import my Square function perhaps from another library from
373:08
Speaker A
another file treating it as though it's a library I want to make sure that main is not just automatically called itself now what do I want to do from here now that I've modified this program as follows well let's go ahead and write a
373:21
Speaker A
completely different program whose sole purpose in life is to now test this program so I've got my actual calculator in calculator. I've readed myself to call Main conditionally so that I can safely import one or more things from
373:35
Speaker A
this file in another file well what should that other file be well by convention I'm going to create a file that's called test underscore and then because the thing I'm testing is this calculator itself let's call this file
373:46
Speaker A
test calculator. piy that's going to give me a new tab in which I can write a brand new program whose purpose in life is now specifically to test that program but really that program's specific functionality built into that program is
373:59
Speaker A
the square function let's focus on testing that function all right so how do I access that function in this program well recall that I can import a function from another file as though it's a library of my own a so-called
374:11
Speaker A
module so I'm going to do this from calculator import Square I could go ahead and just import Square itself but then I would have to prefix my use of square recall by saying calculator dot everywhere and it's just a little
374:25
Speaker A
cleaner to just import the one function and now let me go ahead and do this let me go ahead and Define a function called test Square this two is a convention if you want to test a function called
374:37
Speaker A
Square your function for testing should be called testore Square or alternatively you could do Square underscore test but I'll adopt this convention here now what kind of tests can we do well I don't dislike the test I ran earlier testing xals 2 and x
374:52
Speaker A
equals 3 but every time I uh want to test my program previously I would have to do that manually and that's going to get tedious it's not going to be easy for someone else to test it and if I'm
375:00
Speaker A
actually working in the real world it would be nice if I could automatically have my program tested again and again by having some automated process run my own code so let's do that and take the human ultimately out of the equation so
375:12
Speaker A
how might I go about testing the square function that I've now imported per line one well in my test Square function why don't I do this if uh the result of calling square of two does not equal four why don't we go ahead and print an
375:26
Speaker A
error message because I know that in the real world 2 squared should equal four so if square of two does not equal four there's a bug in my program there's a bug in my function I've made a mistake
375:37
Speaker A
so let me go ahead and print something like that so I or someone else knows 2^2 was not four for instance so I could print out anything here what should I maybe next test well let's do more than
375:47
Speaker A
one test let's say if the square of three does not equal 3^2 9 then let's go ahead and print out that 3^ SAR was not 9 so I haven't done any more testing than I did earlier but I've baked those
376:01
Speaker A
two tests xal 2 and xal 3 into my own code here so I can now run those tests automatically if you will now it's not enough to just Define a function called test Square I actually if I want to run
376:15
Speaker A
this function need to call it somehow and our convention for doing that is the same as always in this function here in this file two let me Define Main and Main's sole purpose in life is going to be to test square and now at the bottom
376:27
Speaker A
of this file as before let me go ahead and adopt my Convention of if underscore uncore name underscore uncore equals equals quote unquote underscore uncore maincore uncore then go ahead and call Main so a lot of this is just
376:41
Speaker A
boilerplate like we've seen this before defining a main function and calling a function to kick off some process now adding the conditional at the bottom of the file to make sure I'm only conditionally calling main just in case
376:51
Speaker A
I import anything from this file elsewhere so let's see let's go ahead and test my code now let me go ahead and run test calculator with python and hit enter and nothing outputs nothing outputs but I think it's okay I think no
377:07
Speaker A
output is good because look at my test Square function I'm not printing anything if all seems well so let's let's demonstrate as much by going back to my calculator and let me break it let me introduce a bug maybe I didn't even
377:20
Speaker A
get it right the first time maybe my code originally looked like this I wasn't thinking I forgot my squares and so I thought that the square of a number is n plus n instead of n * n so a
377:30
Speaker A
reasonable mistake to make perhaps arithmetically let me now go back to my test calculator which which I'm not going to change but I am going to rerun it python of test calculator. Pi going to cross my fingers here but for not I'm
377:43
Speaker A
going to see immediately that 3^ SAR was not n now what is it well let's see when your tests fail how can we put our finger on what's wrong well it's a little interesting that I completely broke my Square function and yet only
377:57
Speaker A
one of these tests is failing it looks like this test lines 9 and 10 is fine because I'm not seeing that output but of course these two lines this test is failing because 3^ s is not n when I'm
378:10
Speaker A
using plus so just to be clear here why is my function only partially broken just to be clear why am I seeing only one error instead of two even though the square function is now mathematically broken because 2 plus two is four no
378:27
Speaker A
yeah I mean it's as simple as that I just got lucky that 2+ 2 is the same thing as 2 * 2 so this is one of those Corner cases and this is why it's good to be in the habit of not just testing
378:35
Speaker A
one thing but test several and make sure you're covering your bases so to speak so I got lucky here and that explains why I'm seeing only one error even though the function itself is flawed but let me propose that there's another way
378:47
Speaker A
we could do this because honestly if I extrapolate from this simple example running not just two tests but three or four or 10 or 20 tests you can imagine that my God the code is going to get so
379:00
Speaker A
much more complicated than the function itself I mean already look in calculator. the function in question is two lines long and yet in test calculator the fun code in question is five lines long like I've written more code to test my code than I actually
379:14
Speaker A
wrote original code so the fewer lines of code we can write when testing code I think the more likely you and I are to do it because it's going to be literally a little less work and just fewer
379:25
Speaker A
opportunities for mistakes so what's another approach I can take here well it turns out in Python there is another keyword that we haven't yet used which is this here assert assert is a keyword in Python and some other languages as well that allow you
379:39
Speaker A
to do exactly that as in English to assert that something is true to sort of boldly claim that something is true and if it is nothing's going to happen no errors are going to appear on the screen but if you assert something in Python
379:52
Speaker A
and it is not true that is the thing you're insert asserting a Boolean expression is false you're actually going to see some kind of error on the screen so let's go ahead and try this new keyword as follows let me go back to
380:05
Speaker A
my code here and just to make it a little simpler let me propose that I I use this new keyword as follows let me simply assert that the square of two should equal four so I've changed my logic instead of checking for not equals
380:21
Speaker A
I'm now asserting very loudly that it should equal four and then on one additional line let me do the other test assert that the square of 3 equals equals 9 and that's it no if no indented print I'm just going to assert more
380:36
Speaker A
simply these two things that I want to be true well let me go ahead now with calculator. pi still broken I'm still using plus accidentally instead of multiplication let me go ahead now and run python of test calculator. Pi
380:51
Speaker A
crossing my fingers as always but it's not going to go well this time a whole lot of Errors seem to appear on the screen and if I scroll up here for this traceback we'll see that the thing that
381:02
Speaker A
failed was this line here assert Square of three equals equals 9 now unfortunately when you're using the assert keyword it's not terribly userfriendly it shows you the files and the line numbers involved but it does show you the specific line of code that
381:15
Speaker A
failed the assertion that failed so to speak it's now kind of up to you and me to infer from this well wait a minute why is the square of three not equal to 9 so it's not super user friendly but
381:26
Speaker A
honestly it was like half as much code for me to write it's just two lines instead of those previous four but notice this little Remnant down here this was an assertion error and we have seen errors before we've seen errors
381:38
Speaker A
before when we've made other mistakes in our code and in the past what was our solution for catching those errors how do we catch errors that seem to resemble this even though we've not seen this one before um try and accept
381:55
Speaker A
yeah in Python we can use the try and accept keywords to try to do something optimistically except if something goes wrong do something else instead so this is a step forward and that I can at least catch this error but it's going to
382:08
Speaker A
be perhaps a step backward and that I'm going to end up writing I'll admit in advance a little more code uh instead so let me go ahead and try this let me go back into my code here and instead of
382:17
Speaker A
just asserting blindly let me go ahead is to proposed and try to do this first assertion except if there is an assertion error like we saw a moment ago then go ahead and print out something more userfriendly that explains what
382:33
Speaker A
actually failed 2 squar is uh was not four and let me go ahead similarly and try to assert that the square of 3 equals 9 except if there's an assertion error there in which case I'm going to print out more user
382:48
Speaker A
friendly 3^ squar was not n so I've taken a step forward but also a step back because now I have more code but I have at least introduced assertions and exceptions in a manner consistent with how we've seen it in the past when
383:00
Speaker A
something goes wrong you actually see an exception raised well let me go ahead and run this version of the program now instead python of test calculator.
383:09
Speaker A
crossing my fingers all right it still failed because I'm seeing output but we're back to at least userfriendly output so that's at least progress in some way here but it's again more code than might have been ideal and in fact
383:23
Speaker A
if we continue this further what if we actually want to add additional test cases here as well well it seems like we might end up writing way more code than would be ideal for instance I'm testing two and three now I should probably test
383:36
Speaker A
some negative numbers as well so why don't I go ahead and add in for instance let me go ahead and copy and paste this let me try to assert that the square of -2 equals equals 4 which should be the
383:48
Speaker A
case mathematically and if not let me go ahead and change this to say -22 was not four and you know what let me go ahead and copy paste this again test another negative number just for good measure let's test the square ofg -3 which
383:59
Speaker A
should equal 9 but if it doesn't let's go ahead and say that -32 was not 9 and just to think aloud here what might be another good value to test I've tried two I've tried three I've tried ne-2
384:13
Speaker A
I've tried negative3 I can't try in infinite numbers but there's at least something that's a little different in between those values let's try zero zero is an interesting case too just in case something might be wrong and Y zero I'm
384:23
Speaker A
just going with instincts here right odds are positive numbers are generally going to behave the same negative numbers might generally behave the same zero might be a little anomalous there's no uh science to it necessarily but rather considering for yourself
384:36
Speaker A
based on your own experience like what are the potential Corner cases based on the function you're trying to test I'm trying to test something mathematical so I want to test representative values so let me go ahead and paste in one more
384:47
Speaker A
try accept block let's assert that the square of zero should equal zero and if not I'll say something explanatory like 0^ squar was not zero now if I go ahead and run this python of test calculator.
385:01
Speaker A
piy and hit enter now I see multiple errors and and this is interesting it's a bit of a clue because notice that some but not all of these assertions are failing the one for 2^ SAR is apparently okay as we noted earlier recall that 2^
385:17
Speaker A
SAR happens to be 2 plus 2 so that bug doesn't really throw off our test but it's a good thing we tested for three it's a good thing we tested for neg -2 and neg3 because all of those tests
385:26
Speaker A
caught this error the zero test did not notice because 0 squared is of course 0 but 0 + 0 is 0 so we're getting lucky or unlucky there depending on how you you view the glass is half full or half
385:38
Speaker A
empty here we at least by way of having multiple tests caught this mistake somehow so it would be nice though if we weren't writing so much darn code here right because notice what I've done I have try except try except I have all of
385:54
Speaker A
these assertions I have a main function I have this if conditional at the bottom of my file I mean honestly who's going to want to write 31 lines of code now just to test a two line function right
386:05
Speaker A
no one's going to write test code like this if we're all writing so much more code to do the actual testing so people have solved this problem if you are in the habit of testing your code a lot or
386:16
Speaker A
wanting to if I'm in the habit of wanting to test my code a lot if everyone else in the real world is in this habit of wanting to test their code why don't we create tools that make it a
386:23
Speaker A
little easier to do so and in fact there is a mechanism for doing this whereby we can use a tool that's popularly called pest so py test is a third-party program that you can downloaded install that will automate the testing of your code
386:38
Speaker A
so long as you write the tests but what's nice about this library and others like it is that it adopts some conventions so that you don't have to write as many lines of code yourself manually they do some of that
386:50
Speaker A
automatically for you now this is a thirdparty library there's other libraries for unit tests uh so to speak that is testing units of your code uh some of them come with python itself we're proposing that we look at py test
387:02
Speaker A
today because it's actually a little simpler than the unit testing Frameworks that come with python itself and what do we mean by unit testing unit testing is just a formal way of describing testing individual units of your program what
387:14
Speaker A
are those individual units they're typically functions so unit tests are typically tests for functions that you have written now what does this mean in practice here well let me go back to my VSS code here and let me propose that we
387:28
Speaker A
simplify my test calculator significantly I'm going to go ahead and delete all of these tests which were um which we're accumulating to like 31 lines of code and let's see if we can distill the tests to their Essence using
387:41
Speaker A
p test from my same calculator program let me still import Square so I do still need that line of code so that I can test that specific function now I'm going to go ahead and Define a function just like I did before as follows I'm
387:53
Speaker A
going to define a function called test Square Again by convention test underscore and the name of the function you want to test though it doesn't have to be that way and now I'm going to go ahead and make a few assertions I'm
388:04
Speaker A
going to assert that the square of two should equal four I'm going to assert that the square of three should equal 9 I'm going to assert that the square of -2 should equal 4 and I'm going to insert that the square of -3 should
388:19
Speaker A
equal 9 and lastly for now I'm going to assert that the square of 0 should equal zero so I'm still using the assert keyword as I introduced earlier and even though it was a little tedious to type those I mean it's only eight lines of
388:32
Speaker A
code now and they're so easy to type it's try and accept and all of this wouldn't it be nice if something else someone else handled the try the accept the printing all of the standardization of actually running these tests and
388:47
Speaker A
that's where indeed P test comes into play per the documentation for py test which can itself be installed with Pip install py test which we've used to install other libraries in the past you can look at the documentation here for
388:59
Speaker A
all of its formal usage but fortunately pest is pretty userfriendly testing Frameworks go and it actually allows us to Dive Right In by just running P test on the code that we've written so if I go back to vs code here
389:11
Speaker A
and look at my test calculator. piy which notice has no main function anymore it has no conditional it has no tries it has no accepts it has no prints it just has my few assertions Pi test and other libraries like it are going to
389:26
Speaker A
automate the process of running these tests for me and informing me on the screen whether or not any of those tests failed so so let me go ahead and do this I'm going to go ahead and increase the
389:37
Speaker A
size of my terminal window for a moment just so we can see more on the screen and I'm going to run not python as I've been doing I'm going to run Pi test which again is this third party tool for
389:47
Speaker A
running tests in your code I'm going to run Pi test of testore calculator so that same file I'm going to cross my fingers as always and hit enter and we'll see that ah something has failed now admittedly even though I do think
390:02
Speaker A
you'll find that Pi test is relatively simple to use its output at least at first glance is not necessarily super user friendly so what are we seeing here we'll notice at the very top of my window is the command that I ran after
390:14
Speaker A
my prompt right below that is a single F in red which means fail so not very encouraging I tried really hard here but fail is my grade on this program but let's see exactly what happened well if I look at this excerpt here under
390:28
Speaker A
failures you'll see that test square is the function that failed all right that makes sense because that's the only one I wrote and you'll see here somewhat uh Arcane output describing what the error was so what you're seeing here is the
390:40
Speaker A
first line of output equals equals 4 which was fine there's no red error message below that so that one's okay but this line of code here assert that square of three equals equals 9 pi test did not like that assertion because it
390:52
Speaker A
didn't end up being true in fact per the red e at the start of this line You'll see that I'm effectively trying to assert that 6 equals equals 9 now where did the six come from okay wait a minute
391:06
Speaker A
if my test involves this notice that where 6 equals square of three this is saying that because I've called Square passing in a value of three it turns out its return value is six and of course mathematically six does not equal equal
391:20
Speaker A
9 so that's why this is failing now Pi test is not as user friendly as telling you exactly why the bug is there or how to fix it this is really just a clue to you what must be wrong what you're
391:34
Speaker A
seeing here is a clue that the first test passed because there's no red error below that line of code but this test failed somehow or other your Square function is returning six when passed in three instead of nine so at this point
391:49
Speaker A
you sort of put your detective hat on you go back to your actual code and you think about in calculator to Pi how in the world is line seven of my square function returning six instead of nine and at this point odds are the light
392:03
Speaker A
bulb would go off above your head proverbially and you would see oh I'm using addition instead of multiplication but what P test has done for us is automate the process of at least pointing out that error for us and if I
392:15
Speaker A
now go in and fix this let me go ahead and the light bulb has gone off I change the plus to a uh to multiply now I'm going to go ahead and after clearing my screen I'm going to run not python but
392:26
Speaker A
Pi test of test calculator. Pi crossing my fingers again and now it's green and I see just a DOT which indicates that my one and only only test passed I'm good 100% success with my test now after fixing that bug all right let me pause
392:41
Speaker A
here and see if there's any questions so my question is what if a user uh instead of because we are taking input from the user what if the user is uh somewhat malicious and types in a string instead
392:55
Speaker A
of an integer or maybe he types in a float or some other data type yeah so what if the user like we've seen in past examples types in instead of a number when we're expecting an integer how do
393:06
Speaker A
we test for something like that at the moment I'm admittedly not testing user input if I go back to my code here notice that my calculator function of course has the square function that we keep testing and retesting but notice
393:19
Speaker A
that all of the user input is currently relegated to my main function and admittedly as of now I am not testing my main function so they could be one of those bugs and in fact there would be because if the user types in a string
393:32
Speaker A
like cat instead of an integer like two or three then line two recall would actually raise a value error exception so we've seen that before so when it comes to testing your code this is actually a good reason for having
393:46
Speaker A
multiple functions in your program rather than putting all of your logic in just the file itself rather than putting all of the logic in just main it's actually really good really helpful practice to break your ideas up into
393:58
Speaker A
smaller bite-sized functions that themselves are testable and what do I mean here Square is perfectly testable why because it takes as input a parameter called n and it returns as output an integer which is going to be the square thereof hopefully it has a
394:15
Speaker A
well-defined input and a well-defined output it is therefore completely within your control in your test program to pass in those values now I will say if you want to test whether Square behaves properly when past something like a
394:30
Speaker A
string like quote unquote cat we could absolutely do something like this assert that the square of uh quote unquote cat it's not going to equal something you can actually using different syntax assert that a specific exception will be
394:44
Speaker A
raised so if we were actually going to go back into our Square function improve it and deliberately raise an exception we could test for that too but for now I'm deliberately only testing the square function I'm not testing for specific
394:57
Speaker A
user input but that's another problem to be solved other questions now on unit tests uh do use the units test to test the code for the C cs50 check so check 50 is similar in spirit cheze 50 is a tool
395:13
Speaker A
that we cs50 wrote that is essentially doing something like pie test for the evaluation of students code it is similar in spirit but think of cze 50 as being an alternative to P test if you will but it works a little bit
395:27
Speaker A
differently but same idea pie test and unit testing more generally is a technique that is independent of cs50 and is something that you can and should be doing on your own code both in or outside of this class how about one
395:39
Speaker A
other question here on on um on our uh unit tests uh my question is instead of writing four times like s square of 2al 4 uh instead of that can we write if is uh I is equals to in square brackets the numbers
395:56
Speaker A
we want instead of writing four lines a really good question absolutely right now if I go back to test calculator.
396:03
Speaker A
it's in pretty manual I mean it took me a while to say and to type out those several lines and you could imagine writing some kind of loop to just assert in a loop that this equals that that
396:13
Speaker A
this equals that and so forth using a list or using maybe a list or a dictionary or some structure like that so yes you can absolutely automate some of these tests by not just doing the same thing again and again you can still
396:24
Speaker A
use all of the syntax of python to do loops but generally speaking your test should be pretty simple and in fact let me propose that we improve upon even this design further because at the moment what's not really ideal when I
396:39
Speaker A
run all of this uh when I run all of these tests when my uh function is buggy is notice the output that I got let me reintroduce that same bug by changing my multiplication back to addition let me
396:50
Speaker A
increase the size of my terminal window again and let me run Pi test again of test calculator. Pi so this is the version of my code now that has the bug again so I'm going to see that big
397:01
Speaker A
massive failure where this failure has been displayed to me but this is not as helpful as it could be right because I have all of those other tests in my code recall that I had what 1 2 3 four five
397:14
Speaker A
separate tests and it I'm only seeing the output of the first now why is that well if we go back to my code here you'll see that the first assertion that's failing namely this one here that assert of square of three equals equals
397:26
Speaker A
9 the other tests aren't even getting run and that's not a big deal in the sense that my code is buggy so one or more of them are probably going to fail anyway but wouldn't it be nice to know
397:37
Speaker A
which of them are going to fail and in fact it's ideal to run as many tests all at once as possible to give you as many Clues as possible to finding your bug so let me propose that we improve the
397:47
Speaker A
design of my testing code now still using pi test as follows instead of having one big function called test square that tests the entire function itself with so many different inputs let's break down my tests into different categories and here too there's no one
398:03
Speaker A
right way to do this but my mind is thinking that I should maybe test positive numbers separately test negative numbers separately and test zero separately I could think of other ways I could test even numbers I could test odd numbers or maybe some other
398:16
Speaker A
pattern alt together but separating this big test into multiple tests is probably going to yield more clues for me when something goes wrong so let me do this let me go ahead and rename this function to test positive initially and let me
398:30
Speaker A
include in that function only those first two tests let me then create another function here called test negative and in this function let me test only -2 and -3 then down here let me do one more def of test zero and I'll
398:45
Speaker A
just run one test in there so I have the same assertions the same five but I've now divided them up among three separate functions what's nice about Pi test and other unit testing Frameworks is that all three of these test functions will
398:59
Speaker A
be run automatically even if one of them fails the others will be attempting that means that if one or two or three of them fail I'll have one or two or three Clues now for helping me find that
399:11
Speaker A
mistake so let me go ahead and again increase the size of my terminal window just so we can see more on the screen my calculator still has the bug using addition instead of multiplication let me go ahead and run not python but again
399:23
Speaker A
Pi test of test calculator. piy crossing my fingers as always and now oh my God there's even more errors on the screen but this in itself is more helpful let's work through them from top to bottom so under failures here in all caps which I
399:36
Speaker A
know is not very encouraging to see failure when you're just trying to solve a problem but that's what these Frameworks do under failures the first function that failed is test positive but here too we see the same clue as
399:47
Speaker A
before the first one two the square of two equals equals 4 that one's fine it's not airing with any red errors but the next one is failing so I know that square is broken when I pass in three
399:58
Speaker A
all right what about down here it looks like unfortunately my test negative function is failing to why well when I pass in oh this is interesting here now -2 doesn't even work so I got lucky with positive two but negative -2 isn't
400:11
Speaker A
working so that's a bit of a clue but in total only two tests failed so notice at the very bottom this summary two failed and one passed what's the other one what was the third one test zero so test zero
400:24
Speaker A
is passing these two are failing and so that kind of leads me logically mathematically if you will to the source of the bug and just to be clear too if you have a lot of tests this little oneline output is helpful even though
400:36
Speaker A
also a bit discouraging fail fail and Dot means pass so there are the three tests just depicted graphically a little bit differently well let me rewind now and go back into calculator. Pi let's fix that bug because let's suppose that
400:52
Speaker A
I've deduced okay I'm using addition I should have been using multiplication all this time let me now after fixing the bug yet again let me go back to my big terminal let me run Pi test of test calculator. Pi hitting enter crossing my
401:04
Speaker A
fingers now and dot dot dot means all is well 100% of my tests passed all three of them so now I'm good it doesn't necessarily mean that my code is 100% correct but it does mean that it has
401:17
Speaker A
passed 100% of my current tests and so it would probably behoove us to think a little harder about maybe we should test bigger numbers maybe we should test even smaller numbers maybe we should test strings or something else the onus is
401:30
Speaker A
ultimately on you to decide what you're going to test but in the real world you're going to be very unhappy with yourself or someone else maybe your boss is going to be very unhappy with you if you did not catch a bug in your code
401:42
Speaker A
which you could have caught had you just written a test to try that kind of input all right let me pause again and see if there's any questions now on unit testings with P test um so if you wanted
401:53
Speaker A
to test like someone suggested before user input as well as testing your function do you do that within the same file or do you make separate files for different types of test really good question you could absolutely make separate files to test
402:07
Speaker A
different types of things or if you don't have that many you can keep them all in the same file at the moment I've been storing all of my tests in one file for convenience and there's not terribly many of them but we'll take a look in a
402:18
Speaker A
bit at an example that allows me to put them into a folder and even run P test on a whole folder of tests as well so that's possible other questions on unit testing so I've got two questions um so
402:31
Speaker A
a couple while ago you just used um an exception called assertion um I'm not sure what was oh yeah assertion error um what exactly does that particular error catch and my second question is does the assert keyword um stand out to the compiler and
402:52
Speaker A
exactly tell them to assert this particular um line of code indeed the assert keyword we're seeing and the assertion error we saw earlier are intertwined so when you use assert and the assertion fails because whatever Boolean expression you're using is not
403:09
Speaker A
true it's false an assertion error by definition of python will be raised so those two work in conjunction those errors those assertion errors are still being raised by my code here when any of these lines of code fail however pest
403:24
Speaker A
this third party library is handling the process of catching those exceptions automatically for me so as to give me the standard output so we started to today's Story by really implementing unit testing myself I wrote all of the
403:37
Speaker A
code myself I wrote main I did my conditional I did try except honestly it's going to get incredibly painful to write tests long term if you and I have to write that much code every time especially when our function is this
403:47
Speaker A
small uh so pie test and unit testing Frameworks like it just automate so much of that essentially P test adds the try the accept the if the prints for you so you can just focus on the essence of the
403:59
Speaker A
tests which really are these inputs and outputs how about time for one other question here on unit testing as well sir uh when we uh enter minus 6 or minus5 uh the uh square or Square uh square root of the that uh number comes
404:16
Speaker A
up but when we put 6.6 or 5.6 something like that integer then uh line shows error so what's happening there so if I'm deliberately testing integers right now in large part because I only want pow to operate on inte ERS
404:33
Speaker A
and that might be conveyed in Python's documentation or my own documentation for that function if we were to pass in something else like a float it turns out that floating Point values in Python and other languages are actually very hard
404:46
Speaker A
if not impossible to represent 100% precisely and so if you are trying to compare it against some other value they might be slight rounding errors as a result I'm just inferring from what you've described but I'm very deliberately now testing this function
405:00
Speaker A
with only the inputs that I would expect it might indeed throw other errors if other inputs are passed all right allow me to propose that we consider what should happen if Square isn't actually passed a number for instance if I go
405:13
Speaker A
back to calculator. Pi and suppose that I or perhaps someone else using my Square function simply forgets to convert the return value of input from a stir to an INT as by modifying line two here well now something's definitely
405:26
Speaker A
going to go wrong if I type in a stir instead of what appears to be an INT for instance if I clear my terminal here run pip Pyon of calculator. Pi and hit enter let's type in cat as our value for x and
405:39
Speaker A
of course this raises Now a type error why can't multiply sequence by non-int of type stir what does that mean well you can't do cat times cat because indeed square is expecting that n will be some number but that doesn't
405:51
Speaker A
necessarily mean that square itself is buggy but this does mean that if I expect a type error to be raised let's test for that too so that I know the behavior indeed works as expected so let me go back to test calculator p and let
406:04
Speaker A
me go and add a fourth test down here how about Define testore and I'll call this tester because I'm going to specifically and deliberately pass in a stir for testing and I want to in spirit assert that passing in something like
406:19
Speaker A
cat to square will raise a type error but we don't use the assert keyword for that rather we need this let me go to the top of this file and let me additionally import the pest Library itself because it turns out there's a
406:32
Speaker A
function in that Library called raises that allows me to express that I expect an exception to be raised and I can express that as follows with pest.
406:42
Speaker A
raises and then in parenthesis I can pass in the type of exception I expect which is going to be a type error in this case and now when do I expect that type error to be raised whenever I do
406:53
Speaker A
something like calling square and passing in not a number but something like cat so now if I go back to my terminal window run Pi test of test calculator. piy this time having four tests I should see that all four now are
407:08
Speaker A
successful all right let's now consider how we could test code that doesn't just expect numbers as input but actually strings and let me rewind Us in time here in VSS code to that very first program rewrote a few different versions
407:21
Speaker A
of in hello.py that ultimately looked a little something like this I had a main function that prompted the user for the value of a variable by asking them what's your name question mark and then we went ahead and did something like
407:34
Speaker A
hello open pen name passing that user's name into a function called hello now that function hello recall ultimately looked like this we defined hello as taking a parameter called two the default value of which was world and that function very simply printed hello
407:53
Speaker A
followed by a comma and then whatever the name that had been passed in and then we ultimately called main but for now onward I'm going to always add this if conditional if name equals equals underscore uncore main then and only
408:07
Speaker A
then do I want to call Main so that's essentially what this program looked like in its last Incarnation how do we go about testing it well here again too I'm not going to test the user's input per se in main I'm going to focus really
408:18
Speaker A
on the module the module of code here that's of Interest which is the hello function itself how can I go about testing the hello function well unfortunately even if I start by doing something like code of test hello.py
408:33
Speaker A
let me go about and start writing a test program I could import from my hello program a function called hello so a bit strange to see from Hello import hello but notice that on this line here I'm importing from the module that is the
408:47
Speaker A
file called hello.py the function called hello and how do I go about testing this well if I have a function like Define uh test argument like this well let me Sue this so if I were toine a function like
409:03
Speaker A
like Define test hello what could I do well I could call hello with quote unquote say uh David and then check if it equals what hello comma David so would this work this approach here if I've written a test called test hello
409:24
Speaker A
that calls hello with an argument of David and then tests its return value just like we've done for our calculator would this work as written and let me go back to in just a moment the version of hello that we're testing
409:37
Speaker A
so you can see that function hello here's the test here is the actual code would this test now work any thoughts uh I think the problem is that in the first version in hello.py you're using the toe argument
409:54
Speaker A
that you first declare when you declare the function instead of using the name okay I that is actually uh not a bug here so let me stipulate that in hello.py this code actually does work as intended and let me go ahead and test it
410:09
Speaker A
manually just to demonstrate as much let me run python of hello.py typing in as my name David and I see in fact that it says hello David if though I were to change this program and get rid of the
410:22
Speaker A
name argument get rid of the name variable and just call hello again running python of hello.py this time I'm not even prompted because I got rid of my input call but it does pre behave as I expect it does say hello world so let
410:35
Speaker A
me stipulate that this code in its current form is actually correct but my test is not going to work as I'd hoped and there's a subtle difference between hello versus my pow function that expl versus my there's a subtle difference
410:50
Speaker A
between my hello function and my Square function that explains why might this test not work as intended um because it's not returning a value yeah exactly recall our discussion early on about functions functions can either return a value like my Square
411:07
Speaker A
function hands you back the square of some value or they can have side effects sort of visual uh artifacts that might happen on the screen like printing something out on the screen and by definition that's how Print Works notice
411:19
Speaker A
that hello it is short but it's implemented ultimately using the print function which does not return a value as I'm using it here it instead has this side effect of printing something onto the screen so it is not correct in my
411:31
Speaker A
test function to check if the return value of hello equals equals hello David because again hello is not returning anything it's printing something with that side effect but notice literally it has no return keyword unlike my Square function which did so here's an
411:49
Speaker A
opportunity too to perhaps change how I go about implementing my actual functions it turns out that as your programs get more and more sophisticated more and more complicated it tends to be best practiced not to have side effects
412:02
Speaker A
if if you can avoid it especially if you want your code to be testable and in fact I'm going to propose that we change my hello program to now work as follows let me go ahead and change this function
412:14
Speaker A
to not print hello and then that name let me go ahead and literally return maybe an F string which will clean this up a little bit hello comma 2 close quote at the end so my syntax here is
412:27
Speaker A
just the familiar F string or format string it's going to return hello world or hello David or hello whoever name is passed in as that argument but I'm returning it now I'm not printing it out so what needs to change up here well I
412:41
Speaker A
could do something like this I could say something like output equals hello and then print output in my main function or I can simplify that because I don't really need that variable I could instead just do this I could still call
412:55
Speaker A
hello but I could immediately print out the result and this version of my hello program now is actually more test able why because these assert statements that we're using and we've seen th far for our tests are really designed to test
413:10
Speaker A
arguments into functions and return values there from not testing side effects so if you're doing equals equals you're looking for a return value something that's handed back from the function so that's fine if I modify the design of my program now not to just
413:25
Speaker A
print hello but to return the string the sentence the phrase that I want to construct I can leave it to the caller that is the function who's using this hello function to handle the actual printing now what does this mean in my
413:39
Speaker A
code well it means now if my hello.py looks like this and hello is indeed returning a value in my test hello function I can test it exactly like this so let me go ahead and run Pi test of
413:51
Speaker A
test hello.py crossing my fingers as always and voila one passed so I passed this test because apparently the return value of hello does indeed equal hello comma David well let's test the scenario what if I P call hello without any
414:06
Speaker A
arguments let's assert that calling hello with nothing in those parentheses similarly equals hello comma but world the default value let me now go ahead and run Pi test of test hello.py and that too passes entirely but there too
414:22
Speaker A
suppose that I had made some mistake suppose that there were a bug in my code it might not be best practice to combine multiple tests in this one function so let's make it more clear what might pass or fail let's call the first function
414:33
Speaker A
test the default uh to this function and let's only include this first line of code and then let's go ahead and Define another function like test argument to test this other line of code here so now I have two different tests Each of which
414:46
Speaker A
is testing something a little fundamentally different so now when I run my code it's still not broken if I run Pi test of test hello.py enter I've now passed two tests and that's just as good as before but if I did have a bug
415:01
Speaker A
having two tests instead of one would indeed give me perhaps a bit more of a hint as to what's wrong questions now on this testing of return values when these return values are now strings instead of integers and why we've done this so my
415:16
Speaker A
question is uh about function inside the function uh can we test that too or recursion we we we have't seen if you have if you have a recursive function which we've not discussed in this class yes you can absolutely test
415:33
Speaker A
those two uh by simply calling them exactly in this way recursion does not affect this process all right how about one more question here on unit test before we look at one final example when testing our uh arguments like uh can we
415:48
Speaker A
use something like a Loops or inside of assert or for the values absolutely you can absolutely use a loop to test multiple values in this case for instance I could do something like this I could say for name in The Following
416:05
Speaker A
list of Hermione uh say Harry and Ron I could then within this Loop assert that hello of that given name equals equals say the format string of hello comma name and then run all of these here at once by
416:26
Speaker A
running again Pi test of test hello.py it's still going to be just one test within that function but if there's something interesting about those several strings that makes it compelling to test all of them you can absolutely automate the tests in that way with that
416:39
Speaker A
said each of your test should ideally be pretty simple and pretty small why because you don't want to write so much code so much complicated code that your tests might be flawed what we don't want to have to do is write tests for our
416:51
Speaker A
tests and tests for our test for our tests because it would never end so keeping tests nice and simple is really the goal so that a reasonable human yourself included can eyeball them and just claim yeah that is correct we don't
417:03
Speaker A
need tests for our tests all right how about one other feature suppose that we don't have just one test but many different tests instead and we want to start to organize those tests into multiple files and even a folder well P
417:14
Speaker A
test and other Frameworks support that Paradigm as well in fact let me go ahead and test hello.py using a folder of tests with technically just one test but it would be representative of having even more in that folder I'm going to go
417:26
Speaker A
ahead and create a new folder called test using makeer at my command line and then Within that file I'm within that and then within that folder I'm going to go ahead and create a file called test hello.py within this file meanwhile I'm
417:41
Speaker A
going to test the same things I'm going to go ahead and from Hello import hello and I'm going to go ahead and Define a function like test default that simply tests the scenario where hello with no arguments returns hello comma
417:54
Speaker A
world and I'm going to have that other function where I test that an argument is passed and in this case I'll choose an argument like asserting that hello quote unquote David equals indeed hello comma not world but David So in this
418:09
Speaker A
case I've just recreated the same test as earlier but they're in a file now in a folder called test well P test allows me to run these here too but to do so I actually need to create one other file
418:20
Speaker A
within my test directory I need to create a file called uncore uncore init uncore uncore dopy which has the effect even if this file is empty of ing python to treat that folder as not just a module but a package so to speak a
418:39
Speaker A
package is a python module or multiple modules that are organized inside of a folder and this file underscore uncore init underscore uncore Pi is just a visual indicator to python that indeed it should treat that folder as a package
418:53
Speaker A
if I had more code in this folder I could do even more things with this file but for now it's just a cluee that it's indeed meant to be a package and not just a module or file alone what I can
419:03
Speaker A
now do in closing is run P test not even on that specific file but on a whole folder of tests so if I run Pest of test where the test is the name of that folder pest will automatically search
419:16
Speaker A
through that folder looking for all possible tests granted there's just those two in this one file but when I run it now with enter I'll still pass those tests I'll still get 100% And I now have a mechanism ultimately for
419:29
Speaker A
testing my own code so whether you're writing functions that return integers or something else functions that have side effects that could be Rewritten as functions that return values you now have a mechanism to not just wait for one someone like us to test your code
419:41
Speaker A
and not just test your code manually again and again which might get tedious and you might make mistakes by not including some possible inputs we now have an automated mechanism for testing one's own code that's going to be even
419:52
Speaker A
more powerful when you start collaborating with others so that you can write tests that ensure that if they make a change to the same code they haven't broken the code that you've written all right that's it for this
420:03
Speaker A
week we'll see you next time [Music] [Music] all right this is cs50's Introduction to programming with python my name is David men and this is our week on file IO input and output of files so up until now most every program we've written
420:44
Speaker A
just stores all the information that it collects in memory that is in variables or inside of the program itself a downside of which is that as soon as the program exits anything you typed in anything that you did with that program
420:56
Speaker A
is lost now with files of course on your Mac or PC you can hang on to information long term and file IO within the context of programming is all about writing code that can read from that is load
421:07
Speaker A
information from or write to that is save information to files themselves so let's see if we can't transition then from only using memory and variables and the like to actually writing code that save some files for us and therefore
421:20
Speaker A
data persistently well to do this let me propose that we first consider a familiar data structure a familiar type of variable that we've seen before that of a list and using lists we've been able to store more than one piece of
421:32
Speaker A
information in the past using one variable we typically store one value but if that variable is a list we can store multiple values unfortunately lists are stored in the computer's memory and so once your program exits even the contents of those disappear but
421:46
Speaker A
let's at least give ourselves a starting point so I'm over here in vs code and I'm going to go ahead and create a simple program using Code of names. py a program that just collects people's names students names if you will and I'm
421:59
Speaker A
going to do it super simply initially in a manner consistent with what we've done in the past to get user input and print it back out I'm going to say something like this name equals input quote unquote what's your name thereby storing
422:12
Speaker A
in a variable called name the return value of input as always and as always I'm going to go ahead and very simply print out a nice F string that says hello comma and then in curly brace's name to print out hello David hello
422:25
Speaker A
world however happens to be using the program let me go ahead and run this just to remind myself what I should expect and if I run python of names.
422:32
Speaker A
high and hit enter type in my name like David of course I now see hello comma David suppose though that we wanted to add support not just for one name but multiple names maybe three names for the sake of discussion so that we can begin
422:44
Speaker A
to accumulate some amount of information in the program such that it's really going to be a downside if we keep throwing it away once the program exits well let me go back into names. up here at top let me proactively give myself a
422:59
Speaker A
variable this time called names plural and set it equal to an empty list recall that the square bracket notation especially if nothing's inside of it just means give me an empty list that we can add things to over time well what do
423:11
Speaker A
we want to add to it well let's add three names each from the user and let me say something like this uh for underscore in range of three let me go ahead and prompt the user with the input
423:23
Speaker A
function and getting their name in this variable and then using list syntax I can say names. append name to that list list and now I have in that list that given name one two three of them other points to note is I could use a variable
423:40
Speaker A
here like I which is conventional but if I'm not actually using I explicitly on any subsequent lines I might as well just use underscore which is a pythonic convention and actually if I want to clean this up a little bit right now
423:51
Speaker A
notice that my name variable doesn't really need to exist because I'm assigning it a value and then immediately appending it well I could tighten this up further by just getting rid of that variable Al together and just appending immediately the return
424:05
Speaker A
value of input I think we could go both ways in terms of design here on the one hand it's a pretty short line and it's readable on the other hand if I were to eventually change this phrase to be not
424:15
Speaker A
what's your name but something longer we might want to break it out again into two lines but for now I think it's pretty readable now later in the program let's just go ahead and print out those same names but let's sort them
424:26
Speaker A
alphabetically so that it makes sense to be gathering them all together then sorting them and printing them so how can I do that well in Python the simplest way to sort a list in a loop is probably to do something like this for
424:38
Speaker A
name in names but wait let's sort the names first recall that there's a function called sorted which will return a sorted version of that list now let's go ahead and print out uh an F string that says again hello bracket name close
424:54
Speaker A
quote all right let me go ahead and run this so Python ofn names. and let me go ahead and type in a few names this how about hermion how about Harry how about Ron and notice that they're not quite in
425:08
Speaker A
alphabetical order but when I hit enter and that Loop kicks in it's going to print out hello Harry hello Hermione hello Ron in sorted order but of course now if I run this program again all of the names are lost and if this is a
425:23
Speaker A
bigger program than this that might actually be pretty painful to have to re-input the same information again and again and again wouldn't it be nice like most any program today on a phone or or a laptop or desktop or Cloud to be able
425:34
Speaker A
to save this information somehow instead and that's where file IO comes in and that's where Files come in they are a way of storing information persistently on your own phone or Mac or PC or some Cloud servers uh disk so that they're
425:49
Speaker A
there when you come back and run the program again so how can we go about saving all three of these names on in a file as opposed to having to type them again and again let me go ahead and
426:01
Speaker A
simplify this file and again give myself just a single variable called name and set the return value of input equal to that variable so what's your name as before quote unquote and now let me go ahead and let me do something more with
426:15
Speaker A
this value instead of just adding it to a list or printing it immediately out let's save the value of the person's name that's just been typed in to a file well how do we go about doing that well
426:25
Speaker A
in Python there's this function called open whose purpose in life is to do just that to open a file but to open it up Pro grammatically so that you the programmer can actually read information from it or write information to it so
426:38
Speaker A
open is like the programmer's equivalent of like double clicking on an icon on your Mac or PC but it's a programmer's technique because it's going to allow you to specify exactly what you want to read from or right to that file formally
426:51
Speaker A
its documentation is here and you'll see that its usage is relatively straightforward it minimally just requires the name of the file that we want to open and optionally how we want to open it so let me go back back to vs
427:02
Speaker A
code here and let me propose now that I do this I'm going to go ahead and call this function called open passing in an argument for names.txt which is the name of the file I would like to store all of
427:14
Speaker A
these names in I could call it anything I want but because it's going to be just text it's conventional to call it something. txt but I'm also going to tell the open function that I plan to write to this file so as a second
427:26
Speaker A
argument to open I'm going to put literally quote unquote W for right and that's going to tell open to open the file in a way that's going to allow me to change the content and better yet if it doesn't even exist yet it's going to
427:38
Speaker A
create the file for me now open returns what's called a file handle a special value that allows me to access that file subsequently so I'm going to go ahead and sign it equal to a variable like file and now I'm going to go ahead and
427:51
Speaker A
quite simply write this person's name to that file so I'm going to literally type file which is the variable uh linking to that file WR which is a function otherwise known as a method that comes with open files that allows me to write
428:07
Speaker A
that name to the file and then lastly I'm going to quite simply going to go ahead and say file. close which will close and effectively save the file so these three lines of code here are essentially the programmers equivalent
428:19
Speaker A
to like double clicking an icon on your Mac or PC making some changes in Microsoft Word or some other program and going to file save we're doing that all in code with just these three lines here well let's see now how this works let me
428:32
Speaker A
go ahead now and run python of names. piy and enter let's type in a name I'll type in her Mayan enter all right where did she end up well let me go ahead now and type code of names.txt which is a
428:49
Speaker A
file that happens now to exist because I opened it in right mode and if I open this in a tab we'll see there is Hermione well let's go ahead and run names. py once more I'm going to go
429:00
Speaker A
ahead and run python of names. py enter and this time I'll type in Harry let me go ahead and run it one more time and this time I'll type in Ron and now let me go up to names. text where hopefully
429:13
Speaker A
I'll see all three of them here but no I've just actually seen Ron What might explain what happened to Hermione and Harry even though I'm pretty sure I ran the program three times and I definitely wrote the code
429:28
Speaker A
that writes their name to that file what's going on here do you think I think because we are not appending them we should append the names uh since we are writing directly it is erasing the old content and it is replacing with the
429:44
Speaker A
last uh um set of characters that we mentioned exactly unfortunately quote unquote W is a little dangerous not only will it create the file for you it will also recreate the file for you every time you open the file in that mode so
429:58
Speaker A
if you open the file once and write Hermione that worked just fine as we saw but if you do it again for Harry if you do it again for Ron the code is working but each time it's opening the file and
430:07
Speaker A
recreating it with brand new contents so we had one version with Hermione one version with Harry and one final version with Ron but ideally I think we probably want to be appending as bashall says each of those names to the file not just
430:20
Speaker A
clobbering that is overwriting the file each time so how can I do this it's actually a relatively easy fix let me go ahead and do this as follows I'm going to first remove the old version of names. text and now I'm going to change
430:32
Speaker A
my code to do this I'm going to change the W quote unquote to just a quote unquote a for aend which means to add to the bottom to the bottom to the bottom again and again now let me go ahead and
430:43
Speaker A
rerun python of names. piy enter I'll again start from scratch with hermion because I'm creating the file new notice that if I now do code of names.txt enter we do see that hermion is back so we've after removing the file it did get Rec
431:01
Speaker A
created even though I'm using a pend which is good but now let's see what happens when I go back to my terminal and this time I run python of names. py again this time typing in Harry and let
431:12
Speaker A
me run it one more time this time typing in Ron so hopefully this time in that second tab names. text I should now see all three of them but but but but this doesn't look ideal what have I clearly
431:26
Speaker A
done wrong something tells me even though all three names are there it's not going to be easy to read those back unless you know where each name ends and Begins the English format is not correct like the English format is not correct like it's
431:43
Speaker A
say correct it's concatenating them it is it's it's in can it's well it appears to be concatenating but technically speaking it's just a pending to the file first Hermione then Harry then Ron it has the effect of combining them back to
431:58
Speaker A
back but it's not concatenating per se it really is just a pending let's go to another hand here what really have I done wrong or equivalently how might I fix it would be nice if there were some kind of gaps between each of the names
432:12
Speaker A
so we could read them more cleanly Hello uh we should uh add new line before we uh write new name good we want to add a new line ourselves so whereas print by default recall always outputs automatically a line ending of back sln
432:28
Speaker A
unless we override it with the named parameter called n and right does not do that right takes you literally and if you say WR Hermione that's it you're getting the H through the E if you say right hairry you get the H through the Y
432:41
Speaker A
you don't get any extra new lines automatically so if you want to have a new line at the end of each of these names we've got to do that manually so let me again Clos names. text and let me
432:52
Speaker A
remove the current file and let me go back up to my code here and I can fix this in any number of ways but I'm just going to go ahead and do this I'm going to write out an F string that contains
433:01
Speaker A
name and back sln at the end we could do this in different ways we could manually print just the new line or some other technique but I'm going to go ahead and use my f strings as I'm in the habit of
433:11
Speaker A
doing and just print the name and the new line all at once I'm going to go ahead now and down to my terminal window run python of names. py again enter we'll type in Hermione I'm going to run
433:22
Speaker A
it again type in Harry I'm going to type it again and this time Ron now I'm going to run code of names.txt and open that file and now it looks like the file is a bit cleaner indeed I have each of the
433:34
Speaker A
name on its own line as well as a line ending which ensures that uh we can separate one from the other now if I were you know writing code I bet I could parse that is read the previous file by
433:46
Speaker A
looking at differences between lowercase and uppercase letters but that's going to get messy quickly generally speaking when storing data longterm in a file you should probably do it somehow cleanly like doing one name at a time well let's
433:58
Speaker A
now go back and I I'll propose that this code is now working correctly but we can design it a little bit better it turns out that it's all too easy when writing code to sometimes forget to close files
434:09
Speaker A
and sometimes this isn't necessarily a big deal but sometimes it can create problems files could get corrupted or accidentally deleted or the like depending on what happens in your code so it turns out that you don't strictly need to call close on the file yourself
434:22
Speaker A
if you take another approach instead more pythonic when M uh manipulating files is to do this to introduce this other keyword called quite simply with that allows you to specify that in this context I want you to open and
434:38
Speaker A
automatically close some file so how do we use with it simply looks like this let me go back to my code here I've gotten rid of the close line and I'm now just going to say this instead instead
434:49
Speaker A
of saying file equals open I'm going to say with open then the same arguments as before and somewhat curiously I'm going to put the variable at the end of the line why that's just the way this is done you say with you call the function
435:03
Speaker A
in question and then you say as and specify the name of the variable that should be assigned the return value of open then I'm going to go ahead and indent the line underneath so that the line of code that's writing the name is
435:16
Speaker A
now in the context of this withth statement which just ensures that automatically if I had more code in this file down below no longer indented the file would be automatically closed as soon as line four is done executing so
435:30
Speaker A
it doesn't change what has just happen but it does automate the process of at least closing things for us just to ensure I don't forget and so that something doesn't go wrong but suppose now that I wanted to read these names
435:42
Speaker A
from the file all I've done thus far is write code that writes names to the file but let's assume now that we have all of these names in the file and heck let's go ahead and add one more let me go
435:51
Speaker A
ahead and run this one more time python of names. py and let's let in Draco to the mix so now that we have all four of these names here how might we want to re them back well let me propose that we go
436:03
Speaker A
into names. now or we could create another program Al together but I'm going to keep reusing the same name just to keep us focused on this and now I'm going to write code that reads an existing file with Hermione Harry Ron
436:16
Speaker A
and Draco together and how do I do this well it's similar in spirit I'm going to start this time with with open and then the first argument is going to be the name of the file that I want to open as
436:27
Speaker A
before and I'm going to open it this time in read mode quote unquote r and to read a file just means to load it not to save it and I'm going to name the return value file and now I'm going to do this
436:39
Speaker A
and there's a number of ways I can do this but one way to read all of the lines from the file at once would be this let me declare a variable called lines let me access that file and call a
436:49
Speaker A
function or a method that comes with it called read lines so if you read the documentation on file IO in Python you'll see that open files come with a special method whose purpose in life is to read all the lines from the file
437:01
Speaker A
and return them to me as a list so what this line two is doing is it's reading all of the lines from that file storing them in a variable called lines now suppose I want to iterate over all of
437:13
Speaker A
those lines and print out each of those names for line in lines this is just a standard for Loop in Python lines is a list line is the variable that will be automatically be set to each of those
437:25
Speaker A
lines let me go ahead and print out something like oh hello uh comma and then I'll print out the line itself all right so let me go to my terminal window run python of names. py now I have not
437:39
Speaker A
deleted names.txt so it still contains all four of those names and hit enter and okay it's not bad but it's a little ugly here what's going on when I ran names. py it's saying hello to hermion to Harry to Ron to Draco but there's
437:54
Speaker A
these gaps now between the lines what's explains that symptom if if nothing else it just looks ugly it happens because in the text file we have a new line symbols uh in between those names and the print always adds another
438:12
Speaker A
new line at the end so you you use the same symbol twice perfect and here's a good example of a bug a mistake in a program but if you just think about those first principles like how do each
438:23
Speaker A
of the lines of code work that I'm using you should be able to reason exactly as Rafal did there to say that all right well one of those new lines is coming from the file after each name and then
438:32
Speaker A
of course print all of these Weeks Later is still giving us for free that extra new line so there's a couple possible solutions I could certainly do this which we've done in the past and pass in a named argument to print like end
438:44
Speaker A
equals quote unquote and that's fine I would argue a little better than that might actually be to do this to strip off of the end of the line the actual new line itself so that print is handling the printing of everything the
438:57
Speaker A
person's name as well as the new line but you're just stripping off what is really just an implementation detail in the file we chose to use new lines in my text file to separate one name from another so arguably it should be a
439:10
Speaker A
little cleaner in terms of design to strip that off and then let print print out what is really just now a name but that's ultimately a design decision the effect is going to be exactly the same well if I'm going to open this file and
439:25
Speaker A
read all the lines and then iterate over all of those lines and print them each out I could actually combine this into one thing because right now I'm doing twice as much work I'm reading all of the lines then I'm iterating over all of
439:37
Speaker A
the lines just to print out each of them well in Python with files you can actually do this I'm going to erase almost all of these lines now keeping only the width statement at top and inside of this width statement I'm going
439:50
Speaker A
to say this for line in file go ahead and print out quote unquote hello comma and then line. rstrip so I'm going to take the approach of stripping off the end of the line but notice how elegant this is so to
440:04
Speaker A
speak I've opened the file in line one and if I want to iterate over every line in the file I don't have to very explicitly load all read all the lines then iterate over all of the lines I can
440:14
Speaker A
combine this into one thought it in Python you can simply say for line in file and that's going to have the effect of giving you a for Loop that iterates over every line in the file one at a
440:24
Speaker A
time and on each iteration updating the value of this variable line to be Hermione then Harry then Ron than Draco so this again is one of the appealing aspects of python is that it reads rather like English for line and file
440:38
Speaker A
print this it's a little more compact when written this way well what if though I don't want quite this Behavior because notice now if I run python of names. piy it's correct I'm seeing each of the names and each of the hos and
440:52
Speaker A
there's no Extra Spaces in between but just to be difficult I'd really like us to be sorting these hellos really I'd like to Draco first then Harry then Hermione then Ron no matter what order they appear in the file so I could go in
441:07
Speaker A
of course to the file and manually change the file but if that file is changing over time based on who is typing their name into the program that's not really a good solution in code I should be able to load the file
441:17
Speaker A
no matter what it looks like and just sort it all at once now here is a reason to not do what I've just done I can't iterate over each line in the file and print it out but sort everything in
441:30
Speaker A
advance right logically if I'm looking at each line one at a time and printing it out it's too late to sort I really need to read all of the lines first without printing them sort them then print them so we have to take a step
441:43
Speaker A
back in order to add now this new feature so how can I do this well let me combine some ideas from before let me go ahead and start fresh with this let me give myself a list called names and
441:54
Speaker A
assign it in empty list just so I have a variable in which to accumulate all of these lines and now let me open the file with open quote unquote names. text and it turns out I can tighten this up a
442:05
Speaker A
little bit it turns out if you're opening a file to read it you don't need to specify quote unquote r that is the implicit default so you can tighten things up by just saying open names.
442:15
Speaker A
text and you'll be able to read the file but not write it I'm going to give myself a variable called file as before I am going to iterate over the file in the same way for line in file but
442:25
Speaker A
instead of printing each line I'm going to do this I'm going to take my name's list list and append to it and this is appending to a list in memory not appending to the file itself I'm going to go ahead and append the current line
442:40
Speaker A
but I'm going to strip off the new line at the end so that all I'm adding to this list is each of the students names now I can use that familiar technique from before let me go outside of this
442:52
Speaker A
with statement because now I've read the entire file presumably so by the time I'm done with lines four and five again and again and again for each line in the file I'm done with the file it can close
443:02
Speaker A
I now have all of the students names in this list variable let me do this for name in not just names but the sorted names using our python function sorted which does just that and do print quote unquote with an FST string hello comma
443:18
Speaker A
and now I'll plug in bracket name so now what have I done I'm creating a list at the beginning just so I have a place to gather my data I then on lines 3 through five iterate over the file from Top top
443:31
Speaker A
to bottom reading in each line one at a time stripping off the new line and adding just the students name to this list and the reason I'm doing that is so that on line seven I can sort all of
443:41
Speaker A
those names now that they're all in memory and print them in order I need to load them all into memory before I can sort them otherwise I'd be printing them out prematurely and Draco would end up last instead of first so let me go ahead
443:53
Speaker A
in my terminal window and run python of names. py now and hit enter and there we go the same list of four hellos but now they're sorted and this is a very common technique when dealing with files and
444:05
Speaker A
information more generally if you want to change that data in some way like sorting it creating some kind of variable at the top of your program like a list adding or appending information to it just to collect it in one place
444:18
Speaker A
and then do something interesting with that collection that list is exactly what I've done here now I should note that if we just want to sort the file we can actually do this even more simply in Python particularly by not bothering
444:30
Speaker A
with this names list nor the second for Loop and let me go ahead and instead just do more simply this let me go ahead and tell python that we want the file itself to be sorted using that same
444:40
Speaker A
sorted function but this time on the file itself and then inside of that for Loop let's just go ahead and print right away our hello comma followed by the line itself but still stripping off of the end of it any white space therein if
444:53
Speaker A
we go ahead and run this same program now with python of names. py and hit enter we get the same result but of course it's a lot more compact but for the sake of discussion let's assume that we do actually want to
445:05
Speaker A
potentially make some changes to the data as we iterate over it so let me undo those changes leave things as is whereby now we'll continue to accumulate all of the names first into a list maybe do something to them maybe forcing them
445:16
Speaker A
to uppercase or lower case or the like and then sort and print out each item let me pause and see if there's any questions now on file IO reading or writing or now accumulating all of these values in some list hi it's is there a
445:31
Speaker A
way to sort the files but instead if you want it from alphabetically from A to Z is there a way to reverse it from Z to A is there like a little extension that you can add to the end to do that or
445:43
Speaker A
would you have to create a new function if you wanted to reverse the contents of the file yeah so if you instead of sorting them from a to z in ascending order if you wanted them in descending order is there an extension for that
445:57
Speaker A
there is indeed and as always the documentation is your friend so if the goal is to sort them not in alphabetical order which is the default but maybe reverse alphabetical order you can take a look for instance at the formal python
446:08
Speaker A
documentation there and what you'll see is this summary you'll see that the sorted function takes a first argument generally known as an iterable and something that's iterable means that you can iterate over it that is you can Loop
446:19
Speaker A
over it one thing at a time what the rest of this line here means is that you can specify a key like how you want to sort it but more on that later but this last named parameter here is reverse and
446:30
Speaker A
by default per the documentation it's false it will not be reversed by default but if we change that to true I bet we can do that so let me go back to vs code here and do just that let me go ahead
446:40
Speaker A
and pass in a second argument to sorted in addition to this iterable which is my names list iterable again in the sense that it can be looped over and let me pass in Reverse equals true thereby overwriting the default of false let me
446:55
Speaker A
now run python of names. piy and now Ron's at the top and draco's at the bottom so there too whenever you have a question like that moving forward consider what does the documentation say and see if there's a germ of an idea
447:08
Speaker A
there because oddar if you have some problem oddar some programmer before you has had the same question other thoughts uh can we limit uh number uh numbers of names and the second question uh can we find specific name in least really good
447:24
Speaker A
question can we limit the number of the names in the file and can we find a specific one we absolutely could if we were to write code we could for instance open the file first count how many lines
447:36
Speaker A
are already there and then if there's too many already we could just exit with cy. exit or some other message to indicate to the user that sorry the class is full as for finding someone specifically absolutely you could
447:48
Speaker A
imagine opening the file iterating over it with a for loop again and again and then adding a conditional like if the current line equals equals Harry then we found the chosen run and you can print something like that so you can
448:01
Speaker A
absolutely combine these ideas with previous ideas like conditionals to ask those same questions how about one other question on file IO uh so I just thought about um this function like uh read all lines and uh it looks like it's uh like
448:20
Speaker A
separate all the lines by this special character back sln but it looks like we don't need it character and we we always strip it uh and uh it looks like some bad design of function why why wouldn't we just strip it inside this function a
448:42
Speaker A
really good question so we are in my examples thus far using our strip to reverse uh to strip from the end of the line all of this white space you might not want to do that in this case I am
448:53
Speaker A
stripping it away because I know that each of those lines isn't some generic line of text each line really represents a name that I have put there myself I'm using the new line just to separate one value from another in other scenarios
449:07
Speaker A
you might very well want to keep that line ending because it's a very long series of text or a paragraph or something like that where you want to keep it distinct from the others but it's just a convention we have to use
449:18
Speaker A
something presumably to separate one uh chunk of text from another there are other functions in Python that will in fact handle the removal of that white space for you read lines though does literally that though it reads all of
449:31
Speaker A
the lines as is well allow me to turn our attention back to where we left off here which is just names to propose that with names. text we have an ability it seems to store each of these names
449:43
Speaker A
pretty straightforwardly but what if we wanted to keep track of other information as well suppose that we wanted to store information including a student's uh name and their house at Hogwarts be it Gryffindor or Slytherin or something else well where do we go
449:59
Speaker A
about putting that you know Hermione lives in Gryffindor so we could do something like this in our text file Harry lives in Gryffindor so we could do that Ron lives in Gryffindor so we could do that and Draco lives in Slytherin so
450:10
Speaker A
we could do that but I worry here but I worry now that we're mixing apples and oranges so to speak like some lines are names some lines are houses so this probably isn't the best design if only because it's confusing or it's
450:23
Speaker A
ambiguous so maybe what we could do is Adopt A convention and indeed this is in fact what a lot of programmers do they change this file not to be names. text but instead let me create a new file
450:34
Speaker A
called names. CSV CSV stands for comma separated values and it's a very common convention to store multiple pieces of information that are related in the same file and so to do this I'm going to separate each of these types of data not
450:49
Speaker A
with another new line but simply with a comma I'm going to keep each student on their own line but I'm going to separate the information about each student using a comma instead and so now we sort of have a a two-dimensional file if you
451:01
Speaker A
will row by row we have our students but if you think of these commas as representing a column even though it's not perfectly straight because of the lengths of these names it's a little ra it's a little uh Jagged you can think of
451:13
Speaker A
these commas as representing a column and it turns out these CSV files are very commonly used when you use something like Microsoft Excel Apple numbers or Google spreadsheets and you want to export the data to share with someone else as a CSV file or conversely
451:28
Speaker A
if you want to import a CSV file into your preferred spreadsheet software like Excel or numbers or Google spreadsheets you can do that as well so CSV is a very common very simple text format that just separates values with commas and
451:43
Speaker A
different types of values ultimately with new lines as well let me go ahead and run code of students. CSV to create a brand new file that's initially empty and we'll add to it those same names but also some other information as well so
451:56
Speaker A
if I now have this new file students. CSV inside of which is one column of names so to speak and one column of houses how do I go about changing my code to read not just those names but
452:07
Speaker A
also those names and houses so that they're not all on one line we somehow have access to both type of value separately well let me go ahead and create a new program here called uh students. py and in this program let's
452:20
Speaker A
go about reading not a text file per se but a specific type of text file a CSV a comma separated values file and to do this I'm going to use similar code as before I'm going to say with open quotee
452:32
Speaker A
unquote students. CSV I'm not going to bother specifying quote unquote R because again that's the default but I'm going to give myself a variable name of file and then in this file I'm going to go ahead and do this for line in file as
452:45
Speaker A
before and now I have to be a bit clever here let me go back to students. CSV looking at this file and it seems that on my loop on each iteration I'm going to get access to the whole line of text
452:58
Speaker A
I'm not going to automatically get access to just Hermione or just Gryffindor recall that the loop is going to give me each full line of text so logically what would you propose that we do inside of a for Loop that's reading a
453:11
Speaker A
whole line of text at once but we now want to get access to the individual values like Hermione and Gryffindor Harry and Gryffindor how do we go about taking one line of text and gaining access to those individual values do you
453:24
Speaker A
think just instinctively even if you're not sure what the name of the functions would be you can access access as you would as if you were using a dictionary like using a key and value so ideally we would access it using it a key and value
453:36
Speaker A
but at this point in the story all we have is this Loop and this Loop is giving me one line of text at is a time I'm the programmer now I have to solve this there is no dictionary yet in
453:46
Speaker A
question how about another suggestion here um so you can somehow split the two words based on the comma yeah even if you're not quite sure what function is going to do this intuitively you want to take this whole line of text hermion
453:59
Speaker A
comma Gryffindor Harry comma Gryffindor and so forth and split that line into two pieces if you will and it turns out wonderfully the function we'll use is actually called split that can split on any characters but you can tell it what
454:12
Speaker A
character to use so I'm going to go back into students. py and inside of this Loop I'm going to go ahead and do this I'm going to take the current line I'm going to remove the white space at the
454:22
Speaker A
end as always using rst strip here and then whatever the result of that is I'm going to now call split and quote unquote comma so the split function or method comes with strings stirs in Python any stir has this method built in
454:39
Speaker A
and if you pass in an argument like a comma what this stri split function will do is split that current string into one two three maybe more pieces by looking for that character again and again ultimately strip uh ultimately split is
454:55
Speaker A
going to return to us a list of all of the individual parts to the left and to the right of those commas so I can give myself a variable called row here and this is a common Paradigm when you know
455:05
Speaker A
you're iterating over a file specifically a CSV it's common to think of each uh line of it as being a row and each of the values therein separated by commas as columns so to speak so I'm going to deliberately name my variable
455:20
Speaker A
row just to be consistent with that convention and now what do I want to print well I'm going to go ahead and say this print how about the following uh in F string that starts with curly braces well how do I get access to the first
455:36
Speaker A
thing in that row well the row is going to have how many parts two because if I'm splitting on commas and there's one comma per line that's going to give me a left part and a right part like hermion
455:46
Speaker A
and Gryffindor Harry and Gryffindor when I have a list like row how do I get access to individual values well I can do this I can say Row Bracket zero and that's going to go to the first element
455:59
Speaker A
of the list which should hopefully be the student's name then after that I'm going to say is in and I'm going to have another curly brace here for Row Bracket one and then I'm going to close my whole
456:10
Speaker A
quote so it looks a little cryptic at first glance but most of this is just F string syntax with curly braces to plug in values and what values am I plugging in well row again is a list and it has
456:21
Speaker A
two elements presumably Hermione in one and Gryffindor in the other and so forth so bracket zero is the first element cuz remember we start indexing at zero in Python and one is going to be the second element so let me go ahead and run this
456:36
Speaker A
now and see what happens python of uh students. py enter and we see hermion is in Gryffindor Harry's in Gryffindor Ron is in Gryffindor and Draco is in Slytherin so we have now implemented our own code from scratch that actually
456:55
Speaker A
parses that is reads and interprets a CSV file ultimately here now let me pause to see if there's any questions but we'll make this even easier to read in just a moment any questions on what we've just done here
457:09
Speaker A
by splitting by comma so my question is uh can we uh edit any line of code anytime we want or uh the only option that we have is to append uh the lines or uh let's say if we want to let's say
457:24
Speaker A
change Harry's uh house to let's say Slytherin or some other house yeah a really good question what if you want to in Python change a line in the file and not just uh a pen to the end you would have to implement that logic
457:39
Speaker A
yourself so for instance you could imagine now opening the file and reading all of the contents in then maybe iterating over each of those lines and as soon as you see that the current name equals equals Harry you could maybe
457:52
Speaker A
change his house to slitherin and then it would be up to you though to write all of those changes back to the file so in that case you might want to in simplest form read the file once and let
458:03
Speaker A
it close then open it again but open for writing and change the whole file it's not really possible or easy to go in and change just part of the file though you can do it it's easier to actually read
458:15
Speaker A
the whole file make your changes in memory then write the whole file out but for larger files where that might be quite slow you can be more clever than that well let me propose now that we clean this up a little bit because I
458:27
Speaker A
actually think this is a little cryptic to read Row Bracket Z Row Bracket one it's it's not that well written at the moment I would say but it turns out that when you have a variable that's a list
458:38
Speaker A
like row you don't have to throw all of those variables into a list you can actually unpack that whole sequence at once that is to say if you know that a function like split returns a list but you know in advance that it's going to
458:52
Speaker A
return two values in a list the first and the second you don't have to throw them all into a variable that itself is a list you can actually unpack them simultaneously into two variables doing name comma house so this is a nice
459:06
Speaker A
python technique to not only create but assign automatically in parallel two variables at once rather than just one so this will have the effect of putting the name in the left Hermione and it will have the effect of putting
459:19
Speaker A
Gryffindor the house in the right variable and we now no longer have a row we can now make our code a little more readable by now literally just saying name down here and for instance house down here so just a little more readable
459:30
Speaker A
even though functionally the code now is exactly the same all right so this now works and I'll confirm as much by just running it once more python of students. py enter and we see that the text is as intended
459:45
Speaker A
but suppose for the sake of discussion that I'd like to sort this list of output I'd like to say hello again to Draco first then hello to Harry then Hermione then Ron how can I go about doing this well let's take some
459:58
Speaker A
inspiration from the previous example where we were only dealing with names and instead do it with these full phrases so and so is in house well let me go ahead and do this I'm going to go ahead and start scratch and give myself
460:10
Speaker A
a list uh called students equal to an empty list initially and then with open students. CSV as file I'm going to go ahead and say this for line in file and then below this I'm going to do exactly
460:25
Speaker A
as before name comma house equals the current line stripping off the white space at the end splitting it on a comma so that's exact same as before but this time before I go about uh printing the sentence I'm going to store it
460:40
Speaker A
temporarily in a list so that I can accumulate all of these sentences and then sort them later so let me go ahead and do this students which is my list do append let me append the actual sentence I want to show on the screen so another
460:54
Speaker A
F string so name is in house just as before but notice I'm not printing that sent sentence I'm appending it to my list not a file but to my list why am I doing this well just because as before I
461:07
Speaker A
want to do this for student in the sorted students I want to go ahead and print out student like this let me go ahead and run python of students. py and hit enter now and I think we'll see
461:21
Speaker A
indeed Draco is now first Harry is second hermion is third and Ron is fourth but this is arguably a little sloppy right it seems a little hackish that I'm constructing these sentences and even though I'm technically want to
461:35
Speaker A
sort by name I'm technically sorting by these whole English sentences so it's not wrong it's achieving the intended result but it's not really welld designed because I'm just kind of getting lucky that English is reading from left to right and therefore when I
461:49
Speaker A
print this out it's sorting properly it would be better really to come up with a technique for sorting by the students names not by some English sentence that I've constructed here online six so to achieve this I'm going to need to make
462:03
Speaker A
my life more complicated for a moment and I'm going to need to collect information about each student before I bother assembling that sentence so let me propose that we do this let me go ahead and undo these last few lines of
462:17
Speaker A
code so that we currently have two variables name and house Each of which has name and the student's house respectively and we still have our Global variable students but let me do this recall that python supports dictionaries and dictionaries are just
462:31
Speaker A
collections of keys and values so you can associate something with something else like a name with Hermione like a house with Gryffindor that really is a dictionary so let me do this let me temporarily create a dictionary that
462:45
Speaker A
stores this Association of name with house let me go ahead and do this let me say that the student here is going to be represented initially by an empty dictionary and just like you can create an empty list with square brackets you
462:57
Speaker A
can create an empty dictionary with curly braces so give me an empty dictionary that will soon have two keys name and house how do I do that well I could do it this way student Open Bracket name equals the student's name
463:12
Speaker A
that we got from the line student bracket house equals the house that we got from the line and now I'm going to append to the students list plural that particular student now why have I done this I've admittedly made my code more
463:28
Speaker A
complicated it's more lines of code but I've now collected all of the information I have about students while still keeping track what's a name what's a house the list meanwhile has all of the students names and houses together
463:42
Speaker A
now why have I done this well let me for the moment just do something simple let me do for student in students and let me very Simply Now say print the following F string the current student with this
463:55
Speaker A
name uh is in this current student house and now notice one detail inside of this F string I'm using my curly braces as always I'm using inside of those curly braces the name of a variable as always but then I'm using
464:12
Speaker A
not bracket zero or one because these are dictionaries now not list but why am I using single quotes to surround house and to surround name why single quotes inside of this F string to access those keys yes um because you
464:35
Speaker A
have double quotes in that in that line 12 and so you have to tell p python to differentiate exactly because I'm already using double quotes outside of the F string if I want to put quotes around any strings on the inside which I
464:49
Speaker A
do need to do for dictionaries because recall when you index into a dictionary you don't use numbers like lists 0 1 two onward you instead use strings which need to be quoted but if you're already using double quotes it's easiest to then
465:02
Speaker A
use single quotes on the inside so python doesn't get confused about what lines up with what so at the moment when I run this program it's going to print out those hellos but they're not yet sorted in fact what I now have is a list
465:16
Speaker A
of dictionaries and nothing is yet sorted but let me tighten up the code too to point out that it doesn't need to be quite as verbose if you're in the habit of creating an empty dictionary like this on line six and then
465:28
Speaker A
immediately putting in Keys name and house each with two values name and house respectively you can actually do this all at once so let me show you a slightly different syntax I can do this give me a variable called student and
465:40
Speaker A
let me use curly braces on the right hand side here but instead of leaving them empty let's just Define those keys and those values now quote unquote name will be name and quote unquote house will be house this achieves the exact
465:54
Speaker A
same effect in one line instead of three it creates a new non dictionary containing a name key the value of which is the student's name and a house key the value of which is the student's house nothing else needs to change that
466:07
Speaker A
will still just work so that if I again run python of students. I'm still seeing those greetings but they're still not quite actually sorted well what might I go about doing here in order to what could I do to improve upon this further
466:23
Speaker A
well we need some mechanism now of sorting those students but unfortunately you can't do this we can't sort all of the students now because those students are not names like they were before they aren't sentences like they were before
466:39
Speaker A
each of the students is a dictionary and it's nonobvious how you would sort a a dictionary inside of a list so ideally what do we want to do if at the moment we hit hit line nine we have a list of
466:52
Speaker A
all of these students and inside of that list is one dictionary per student and each of those dictionaries has two keys name and house wouldn't it be nice if there were a way in code to tell python sort this list by
467:05
Speaker A
looking at this key in each dictionary because that would give this the ability to sort either by name or even by house or even by any other field that we add to that file so it turns out we can do
467:17
Speaker A
this we can tell the sorted function not just to reverse things or not it takes another positional it takes another named parameter called key where you can specify what key should be used in order to sort some list of dictionaries and
467:33
Speaker A
I'm going to propose that we do this I'm going to first Define a function temporarily for now called get name and this function's purpose in life given a student is to quite simply return the student's name from that particular
467:47
Speaker A
dictionary so if student is a dictionary this is going to return literally the student's name and that's it that's the sole purpose of this function in life what do I now want to do well now that I have a function that given a student
468:00
Speaker A
will return to me the student's name I can do this I can change sorted to say use a key that's equal to whatever the return value of get name is and this now is a feature of python python allows you
468:14
Speaker A
to pass functions as arguments in two other functions so get name is a function sorted is a function and I'm passing in get name to sorted as the value of that key parameter now why am I doing that well if you think of the get
468:33
Speaker A
name function as just a bunch a block of code that will get the name of a student that's handy because that's the capability that sorted needs when given a list of students Each of which is a dictionary sorted needs to know how do I
468:45
Speaker A
get the name of the student in order to do alphabetical sorting for you the authors of python didn't know that we were going to be creating students here in this class so they couldn't have anticipated writing code in advance that
468:55
Speaker A
specifically sorts on a field called student let alone called name name let alone house so what did they do they instead built into the sorted function this named parameter key that allows us all these years later to tell their
469:10
Speaker A
function sorted how to sort this list of dictionaries so now watch what happens if I run python of students. py and hit enter I now have a sorted list of output why because now that list of dictionaries has all been sorted by the
469:26
Speaker A
student's name I can further do this if as before we want to reverse the whole thing by saying reverse equals true we can do that too let me rerun python of students. and hit enter now it's revers now it's Ron than hermion Harry and
469:39
Speaker A
Draco but we can do something different as well what if I want to sort for instance by house name reversed I could do this I could change this function from get name to get house I could change the implementation up here to be
469:53
Speaker A
get house and I can return not the student's name but the student's house and so now notice if I run python of students. piy enter notice now it is sorted by house in reverse order Slytherin is first and then Gryffindor
470:10
Speaker A
if I get rid of the reverse but keep the get house and rerun this program now it's sorted by house Gryffindor is first and Slytherin is last and the upside now of this is because I'm using this list
470:22
Speaker A
of dictionaries and keeping the students data together until the last minute when I'm finally doing the printing I now have full control over the information itself and I can sort by this or that I don't have to constru construct those
470:35
Speaker A
sentences in advance like I rather hack asly did the first time all right that was a lot let me pause here to see if there are questions so when when we sorting the files should we every time should we use the uh Loops or like a
470:52
Speaker A
like a d dictionary or or any kind of list can we sort by just sorting now looping or any kind of stuff a good question and the short answer with python alone you're the programmer you need to do the Sorting with libraries
471:10
Speaker A
and other techniques absolutely you can do more of this automatically because someone else has written that code what we're doing at the moment is doing everything from scratch ourselves but absolutely with other functions or libraries some of this could be made uh
471:23
Speaker A
more uh easily done some of this could be made uh easier other questions on this technique here it equal to the returned value of the function can it be equal to just a a variable or a value it well yes it should equal a
471:45
Speaker A
value so I'm spec and I should clarify actually since this was not obvious so when you pass in a function like get name or get house to the sorted function as the value of key that function is automatic ially called by the get by the
472:02
Speaker A
sorted function for you on each of the dictionaries in the list and it uses the return value of get name or get house to decide what strings to actually use to compare in order to decide which is alphabetically correct so this function
472:18
Speaker A
which you pass just by name you do not pass in parentheses at the end is called by the sorted function in order to figure out for you how to compare these same values how can we use nested dictionaries I
472:33
Speaker A
have read about nested dictionaries what is the difference between Ned dictionaries and dictionary inside a list I think it is sure um uh so we are using a list of dictionaries why because each of those dictionaries represents a
472:49
Speaker A
student and a student has a name in a house and we want to I claim maintain that Association and it's a list of students because we've got multiple students four in this case you could create a a structure that is a
473:01
Speaker A
dictionary of dictionaries but I would argue it just doesn't solve a problem I don't need a dictionary of dictionary I need a list of key value pairs right now that's all so let me propose if we go back to students. py here and we revert
473:14
Speaker A
back to the approach where we have get name as the function both used and defined here and that function Returns the student's name what happens to be clear is that the sorted function will use the value of key get name in in this
473:29
Speaker A
case calling that function on every dictionary in the list that it's supposed to sort and that function get name Returns the string that sorted we'll actually use to decide whether things go in this order left right or in
473:43
Speaker A
this order right left it alphabetizes things based on that return value so notice that I'm not calling the function get name here with parenthesis I'm passing it in only by its name so that the sorted function can call that get
473:56
Speaker A
name function for me now it's turns out as always if you're defining something be it a variable or in this case a function and then immediately using it but never once again needing the name of that function like get name we can
474:10
Speaker A
actually tighten this code up further I can actually do this I can get rid of the get name function Al together just like I could get rid of a variable that isn't strictly necessary and instead of passing key the name of a function I can
474:24
Speaker A
actually Pass Key what's called in a Lambda function which is an a function a function that just has no name why because you don't need to give it a name if you're only going to call it in one
474:34
Speaker A
place and the Syntax for this in Python's a little weird but if I do key equals literally the word Lambda then something like student which is the name of the parameter I expect this function to take and then I don't even type the
474:48
Speaker A
return key i instead just say student bracket name so what am I doing here with my code this code here that I've highlighted is equivalent to to the get name function I implemented a moment ago the syntax is admittedly a little
475:03
Speaker A
different I don't use def I didn't even give it a name like get name i instead I'm using this other keyword in Python called Lambda which says Hey python here comes a function but it has no name it's
475:14
Speaker A
Anonymous that function takes a parameter I could call it anything I want I'm calling it student why because this function that's passed in as key is called on every one of the students in that list every one of the dictionaries
475:29
Speaker A
in that list what do I want this Anonymous function to return well given a student I want to index into that dictionary and access their name so that the string Hermione and Harry and Ron and Draco is ultimately returned and
475:42
Speaker A
that's what the sorted function uses to decide how to sort these bigger dictionaries that have other Keys like house as well so if I now go back to my terminal window and run python of students. it still seems to work the
475:56
Speaker A
same but it's arguably a little better design because I didn't waste lines of Code by defining some other function calling it in one and only one place I've done it all sort of in one breath if you will all right let me pause here
476:09
Speaker A
to see if there's any questions specifically about Lambda or Anonymous functions and this tightening up of the code and I had one question like whether we could Define Lambda twice can you you can use Lambda twice you can create as
476:25
Speaker A
many Anonymous functions as you'd like and you generally use them in context like this where you want to pass to some other function uh a function that itself does not need a name so you can absolutely use it in more than one place
476:38
Speaker A
I just have only one use case for it how about one other question on Lambda or Anonymous functions specifically what what if our Lambda would take more than one line for example if sure if your Lambda function takes multiple parameters that is fine
476:55
Speaker A
you can simply specify commas follow by the names of those parameters maybe X and Y or so forth after the name student so here too Lambda looks a little different from DEA in that you don't have parentheses you don't have the
477:08
Speaker A
keyword def you don't have a function name but ultimately they achieve that same effect they create a function anonymously and allow you to pass it in for instance as some value here so let's now change students. CSV to contain not
477:21
Speaker A
students houses at Hogwarts but their homes where they grew up so Draco for instance grew up in Malfoy Manor uh Ron grew up in the burrow uh Harry grew up in uh number four privet drive and according to the internet no one knows
477:39
Speaker A
where hermion grew up the movies apparently took certain liberties with where she grew up so for this purpose we're actually going to remove Hermione because it is unknown exactly where she was born so we still have some three
477:49
Speaker A
students but if anyone can spot the potential problem now how might this be a bad thing well let's go and try and run our own code here let me go back to students. py here and let me propose
478:02
Speaker A
that I just change my semantics because I'm now not thinking about Hogwarts houses but the students own home so I'm just going to change some variables I'm going to change this house to a home this house to a home as well as this one
478:14
Speaker A
here I'm still going to sort the students by name but I'm going to say that they're not in a house but rather from a home so I've just Chang the names of my variables in my grammar in English
478:25
Speaker A
here ultimately to print out that for instance Harry is from number four privet drive and so forth but let's see what happens here when I run python of this version of students. having changed students. CSV to contain those homes and
478:40
Speaker A
not houses enter huh our first value error like the program just doesn't work What might explain this value error the explanation of which rather cryptically is too many values to unpack and the line in question is this one involving split how
479:00
Speaker A
did all of a sudden after all of these successful runs of this program did line five suddenly now break in the line in students that says we you have three values there's a line that you have three values and and students yeah I
479:16
Speaker A
spent a lot of time trying to figure out where uh every student should be from so that we could create this problem for us and wonderfully like the first sentence of the book is number four privet drive and so the fact that that address has a
479:29
Speaker A
comma in it is problematic why because you and I decided some time ago to just standardize on commas CSV comma separated values to denote the uh uh we standardized on commas in order to delineate one value from another and if
479:45
Speaker A
we have commas grammatically in the student's home we're clearly confusing it as this special symbol and the split function is now for just Harry trying to split it into three values not just two and that's why there's too many values
480:00
Speaker A
to unpack because we're only trying to assign two variables name and house now what could we do here well we could just change our approach for instance like one Paradigm that is not uncommon is to use something uh a little more um a
480:15
Speaker A
little less common like a vertical bar so I could go in and change all of my commas to Vertical bars that too could eventually come back to bite Us in that if my file eventually has vertical bars somewhere it might still break so maybe
480:27
Speaker A
that's not the best approach I could maybe do something like this I could escape the data as I've done in the past and maybe I could put quotes around any English string that itself contains a comma and that's fine I could do that
480:41
Speaker A
but then my code students. py is going to have to change too because I can't just naively split on a comma Now I'm going to have to be smarter about it I'm going to have to take into account split
480:53
Speaker A
only on the commas that are not inside of quotes and oh it's getting complicated fast and at this point you need to take a step back and consider you know what if we're having this problem odds are many other people
481:05
Speaker A
before us have had this same problem it is incredibly common to store data in files it is incredibly common to use CSV files specifically and so you know what why don't we see if there's a library in Python that exists to read Andor write
481:21
Speaker A
CSV files rather than reinvent a wheel so to speak let's see if we can write better code by standing on the shoulders of others who have come before us programmers passed and actually use their code to do the reading and writing
481:32
Speaker A
of csvs so we can focus on the part of our problem that you and I care about so let's propose that we go back to our code here and see how we might use the CSV Library indeed within python there
481:45
Speaker A
is a module called CSV the documentation for it is at this URL here in Python's official documentation but there's a few functions that are pretty readily accessible if we just Dive Right In and let me OS that we do this let me go back
482:00
Speaker A
to my code here and instead of Reinventing this wheel and reading the file line by line and splitting on commas and dealing now with quotes and privet drives and so forth let's do this instead at the start of my program let
482:14
Speaker A
me go up and import the CSV module let's use this library that someone else has written that's dealing with all of these Corner cases if you will I'm still going to give myself a list initially empty in which to store all these students but
482:28
Speaker A
I'm going to change my Approach here now just a little bit when I open this file with width let me go in here and change this a little bit I'm going to go in here now and say this uh reader equals
482:43
Speaker A
csvreader passing in file as input so it turns out if you read the documentation for the CSV module it comes with a function called reader whose purpose in life is to read a CSV file for you and figure out where are the commas where
482:58
Speaker A
are the quotes where are all the the potential Corner cases and just deal with them for you you can override certain defaults or assumptions in case you're using not a comma but a pipe or something else but by default I think
483:09
Speaker A
it's just going to work now how do I iterate over a reader and not the raw file itself it's almost the same the library allows you still to do this for each row in the reader so you're not
483:21
Speaker A
iterating over the file directly now you're iterating over the reader which is again going to handle all of the parsing of comma in new lines and more for each row in the reader what am I going to do well at the moment I'm going
483:34
Speaker A
to do this I'm going to append to my students list the following dictionary a dictionary that has a name whose value is the current Row's First Column and whose house or rather home now is the Row's second column now it's worth
483:50
Speaker A
noting that the reader for each line in the file indeed returns to me a row but it returns to me a row that's a list which is to say say that the first element of that list is going to be the
484:00
Speaker A
student's name as before the second element of that list is going to be the student's home uh as now before but if I want to access each of those elements remember that lists are zero indexed we start counting at zero and then one
484:13
Speaker A
rather than one and then two so if I want to get at the student's name I use Row Bracket zero and if I want to get at the student's home I use Row Bracket one but in my four Loop we can do that same
484:23
Speaker A
unpacking as before if I know this CSV is only going to have two columns I could even do this for name home in reader and now I don't need to use list notation I can unpack things all at once
484:36
Speaker A
and say name here and home here the rest of my code can stay exactly the same because what am I doing now on line 8 I'm still constructing the same dictionary as before albeit for homes instead of houses and I'm grabbing those
484:50
Speaker A
values now not from the file itself and my use of split but the reader and again what the reader is going to do is figure out where are those commas where are the quotes and just solve that problem for
485:00
Speaker A
you so let me go now down to my terminal window and run python of students. and hit enter and now we see successfully sorted no less that Draco is from Mal for Manor Harry is from number four comma Private Drive and Ron is from the
485:16
Speaker A
burrow questions now on this technique of using CSV reader from that CSV module which again is just getting us out of the business of reading each line our in Reading each of those commas and splitting so my question is related to
485:32
Speaker A
something a bit bit in the past um I recognize that you are reading a file every time you well you we're we're assuming that we have the CSV file to hand already in this case um is it possible to make a file readable and
485:51
Speaker A
writable so in in in in case if you want you could you could write stuff to the but then at the same time you could have another function that reads through the file and as changes to it as you go
486:05
Speaker A
along a really good question and the short answer is yes however historically the mental model for a file is that of a cassette tape years ago not really in use anymore but cassette tapes are sequential whereby they start at the
486:18
Speaker A
beginning and if you want to get to the end you kind of have to uh unwind the tape to get to that point the closest analog nowadays would be something like Netflix or any streaming service where there's a scrubber that you have to go
486:28
Speaker A
left to right you can't just jump there or jump there you don't have Random Access so the problem with files if you want to read and write them you or some Library needs to keep track of where you
486:37
Speaker A
are in the file so that if you're reading from the top and then you write at the bottom and you want to start reading again you seek back to the beginning so it's not something we'll do here in class it's more involved but
486:47
Speaker A
it's absolutely doable for our purposes we'll generally recommend read the file and then if you want to change it write it back out rather than trying to make more peac mail changes which is good if the though the file is massive and it
486:59
Speaker A
would just be very expensive TimeWise to change the whole thing other questions on this CSV reader is possible to write uh a paragraph in that file absolutely right now I'm writing very small strings just names or houses as I did before but
487:18
Speaker A
you can absolutely write as much text as you want indeed other questions on CSV reader can user choose himself a key like input key will be a name or home so short answer yes we could absolutely write a program that
487:38
Speaker A
prompts the user for a name and a home a name and a home and we could write out those values and in a moment we'll see how you can write to a CSV file for now I'm assuming as the programmer who
487:49
Speaker A
created students. CSV that I know what the columns are going to be and therefore I'm naming my variables accordingly however this is a good seg way to one final feature of reading csvs which is that you don't have to rely on
488:03
Speaker A
either getting a row as a list and using bracket zero or bracket one and you don't have to unpack things manually in this way we could actually be smarter and start storing the names of these columns in the CSV file itself and in
488:16
Speaker A
fact if any of you have ever opened a spreadsheet file before be it in Excel Apple Numbers Google spreadsheets or the like odds are you've noticed that the first row very frequently is a little different it actually is boldface
488:29
Speaker A
sometimes or it actually contains the names of those columns the names of those attributes below and we can do this here in students. CSV I don't have to just keep assuming that the student's name is first and that the student's
488:41
Speaker A
home is second I can explicitly bake that information into the file just to reduce the probability of mistakes down the road I can literally use the first row of this file and say name comma home so notice that name is not literally
488:57
Speaker A
something some 's name and home is not literally someone's home it is literally the words name and home separated by a comma and if I now go back into students. py and don't use CSV reader but instead I use a dictionary reader I
489:12
Speaker A
can actually treat my CSV file even more flexibly not just for this but for other examples too let me do this instead of using a CSV reader let me use a CSV dict reader which will now iterate over the
489:25
Speaker A
file top to bottom loading in each line of text not as a list of columns but as a dictionary of columns what's nice about this is that it's going to give me automatic access now to those columns names I'm going to revert to just saying
489:41
Speaker A
for Row in reader and now I'm going to append a name and a home but how am I going to get access to the current rows name and the current rows home well earlier I used bracket zero for the
489:54
Speaker A
first and bracket one for the second when I was using a reader a reader returns lists a dict reader or dictionary reader returns dictionaries one at a time and so if I want to access the current Row's name I can say row
490:09
Speaker A
quote unquote name I can say here for home row quote unquote home and I now have access to those same values the only change I had to make to be clear was in my CSV file I had to include on
490:21
Speaker A
the very first row little hints as to what these columns are and if I now run this code I think it's should behave pretty much the same python of students.
490:30
Speaker A
and indeed we get the same sentences but now my code is more robust against changes in this data if I were to open the CSV file in Excel or Google spreadsheets or apple numbers and for whatever reason change the columns
490:44
Speaker A
around maybe this is a file that you're sharing with someone else and just because they decide to sort things differently left or right by moving the columns around previously my code would have broken because I was assuming that
490:56
Speaker A
name is always first and home is always second but if I did this be it manually in one of those programs or here home comma name and suppose I reversed all of this the home comes first followed by
491:08
Speaker A
Harry the burrow then by Ron and then lastly Maloy Manor then Draco notice that my file is now completely flipped the First Column is now the second and the second's the first but I took care to update the header of that file the
491:24
Speaker A
first row notice my python code I'm not going to going to touch it at all I'm going to rerun python of students. py and hit enter and it still just works and this too is an example of like
491:36
Speaker A
coding defensively like what if someone changes your CSV file your data file ideally that won't happen but even if it does now because I'm using a dictionary reader that's going to infer from that first row for me what the columns are
491:49
Speaker A
called my code just keeps working and so it keeps getting if you will better and better any questions now on this approach yeah what is the importance of new line CSV file what's the importance of the new line in the CSV file it's
492:04
Speaker A
partly a convention in the world of text files we humans have just been for decades in the habit of storing um data line by line it's visually convenient it's just easy to extract from the file because you just look for the new lines
492:18
Speaker A
so the new line just separates some data from some other data we could use any other symbol on the keyboard but it's just common to hit enter to just move the data to the next line just a convention other questions it seems to
492:32
Speaker A
be working fine if you just have name and home I'm wondering what will happen if you want to put in more data um say you wanted to add the house to both the name and the home sure if
492:48
Speaker A
you wanted to add the house back so if I go in here and add house last and I go here and say uh Gryffindor for Harry Gryffindor for Ron and Slither in for Draco now I have three columns
493:01
Speaker A
effectively if you will home on the left name in the middle house on the right each separated by commas with weird things like number four comma privet Drive still quoted notice if I go back to students. py and I don't change the
493:14
Speaker A
code at all and run python of students dopy it still just works and this is what's so powerful about a dictionary reader it can change over time it can have more and more columns your existing code is not going to break your code
493:28
Speaker A
would break would be much more fragile so to speak if you were making assumptions like the first column's always going to be name the second column's always going to be house things will break fast if those assumptions break down so not a problem in this case
493:42
Speaker A
well let me propose that besides reading csvs let's at least take a peek at how we might write a CSV too if you're writing a program in which you want to store not just students names but maybe their homes as well in a file how can we
493:55
Speaker A
keep adding to this file let me go ahead and delete the contents of students. CSV and just read a single simple row name comma home so as to anticipate inserting more names and homes into this file and then let me go to students. py and let
494:10
Speaker A
me just start fresh so as to write out data this time I'm still going to go ahead and import CSV I'm going to go ahead now and prompt the user for their name so input quote unquote what's your
494:21
Speaker A
name question mark and I'm going to go ahead and prompt the user for their home so home equals input quote unquote where's your home question mark now I'm going to go ahead and open the file but this time for writing instead of reading
494:36
Speaker A
as follows with open quote unquote students. CSV I'm going to open it in append mode so that I keep adding more and more students and homes to the file rather than just overwriting the entire file itself and I'm going to use a
494:49
Speaker A
variable name of file I'm then going to go ahead and give myself a variable called writer and I'm going to set it equal to the return value of another function in the CSV module called CSV do writer and that writer uh function takes
495:03
Speaker A
as its sole argument the file variable there now I'm going to go ahead and just do this I'm going to say writer. WR row and I'm going to pass into WR Row the line that I want to write to the file
495:16
Speaker A
specifically as a list so I'm going to give this a list of name comma home which of course are the contents of those variables now I'm going to go ahead and save the file I'm going to go ahead and rerun python of students. hit
495:29
Speaker A
enter and what's your name well let me go ahead and type in Harry as my name and number four comma Private Drive enter now notice that input itself did have a comma and so if I go to my CSV file now
495:44
Speaker A
notice that it's automatically been quoted for me so that subsequent reads from this file don't confuse that comma with the actual comma between Harry and his home well let me go ahead and run it a couple of more times let me go ahead
495:56
Speaker A
and rerun python of students. py let me go ahead and input this time Ron and his home as the burrow let's go back to students. CSV to see what it looks like now we see Ron comma the burough has
496:08
Speaker A
been added automatically to the file and let's do one more python of students. enter let's go ahead and give draco's name and his home which would be Malfoy Manor enter and if we go back to students. CSV now we see that Draco is
496:22
Speaker A
in the file itself and the library took care of not only writing each of those rows per the function name it also handled the escaping so to speak of any strings that themselves contained a comma like Harry's own home well it
496:35
Speaker A
turns out there's yet another way we could implement this same program without having to worry about precisely that order again and again and just passing in a list it turns out if we're keeping track of what's the name and
496:46
Speaker A
what's the home we could use something like a dictionary to associate those keys with those values so let me go ahead and back up and remove these students from the file leaving only the header row again name comma home and let
496:57
Speaker A
me go over to students. py and this time instead of using CSV writer I'm going to go ahead and use CSV do dict writer which is a dictionary writer that's going to open the file in much the same
497:08
Speaker A
way but rather than write a row as this list of name comma home what I'm now going to do is follows I'm going to first uh output an actual dictionary the first key of which is Name colon and
497:22
Speaker A
then the value thereof is going to be the name that was typed in and I'm going to pass in a key of Home quote unquote the value of which of course is the home that was typed in but with dict writer I
497:31
Speaker A
do need to give it a hint as to the order in which those columns are when writing it out so that subsequently they could be read even if those orderings change let me go ahead and pass in field
497:43
Speaker A
names which is a second argument to dict writer equals and then a list of the actual columns that I know are in this file which of course are name comma home those times in quotes because that's indeed the string names of the column so
497:57
Speaker A
to speak that I intend to write to in that file all right now let me go ahead and go to my terminal window run python of students. py this time I'll type in Harry's name again I'll again type in
498:08
Speaker A
number four comma Private Drive enter let's now go back to students. CSV and voila Perry's back in the file and it's properly escaped or quoted I'm sure then if we do this again with Ron and the burrow and let's go ahead and run it one
498:24
Speaker A
third time with Draco and Malfoy Manor enter let's go back to students. CSV and Via this dictionary writer we now have all three of those students as well so whereas with CSV writer the onus is on us to pass in a list of all of the
498:41
Speaker A
values we want to put from left to right with a dictionary writer technically they could be in any order in the dictionary in fact I could just have correctly done this passing in home followed by name but it's a dictionary
498:54
Speaker A
and so the ordering in this case does not matter so long as the key is there and the value is there and because I have passed in field names as the second argument to dict writer it ensures that
499:04
Speaker A
the library knows exactly which column contains name or home respectively are there any questions now on dictionary reading dictionary writing or csvs more generally inia any specific specific situation for me to use single quotation or double quotation because uh after the
499:26
Speaker A
print we use single quotation to represent the key of the dictionary but after the reading or writing we use the double quotation it's a a good question in Python you can generally use double quotes or you can use single quotes and
499:44
Speaker A
it doesn't matter you should just be self-consistent so that stylistically your code looks the same all throughout sometimes though it is necessary to alternate if you're already using double quotes as I was earlier for a long f string but inside that F string I was
499:59
Speaker A
interpolating the values of some variables using curly braces and those variables were dictionaries and in order to index into a dictionary you use square brackets and then quotes but if you're already using double quotes out here you should generally use single
500:14
Speaker A
quotes here or vice versa but otherwise I'm in the habit of using double quotes everywhere others are in the habit of using single quotes everywhere it only matters sometimes if one might be confused for the other other questions on dictionary writing or
500:31
Speaker A
reading uh yeah d uh my question is can we use multiple CSV files in any program absolutely you can use as many CSV files as you want and it's just one of the formats that you can use to save data
500:45
Speaker A
other questions on csvs or file IO thanks for taking my question uh so when you're reading from the file the um you had the um uh as a as a dictionary you had the fields called um couldn't you
501:00
Speaker A
just call when you're reading could couldn't you just call the row in the previous version of the of the students uh P file um when you're reading the uh when you're reading each row you are splitting out the um the fields by
501:17
Speaker A
name yeah so when you're pending to the uh to the students list can you just call the uh for row and reader students.
501:24
Speaker A
append row rather than uh rather than naming each of the fields oh very clever uh short answer yes in so far as dict reader returns one dictionary at a time when you Loop over it row is already going to be a dictionary so yes you
501:43
Speaker A
could actually get away with doing this and the effect would really be the same in this case good observation how about one more question on csvs yeah uh when reading in csvs from my past work with data a lot of things
501:59
Speaker A
can go wrong I don't know if it's a fair question that you can answer in a few sentences but are there any best practices to double check that sort of no mistakes occurred it's a really good question and I would say in general if
502:15
Speaker A
you're using code to generate the csvs and to read the csvs and you're using a good Library theoretically nothing should go wrong it should be 100% correct if the libraries are 100% correct uh you and I tend to be the
502:30
Speaker A
problem like when you let a human touch the CSV or when Excel or apple numbers or some other tools involve that might not be aligned with your codes expectations things then yes can break um the goal really sometimes honestly
502:43
Speaker A
the solution is manual fixes you go in and fix the CSV or you have a lot of error checking or you have a lot of try except just to tolerate mistakes in the data but generally I would say if you're
502:53
Speaker A
using CSV or any file format internally to a program to both read and write it you shouldn't have concerns there you and I the humans are the problem generally speaking and not the programmers the users of those files
503:05
Speaker A
instead all right allow me to propose that we leave csvs behind but to note that they're not the only file format you can use in order to read or write data in fact they're a popular format as is just raw text files. txt files but
503:19
Speaker A
you can store data really any way that you want we've just picked csvs because it's representative of how you might read and write from a file and do so in a structured way where you can somehow have multiple Keys multiple values all
503:32
Speaker A
in the same file without having to resort to what would be otherwise known as a binary file so a binary file is a file that's really just zeros and ones and they can be laid out in any pattern
503:42
Speaker A
you might want particularly if you want to store not textual information but maybe graphical or audio or video information as well so it turns out that python is really good when it comes to having libraries for really everything
503:56
Speaker A
and in fact there's a popular Library called pillow that allows you to navigate image files as well and to perform operations on image files you can apply filters aot Instagram you can uh animate them as well and so what I
504:10
Speaker A
thought we'd do is leave behind text files for now and Tackle one more demonstration this time focusing on uh this particular library and image files instead so let me propose that we go over here to VSS code and create a
504:24
Speaker A
program ultimately that creates an anim GIF these things are everywhere nowadays in the form of memes and animations and stickers and the like and an animated gif is really just an image file that has multiple images inside of it and
504:38
Speaker A
your computer or your phone shows you those images one after another sometimes on an endless loop again and again and so long as there's enough images it creates the illusion of Animation because your mind and mind kind of fills
504:51
Speaker A
in the gaps visually and just assumes that if something is moving even though you're only seeing one frame per second or some sequence thereof it looks like an animation so it's like a simplistic version of a video file well let me
505:04
Speaker A
propose that we start with maybe a couple of uh costumes from another popular programming language and let me go ahead and open up my first costume here number one so suppose here that this is a costume or really just a
505:16
Speaker A
static image here costume 1.f and it's just a static picture of a cat no movement at all let me go ahead now and open up a second one costume 2.gif that looks a little bit different notice and I'll go back and forth this cat's legs
505:31
Speaker A
are a little bit aligned differently so that this was version one and this was version two now these cats come from a programming language from MIT called scratch that allows you very graphically to animate all this and more but we'll
505:44
Speaker A
use just these two static images costume one and costume 2 to create our own animated gif that after this you could text to a friend or message them um much like any meme online well let me propose that we create this animated gif not by
506:00
Speaker A
just using some off-the-shelf program that we downloaded but by writing our own code let me go ahead and run code of costumes. and create our very own program that's going to take as input two or even more image files and then
506:13
Speaker A
generate an animated gif from them by essentially creating this animated gif by toggling back and forth endlessly between those two images well how am I going to do this well let's assume that this will be a program called costumes.
506:27
Speaker A
that expects uh two command line arguments the names of the files the individual costumes that we want to animate back and forth so to do that I'm going to import CIS so that we ultimately have access to cis.org V I'm
506:39
Speaker A
then from this pillow Library going to import support for images specifically so from pil import image capital i as per the library's documentation now I'm going to give myself an empty list called images just so I have a list in
506:53
Speaker A
which to store one or two or or more of these images and now let me do this for each argument in cy. argv I'm going to go ahead and create a new image variable set it equal to this image uh doop
507:09
Speaker A
function passing in ARG now what is this doing I proposing that eventually I want to be able to run python of costumes.
507:17
Speaker A
piy and then as command line argument specify costume 1.f space costume 2. so I want to take in those file names from the command line as my arguments so what am I doing here well I'm iterating over sis. argv all of the words in my command
507:32
Speaker A
line arguments I'm creating a variable called image and I'm passing to this function image. open from the pillow library that specific argument and that library is essentially going to open that image in a way that gives me a lot
507:44
Speaker A
of functionality for manipulating it like animating now I'm going to go ahead and uh pen to my images list that particular image and that's it so this Loop's purpose in life is just to iterate over the command line arguments
508:00
Speaker A
and open those images using this Library the last line is pretty s straightforward I'm going to say this I'm going to grab the first of those images which is going to be in my list at location zero and I'm going to save
508:12
Speaker A
it to disk that is I'm going to save this file now in the past when we use csvs or text files I had to do the file opening I had to do the file writing maybe even the closing I don't need to
508:23
Speaker A
do that with this Library the pillow library takes care of the opening the closing and the saving for me by just calling save I'm going to call this save function and just to leave space because I have a number of arguments to pass I'm
508:35
Speaker A
going to move to another line so it fits I'm going to pass in the name of the file that I want to create costume. GIF that will be the name of my animated gif I'm going to tell this library to save
508:47
Speaker A
all of the frames that I passed to it so the First costume the second costume and even more if I gave them I'm going to then append to this first image the images zero uh the following images equals this list of images and this is a
509:03
Speaker A
bit clever but I'm going to do this I want to append the next image there images one and now I want to specify a duration of 200 Mill seconds for each of these frames and I want this to Loop
509:15
Speaker A
forever and if you specify Loop equals zero that is Time Zero it means it's just not going to Loop an finite number of times but an infinite number of times instead and I need to do do one other
509:27
Speaker A
thing recall that sis. argv contains not just the words I typed after my program's name but what else does cy.
509:36
Speaker A
argv contain if you think back to our discussion of command line arguments what else is in sis. RGV besides the words I'm about to type like costume 1.f and costume 2 yeah so we'll actually get in the the original name of
509:52
Speaker A
the program we want to run the costume at p and we'll get the original name of the program costumes. in this case which is not a gif obviously so remember that using slices in Python we can do this if
510:05
Speaker A
cy. Arvy is a list and we want to get a slice of that list everything after the first element we can do one colon which says start at location one not zero and take a slice all the way to the end so
510:18
Speaker A
give me everything except the first thing in that list which to McKenzie's point is the name of the program now if I haven't made any mistakes let's see what happens I'm going to run python of costumes. piy and now I'm going to
510:30
Speaker A
specify the two images that I want to animate so costume 1.f and costume 2.if what is the code now going to do well to recap we're using the Cy library to access those command line arguments we're using the pillow library to treat
510:46
Speaker A
those files as images and with all the functionality that comes with that Library I'm using this images list just to accumulate all of these images one at a time from the command line and in lines 7 through n I'm just using a loop
510:59
Speaker A
to iterate over all of them and just add them to this list after opening them with the library and the last step which is really just one line of code broken on to three so that it all fits I'm
511:09
Speaker A
going to save the first image but I'm asking the library to append this other image to it as well not bracket zero but bracket one and if I had more I could express those as well I want to save all
511:20
Speaker A
of these files together I want to pause 200 milliseconds a fifth of a second in between each frame and I want it to Loop infinitely many times so now if I cross my fingers as always hit enter nothing
511:35
Speaker A
bad happened and that's almost always a good thing let me now run code of costumes. GIF to open up in VSS code the final image and what I think I should see is a very happy cat and indeed so
511:51
Speaker A
now we've seen not only that we can read and write files be it textually we can read and now write files that are binary zeros and ones we've just scratched the surface this is using the library called pillow but ultimately this is going to
512:03
Speaker A
give us the ability to read and write files however we want so we've now seen that via file.io we can manipulate not just textual files be it txt files or csvs but even binary files as well in this case they happen to be images but
512:16
Speaker A
if we dived in deeper we could find explore audio and video and so much more all by way of these simple Primitives this ability somehow to read and write files that's that's it for now we'll see you next time
512:35
Speaker A
[Music] [Music] all right this is cs50's Introduction to programming with python my name is David men and this is our week on regular Expressions so a regular expression otherwise known as a Rex is really just a pattern and indeed it's quite common
513:10
Speaker A
in programming to want to use patterns to match on some kind of data often user input for instance if the user types in an email address whether to your program or a website or an app on your phone you
513:21
Speaker A
might ideally want to be able to validate that they did indeed type in an email address and not something compl completely different so using regular Expressions we're going to have the new found capability to Define patterns in our code to compare them against data
513:34
Speaker A
that we're receiving from someone else whether it's just a validated or heck even if we want to clean up a whole lot of data that itself might be messy because it too came from us humans before though we use these regular
513:45
Speaker A
Expressions let me propose that we solve a few problems using just some simpler syntax and see what kind of limitations we run up against let me propose that I open up via code here and let me create a file called validate dopy the goal at
514:00
Speaker A
hand being to validate how about just that a user's email address they've come to your app they've come to your website they type in their email address and we want to say yes or no this email address looks valid all right let me go ahead
514:11
Speaker A
and type code of validate dopy to create a new tab here and then within this tab let me go ahead and start writing some code how about that keeps things simple initially first let me go ahead and prompt the user for their email address
514:25
Speaker A
and I'll store return value of input in a variable called email asking them what's your email question mark I'm going to go ahead and preemptively at least clean up the user's input a little bit by minimally just calling strip at
514:39
Speaker A
the end of my call to input because recall that input returns a string or a stir stirs come with some built-in methods or functions one of which is strip which has the effect of stripping off any leading white space to the left
514:52
Speaker A
or any trailing white space to the right so that's just going to go ahead and at least avoid the human having accidentally typed in a space character we're going to throw it away just in case now I'm going to do something
515:03
Speaker A
simple for a user's input to be an email address I think we can all agree that it's got to minimally have an at sign somewhere in it so let's start simple if the user has typed in something with an
515:14
Speaker A
at sign let's very generously just say Okay valid looks like an email address and if we're missing that at sign let's say invalid because clearly it's not an email address it's not going to be the best version of my code yet but we'll
515:26
Speaker A
start simple so I'm going to ask the question if there is an at symbol in the user's email address go ahead and print out for instance quote unquote valid else if there's not now I'm pretty confident that the email address is in
515:39
Speaker A
fact invalid now what is this code doing well if at sign in email is a pythonic way of asking is this string quote unquote at in this other string email no matter where it is at the beginning the
515:53
Speaker A
middle of the end it's going to automatically SE search through the entire string for you automatically I could do this more verbosely and I could use a for Loop or a while loop and look at every character in The user's email
516:04
Speaker A
address looking to see if it's an at sign but this is one of the things that's nice about python you can do more with less so just by saying if at quote unquote in email we're achieving that same result we're going to get back true
516:16
Speaker A
if it's somewhere in there thus valid or false if it is not well let me go ahead now and run this program in my terminal window with python of validate dopy and I'm going to go head and give it my
516:26
Speaker A
email address maen harvard.edu enter and indeed it's valid looks valid is valid but of course this program is technically broken it's buggy what would be an example input if someone might like to volunteer and answer here that would be considered valid but you and I
516:43
Speaker A
know it really isn't valid yeah thank you uh well for instance you can type just two science science and that's it and it still be valid still be valid according to your program but this exactly we've set a very low bar here in
516:59
Speaker A
fact if I go ahead and rerun python of validate dopy and I'll just type in one at sign that's it no username no domain name this doesn't really look like an email address but unfortunately my code thinks it in fact is because it's
517:10
Speaker A
obviously just looking for an at sign alone well how could we improve this well minimally an email address I I think tends to have though this is not actually a requirement tends to have an at sign and a single dot at least maybe
517:22
Speaker A
somewhere in the domain name so mailin Harvard Dot edu so let's check for that dot as well though again strictly speaking doesn't even have to be that case but I'm going for my own email address at least for now as our test
517:34
Speaker A
case so let me go ahead and change my code now and say not only if at is an email but also uh dot is an email as well so I'm asking now two questions I have two Boolean Expressions if at an
517:47
Speaker A
email and I'm anding them together logically this is a logical and so to speak so if it's the case that at is an email and Dot is an email okay now I'm going to go ahead and say valid all
517:59
Speaker A
right this would still seem to work for my email address let me go ahead and run python of validate dopy uh maen harvard.edu enter and that of course is valid as expected but here too we can be a little adversarial and type in
518:11
Speaker A
something nonsensical like at Dot and unfortunately that too is going to be mistaken as valid even though there's still no username domain name or anything like that so I think we need to be a little more methodical here in fact
518:24
Speaker A
notice that if if I do this like this uh the at sign can be anywhere and the dot can be anywhere but if I'm assuming the user is going to have a traditional domain name like harvard.edu or gmail.com I really want to look for the
518:39
Speaker A
dot in the domain name only not necessarily just the username so let me go ahead and do this let me go ahead and introduce a bit more logic here and instead do this let me go ahead and do
518:52
Speaker A
uh email.it of quote unquote at sign so email again is a string or a stir stirs come with methods not just strip but also another one called split that is the name applies will split one stir into multiple ones if you give it a
519:07
Speaker A
character or more to split on so this is hopefully going to return to me two parts from a traditional email address the username and the domain name and it turns out I can unpack that sequence of respon is by doing this username comma
519:22
Speaker A
domain equals this I could store it in a list or some other structure but if I already know in advance what kinds of values I'm expecting a username and hopefully a domain I'm going to go ahead and do it like this instead and just
519:34
Speaker A
Define two variables at once on one line of code and now I'm going to be a little more precise if username uh uh if username then I'm going to go ahead and say print valid else I'm going to go ahead and say print
519:50
Speaker A
invalid now this isn't good enough but I'm at least checking for the presence of a username now and you might not have seen this before but if you simply ask a question like if username and username is a string well usern if username is
520:02
Speaker A
going to give me a true answer if username is anything except none or quote unquote nothing so there's a truthy value here whereby if username has at least one character that's going to be considered true but if username
520:16
Speaker A
has no characters it's going to be considered a false value effectively but this isn't good enough I don't want to just check for username I want to also check that it's the case that dot is in the domain name as well so notice here
520:30
Speaker A
there's a bit of potential confusion with the English language here I seem to be saying if username and Dot in domain as though I'm asking the question if the username and the dot are in the domain but that's not what this means these are
520:44
Speaker A
two separate Boolean Expressions if username and separately if dot in domain and if I parenthesize this we could make that even more clear by putting parenthesis there parentheses here so just to be clear it's really two Boolean Expressions that we're anding together
521:00
Speaker A
not one longer english-like sentence now if I go ahead and run this python of validate dopy enter I'll do my own email address again maen harvard.edu and that's valid and it looks like I could tolerate something like this if I do
521:16
Speaker A
mailin at just say Harvard I think at the moment this is going to be invalid now maybe the top level domain Harvard exists but at the moment it looks like we're looking for something more we're looking for a top level domain too like
521:29
Speaker A
edu so for now we'll just consider this to be invalid but it's not just that we want to do it's not just that we want to check for the presence of a username and the presence of a dot let's be more
521:41
Speaker A
specific let's start to now narrow the scope of this program not just to be about generic emails more generally but about edu addresses so specifically for someone in a US University for instance whose email address tends to end with
521:53
Speaker A
doedu I can be a little more precise and you might recall this function already instead of just saying is there a DOT somewhere in domain let me instead say and the domain ends with quote unquote.
522:06
Speaker A
edu so now we're being even more precise we want there to be minimally a username that's not empty it's not just quote unquote nothing and we want the domain name to actually end with doedu let me go ahead and run python of validate dopy
522:20
Speaker A
and just to make sure I haven't made things even worse let me at least chest my own email address which does seem to be valid now it seems that I minimally need to provide a username because we definitely do have that check in place
522:30
Speaker A
so I'm going to go ahead and say Ma and now I'm going to go ahead and say at and it looks like I could be a little malicious here just say mailen at.edu as though minimally meeting the requirements of this of this pattern and
522:43
Speaker A
that of course is considered valid but I'm pretty sure there's no one at mail at.edu we need to have some domain name in there so we're still not being quite as generous now we could absolutely continue to iter at on this program and
522:56
Speaker A
we could add some more Boolean Expressions we could maybe use some other python methods for checking more precisely as there's something to the left of the dot to the right of the dot we could use split multiple times but
523:06
Speaker A
honestly this just escalates quickly like you end up having to write a lot of code just to express something that's relatively simple in spirit just format this like an email address so how can we go about improving this well it turns
523:20
Speaker A
out in Python there's a library for regular Expressions it's called ccin re and in the re Library you have a lot of capabilities to Define and check for and even replace patterns again a regular expression is a pattern and this Library
523:37
Speaker A
the re library in Python is going to let us to Define some of these patterns like a pattern for an email address and then use some built-in functions to actually validate a user's input against that pattern or even use these patterns to
523:48
Speaker A
change the user's input or extract partial information there from we'll see examples of all this and more so what can should I do with this Library well first and foremost it comes with a lot of functionality here is the URL for
523:59
Speaker A
instance to the official documentation and let me propose that we focus on using one of the most versatile functions in the library library namely this search re. search is the name of the function in the re module that
524:13
Speaker A
allows you to pass in a few arguments the first is going to be a pattern that you want to search for in for instance a string that came from a user the string arguments here is going to be the actual
524:23
Speaker A
string that you want to search for that pattern and then there's a third argument optionally that's a whole bunch of flags a flag in general is like a a parameter you can pass in to modify the behavior of the function but initially
524:34
Speaker A
we're not even going to use this we're just going to pass in a couple of arguments instead so let me go ahead and employ this re Library this regular expression library and just improve on this design incrementally so we're not
524:47
Speaker A
going to solve this problem all at once but we'll take some incremental steps I'm going to go back to VSS code here and I'm going to go ahead now and get rid of most of this code but I'm going
524:57
Speaker A
to go into the top of my file and first and all import this re Library so import re gives me access to that function and more now after I've gotten the user's input in the same way as before
525:08
Speaker A
stripping off any leading or trailing whites space I'm just going to use this function super trivially for now even though this isn't really a big step forward I'm going to say if re. search contains quote unquote at in the email
525:23
Speaker A
address then let's go ahead and print valid else let's go ahead and print invalid at the moment this is really no better than my very first version where I was just asking python if at sign in the email
525:35
Speaker A
address but now I'm at least beginning to use this Library by using its own re.
525:40
Speaker A
search function which for now you can assume returns a a True Value effectively if indeed the at sign is an email just to make sure that this version does work as I expect let me go ahead and run python of validate dopy
525:54
Speaker A
and enter I'll type in in my actual email address and we're back in business but of course this is not great because if I similarly run this version of the program and just type in an at sign not
526:05
Speaker A
an email address and yet my code of course thinks it is valid so how can I do better than this well we need a bit more vocabulary in the realm of regular expressions in order to be able to
526:16
Speaker A
express ourselves a little more precisely really the pattern I want to ultimately Define is going to be something like I want there to be something to the left then an sign then something to the right and that something to the right should end with
526:30
Speaker A
edu but should also have something before the edu like Harvard or Yale or any other school in the US as well well how can I go about doing this well it turns out that in the world of regular
526:41
Speaker A
Expressions whether in python or a lot of other languages as well there's certain symbols that you can use to define patterns at the moment I've just used literal raw text if I go back to my code here this technically qualifies as
526:54
Speaker A
a regular expression I've passed in a quoted string inside of which is an at sign now that's not a very interesting pattern it's just an at sign but it turns out that once you have access to regular expressions or a library that
527:07
Speaker A
offers that feature you can more powerfully express yourself as follows let me reveal that the pattern that you passed to ar. search can take a whole bunch of special symbols and here's just some of them in the examples we're about
527:20
Speaker A
to see in the patterns we're about to Define here are the special symbols you can use a single period a DOT to just represent any character except a new line a blank line so that is to say if I
527:32
Speaker A
don't really care what letters of the alphabet are in the user's username I just want there to be one or more characters uh in the user's name dot allows me to express a through z uppercase and lowercase and a bunch of
527:44
Speaker A
other letters as well star is going to mean in single asterisk zero or more repetitions so if I say something star that means that I'm willing to accept either zero repetitions that is nothing at all or more repetitions one or two or
528:00
Speaker A
three or 300 if you see a plus in my patterns that's going to mean one or more repetitions that is to say there's got to be at least one character there one symbol and then there's optionally more after that and then you can say
528:13
Speaker A
zero or one repetition you can use a single question mark after a symbol and that will say I want zero of this character or one but that's all I'll expect and then lastly there's going to be a to specify a specific number of
528:27
Speaker A
symbols if you use these curly braces and a number represented here symbolically as M you can specify that you want M repetitions be it one or two or three or 300 you can specify the number of repetitions yourself and if
528:38
Speaker A
you want a range of repetitions like you want this few characters or this many characters you can use curly braces and two numbers inside called here M and N which would be a range of M through n repetitions now what does all of this
528:52
Speaker A
mean well let me go back to vs code here and let me propose that we iterate on this solution further it's not sufficient to just check for the at sign we know that already we minimally want something to the left and to the right
529:04
Speaker A
so how can I represent that I don't really care what the user's username is or what letters of the alphabet are in it be it Ma or anyone else's so what I'm going to do to the left of this equal
529:14
Speaker A
sign is I'm going to use a single period the dot that again indicates any character except for a new line but I don't just want a single character otherwise the P person username could only be a at such and such or B at such
529:29
Speaker A
and such I want it to be multiple such characters so I'm going to initially use a star so dot star means give me something to the left and I'm going to do another one do star something to the
529:39
Speaker A
right now this isn't perfect but it's at least a step forward because now what I'm going to go ahead and do is this I'm going to rerun python to validate dopy I'm going to keep testing my own email
529:48
Speaker A
address just to make sure I haven't made things worse and that's now okay I'm now going to go ahead and type in some other input like how about just uh maen at with no domain name whatsoever and you
530:00
Speaker A
would think this is going to be invalid but but but it's still considered valid but why is that if I go back to this chart why is maen at with no domain now considered valid what's my mistake here
530:18
Speaker A
by having used doar at. Star as my regular expression or Rex because you're using the star instead of the plus sign exactly the star again means zero or more repetitions so r. search is perfectly happy to accept nothing after
530:34
Speaker A
the equ after the at sign because that would be zero repetitions so I think I minimally need to evolve this and go back to my code here and let me go ahead and change this from Star to plus and
530:45
Speaker A
let me change the ending from Star to plus so that now when I run my code here let me go ahead and run python of validate dopy I'm going to test my email address as always still working now let
530:57
Speaker A
me go ahead and type in that same thing from before that was accidentally considered valid now I hit enter finally it's invalid so now we're making some progress on being a little more precise as to what it is we're doing now I'll
531:10
Speaker A
note here like with almost everything in programming python included there's often multiple ways to solve the same problem and does anyone see away in my code here that I could make a slight tweak if I forgot that the plus operator
531:26
Speaker A
exists and go back to using a star if I allowed you only to use dots and only Stars could you recreate the notion of plus yes um use another dot dot dot star yeah because if a DOT means any
531:41
Speaker A
character we'll just use a DOT and then when you want to say or more use another Dot and then the star so equivalent to dot plus would have been dot dot star because the first dot means any character and the second pair of
531:54
Speaker A
characters Dot star means zero or more other characters and to be clear it does not have to be the same character just by doing Dot or dot star does not mean your whole username needs to be a or AA
532:05
Speaker A
or A AA or A A AA it can vary with each symbol it just means zero or more of any character back to back so I could do this on both the left and the right which one is better you know it depends
532:18
Speaker A
I think uh an argument could be made that this is even more clear because it's obvious now that there's a DOT which means any character and then there's the dot star but if you're in the habit of doing this frequently one
532:28
Speaker A
of the reasons things like the plus exist is just to consolidate your code into something a little more succinct and if you're familiar with seeing the plus now maybe this is more readable to you so again just like with python more
532:39
Speaker A
generally you're going to often see different ways to express the same patterns and reasonable people might agree or disagree as to which way is better than another well let me propose to that we can think about both of these
532:51
Speaker A
models a little more graphically if this looks a little cryptic to you let me go ahead and rewind to the previous incarnation of this regular expression which was just a single dot star this regular expression doar at dostar means
533:04
Speaker A
what again it means zero or more characters followed by a literal at sign followed by zero or more other characters now when you pass this pattern in as an argument to re. search it's going to read it from left to right
533:16
Speaker A
and then use it to try to match against the input email in this case that the user typed in now how is the computer how is r . search going to keep track of whether or not the user's email matches
533:29
Speaker A
this pattern well it turns out that it's going to be using a machine of sorts implemented in software known as a finite State machine or more formally a non-deterministic finite automaton and the way it works if we depict this
533:40
Speaker A
graphically is as follows the re. search function starts over here in a so-called start State that's the sort of condition in which it begins and then it's going to read the user's email address from left to right and it's going to decide
533:54
Speaker A
whether or not to stay in this first state or transition to the next state so for instance in this first state as the user reading my email address mailin at harvard.edu it's going to follow this curved edge up and around to itself a
534:08
Speaker A
reflexive Edge and it's labeled dot because dot again just means any character so as the function is reading my email address mailin at harvard.edu from left to right it's going to follow these transitions as follows m a l a n
534:25
Speaker A
and then it's hopefully going to follow this transition to the second state because there's a literal at sign both in this machine as well as in my email address then it's going to try to read the rest of my address h a r v a d do
534:41
Speaker A
du and that's it and then the computer's going to check did it end up in a an accept state a final State that's actually depicted here pictorially a little differently with double circles one inside of the other and that just
534:54
Speaker A
means that if the computer finds itself in that second accept state after having read all of the users input it is indeed a valid email address if by some chance the machine somehow ended up stuck in that first state which does not have
535:08
Speaker A
double circles and is therefore not an accept state the computer would conclude this is an invalid email address instead by contrast if we go back to my other version of the code where I instead had Plus on both the left and the right
535:22
Speaker A
recall that re. search is going to use one of these St machines in order to decide from left to right whether or not to accept the user's input like me harbor. edu can we get from the start state so to speak to an accept state to
535:35
Speaker A
decide Yep this was in fact meeting the pattern well let's propose that this non-deterministic finite automaton look like this instead we're going to start as before in the leftmost start State and we're going to necessarily consume one character per this first Edge which
535:50
Speaker A
is labeled with a DOT to indicate that we can consume any one character like the m in maen harvard.edu then we can spend some time consuming more characters before the at sign so the a l a n then we can consume the at sign then
536:05
Speaker A
we can consume at least one more character because recall that the Rex has dot plus this time and then we can consume even more characters if we want so if we first consume the H in harvard.edu that then leaves the a r v a
536:21
Speaker A
r d and then Dot e du and now here too we're at the end of the story but we're in an accept state because that circle at the end has two circles total which means that if the computer if this
536:35
Speaker A
function finds itself in that accept state after reading the entirety of the user's input it is too in fact a valid email address if by contrast we had gotten stuck in one of those other states unable to follow a transition one
536:49
Speaker A
of those edges and therefore unable to make progress in the user's input from left to right then we would have to conclude that that email address is in fact invalid well how can we go upon improving this code further let me
537:02
Speaker A
propose now that we check not only for a username and also something after the username like a domain name but minimally required that the string ends with doedu as well well I think I could do this fairly straightforward not only
537:14
Speaker A
do I want there to be something after the at sign like the domain like Harvard I want the whole thing to end with edu but there's a little bit of danger here what have I done wrong by implementing my regular expression now
537:29
Speaker A
in this way by using plus at. plus. edu what could go wrong with this version uh the dot is an dot means something else in this context where it means zero or more repetitions of a character which is why it will interpret
537:45
Speaker A
it differently exactly even though I mean for it to mean literally doedu a period and then edu unfortunately in the world of regular expression dot means any character which means that this string could technically end in a edu or
538:01
Speaker A
B edu or cedu and so forth but that's not in fact that I want so any instincts now as to how I could fix this problem and let me demonstrate the problem more clearly let me go ahead and run this
538:13
Speaker A
code here let me go ahead and type in maen harvard.edu and as always this does in fact work but Watch What Happens here let me go ahead and do Ma at Harvard and then uh M at Harvard question mark edu
538:28
Speaker A
enter that too is valid so I could put any character there and it's still going to be accepted but I don't want question mark edu I want edu literally any instincts then for how we can solve this problem here how can I get this new
538:42
Speaker A
function re. search and a regular expression more generally to literally mean a dot might you think can you use the uh Escape character the backslash indeed the so-called Escape character which we've seen before for outside of the context of regular Expressions when
538:56
Speaker A
we talked about new lines back sln was a way of telling the computer I want a new line but without actually literally hitting enter and moving the cursor yourself and you don't want a literal n on the screen so back sln was a way to
539:09
Speaker A
escape n and convey that you want a new line it turns out regular Expressions use a similar technique to solve this problem here in fact let me go into my regular expression and before that final dot let me put a single backslash in the
539:22
Speaker A
world of regular Expressions this is a so-called special special sequence and it indicates per this backslash and a single dot that I literally want to match on a DOT it's not that I want to match on any character and then edu I
539:34
Speaker A
want to match on a DOT or a period edu but we don't want python to misinterpret this backslash is beginning a an escape sequence something special like backs slash n which even though we as the programmer might type two characters
539:47
Speaker A
backs slash n it really is interpreted by python as a single new line we don't want any kind of misinterpretation like that here so it turns out there's one other thing we should do for regular expressions like this that have a
539:59
Speaker A
backslash used in this way I want to specify to python that I want this string this regular expression in double quotes to be treated as a raw string literally putting an r at the beginning of the string to indicate to python that
540:11
Speaker A
you should not try to interpret any backslashes in the usual way I want to literally pass the backslash and the dot and the edu into this particular function search in this case so it's similar in spirit to using that f at the
540:24
Speaker A
beginning of a format string which of course tells python to format the string in a certain way plugging in variables that might be between curly braces but in this case r indicates a raw string that I want passed in exactly as is now
540:38
Speaker A
it's only strictly necessary if you are in fact using backslashes to indicate that you want some special sequence like backs slash dot but in general it's probably a good habit to get into to just use raw strings for all of your
540:49
Speaker A
regular Expressions so that if you eventually go back in make a change make an addition you don't accident acally introduce a backslash and then forget that that might have some special or misinterpreted meaning well let me go ahead and try this new regular
541:02
Speaker A
expression I'll clear my terminal window run python of validate run python of validate dopy and then I'll type in my email address correctly mailen harvard.edu and that's fortunately still valid Let Me Clear My screen and run it one more time python of validate dopie
541:19
Speaker A
and this time let's mistype it as mailen Harvard questionmark edu where by there's obviously not a DOT there but there is some other Single Character that last time was misinterpreted as valid but this time now that I've improved my regular expression it's
541:35
Speaker A
discovered as indeed invalid any questions now on this technique for matching something to the left of the at sign something to the right and now ending with edu explicitly um what happens when that a good question and you kind of
541:52
Speaker A
called me out here well when in doubt let's try let me go ahead and do python validate dopy mailin harvard.edu which ALS so is incorrect unfortunately my code thinks it's valid so another problem to solve but a shortcoming for now other
542:10
Speaker A
questions on these regular Expressions thus far can you use curly brackets M instead of back can you use curly brackets instead of backslash not in this case if you want a literal dot backslash Dot is the way to do it
542:25
Speaker A
literally how about one other question on regular Expressions is this the same thing that Google forms uses in order to categorize data in let's say some if you've got multiple people sending in requests about some feedback do they
542:42
Speaker A
categorize the data that they get using this particular regular expression thing indeed if you've ever used Google forms to not just submit it but to create a Google form one of the menu options is for response validation in English at
542:55
Speaker A
least and what that allows you to do is specify that the user has to input an email address or a URL uh or a string of some length but there's an even more powerful feature that some of you may
543:06
Speaker A
not have ever noticed and indeed if you'd like to open up Google forms create a new form temporarily and poke around you will actually see in English at least quote unquote regular expression mentioned as one of the mechanisms you can use to validate your
543:19
Speaker A
users's input into your Google form so in fact after today you can start avoiding these specific dropdowns of like email address or URL or the like and you can express your own patterns precisely as well regular Expressions can even be used in VSS code itself if
543:35
Speaker A
you go and find or do a find and replace in VSS code you can of course just type in words like you could into Microsoft Word or Google Docs you can also type if you check the right box regular
543:46
Speaker A
expressions and start searching for patterns not literally specific values well let me propose that we now enhance this implementation further by introducing a few other symbols because right now with my code I keep saying that I want my email address to end with
544:03
Speaker A
edu and start with a username but I'm being a little too generous this does in fact work as expected for my own email address maen harvard.edu but what if I type in a sentence like my email address is maen harvard.edu and suppose I've
544:20
Speaker A
typed that into the program or I've typed that into a Google form is this going to be considered valid or invalid well let's consider it's got the at sign so we're good there it's got one or more characters to the left of the at
544:37
Speaker A
sign it's got one or more characters to the right of the at sign it's got a literal doedu somewhere in there to the right of the at sign and granted there's more stuff to the right there's literally this period at the end of my
544:51
Speaker A
English sentence but that's okay because at the moment my expression is not so precise as to say the pattern must start with the username and end with the doedu technically it's left unsaid what more can be to the left and what more can be
545:05
Speaker A
to the right so when I hit enter now you'll see that that whole sentence in English is valid and that's obviously not what you want in fact consider the case of using Google forms or Office 365 to collect data from users if you don't
545:18
Speaker A
validate your input your users might very well type in a full sentence or some else with a typographic IAL error not an actual email so if you're just trying to copy all of the results that have been typed into your form so you
545:29
Speaker A
can paste them into Gmail or some email program it's going to break because you're going to accidentally paste something like a whole English sentence into the program instead of just an email address which is what your mailer expects so how can I be more precise
545:42
Speaker A
well let me propose we introduce a few more symbols as well it turns out in the context of a regular expression one of these patterns you can use the carrot symbol the little triangular Mark to repres presentent that you want this
545:55
Speaker A
pattern to match the start of the string specifically not anywhere but the start of the user string by contrast you can use a dollar sign in your regular expression to say that you want to match the end of the string or technically
546:08
Speaker A
just before the new line at the end of the string but for all intents and purposes think of carrot as meaning start of the string and dollar sign as meaning end of the string it is a weird thing that one is a carrot and one is a
546:21
Speaker A
dollar sign these are not really things that I think of as opposites like a parenthesis or something like that but those are the symbols the world chose many years ago so let me go back to VSS code now and let me add this feature to
546:32
Speaker A
my code here let me specify that yes I do want to search for this pattern but I want the user's input to start with this pattern and end with this pattern so even though it's going to start looking
546:43
Speaker A
even more cryptic I put a carrot symbol here at the beginning and I put a dollar sign here at the end that does not mean I want the user to type a carrot symbol or a dollar sign this is special
546:54
Speaker A
symbology that indicates to re. search that it should only look for now an exact match against this pattern so if I now go back to my terminal window and I'll leave the previous result on the screen let me type the exact same thing
547:07
Speaker A
my email address is ma at harvard.edu enter sorry period and now I'm going to go ahead and hit enter now that's considered invalid but let me clear the screen and just to make sure I didn't break things let me type in just my
547:22
Speaker A
email address and that two is valid any questions now on this version of my regular expression which note goes further to specify even more precisely that I want it to match at the start and the end any questions on this one here okay
547:41
Speaker A
you have slash and do edu and then the dollar sign but the dot is like one of the regular expression right it normally is but this backslash that I Deli put before this period here is an escape character it is a way of telling re.
548:00
Speaker A
search that I don't want any character there I literally want a period there and it's the only way you can distinguish one from the other if I got rid of that slash this would mean that the email address just has to end with
548:13
Speaker A
any character then an e then a d then a u i don't want that I want literally a period Then the E then the D then the U this is actually common convention in programming and technology in general if
548:26
Speaker A
you and I decide on a convention whereby we're using some character on the keyboard to mean something special invariably we create a future problem for oursel when we want to literally use that same character and so the solution
548:38
Speaker A
in general to that problem is to somehow escape the character so that it's clear to the computer that it's not that special symbol it's literally the symbol it sees so we don't even love it we don't need another another slash before
548:51
Speaker A
the dollar sign no uh because in this case dollar sign means something special per this chart here dollar sign by itself does not mean US dollars or currency it literally means match the end of the string if however I wanted
549:07
Speaker A
the user to literally type in a dollar sign at the end of their input the solution would be the same I would put a backslash before the dollar sign which means my email address would have to be something like mait harvard.edu dollar
549:21
Speaker A
sign which is obviously not correct too so back slashes just allow you to tell the computer to not treat those symbols specially like meaning something special but to treat them literally instead how about one other question here on regular
549:35
Speaker A
Expressions you said you said one represents to to make it one plus then you say one was to make it one with nothing sure so let me rewind in time I think what you're referring to was one of our earlier versions that initially
549:49
Speaker A
looked like this which just meant Zero or more characters then an at sign than zero or more other characters we then evolved that to be this Plus on both sides which means one or more characters on the left then an at sign then one or
550:05
Speaker A
more characters on the right and if I'm interpreting your question correctly one of the points I made earlier was that if you didn't use Plus or forgot that it exists you could equivalently achieve the exact same result with two dots and
550:17
Speaker A
a star because the first dot means any character it's got to be there the second dot star means zero or more other characters and same on the right so it's just another way of expressing the same idea one or more can be represented like
550:32
Speaker A
this with do do star or you can just use the handier syntax of plus which means the same thing all right so I dare say there's still some problems with the regular expression in this current form because even though now we're starting
550:45
Speaker A
to look for the username at the beginning of the string from the user and we're looking for the edu literally at the end of the string from the user those dots are a little too encompassing right now I am allowed to type in more
550:57
Speaker A
than the single at sign why because at is a character and Dot means any character so honestly I can have as many at signs as this thing at the moment as I want for instance if I run python of
551:08
Speaker A
validate dopy mailin harvard.edu still works as expected but if I also run python to validate dopy and incorrectly do maen harvard.edu that should be invalid but it's considered valid instead so I I think we need to be a
551:24
Speaker A
little more restrictive when it comes to that dot and we can't just say oh any old character there is fine we need to be more specific well it turns out that regular Expressions also support this syntax you can use square brackets
551:39
Speaker A
inside of your pattern and inside of those square brackets include one or more characters that you want to look for specifically alternatively you can inside of those square brackets put a car symbol which unfortunately in this context means something completely
551:57
Speaker A
different from match the start of the string but this would be the compliment operator inside of these square brackets which means you cannot match any of these characters so things are about to look even more cryptic now but that's
552:09
Speaker A
why we're focusing on regular Expressions on their own here if I don't want to allow any character which is what a DOT is let me go ahead and I could just say well I only want to support a or B's or C's or D's or E's or
552:25
Speaker A
FS or G's I could type in the whole alphabet here plus some numbers to actually include all of the letters that I do want to allow but honestly a little simpler would be this I could use a carrot symbol and then an at sign which
552:39
Speaker A
has the effect of saying this is the set of characters that has everything except an at sign and I can do the same thing over here instead of a DOT to the right of the at sign I can do Open Bracket
552:53
Speaker A
carrot at sign and I admit things are starting to escalate quickly here but let's start from the left and go to the right this carrot outside of the square brackets at the very start of my string as before means match from the start of
553:07
Speaker A
the string and let's Jump Ahead the dollar sign all the way at the end of the regular expression means match at the end of the string so if we can mentally tick those off as straightforward let's now focus on
553:18
Speaker A
everything else in the middle well to the left here we have new syntax a square bracket another carrot an at sign and a Clos square bracket and then a plus the plus means the same thing as always it means one or more of the
553:34
Speaker A
things to the left what is the thing to the left well this is the new syntax inside of square brackets here I have a carrot symbol and then an at sign that just means any character except an at
553:46
Speaker A
sign it's a weird syntax but this is how we can express that simple idea any character on the keyboard EX except for an at sign and heck even other characters that aren't physically on your keyboard but that nonetheless exist
554:00
Speaker A
then we have a literal at sign then we have another one of these same things square bracket carrot at close bracket which means any character except an at sign then one or more of those things followed by literally a period
554:14
Speaker A
U so now let me go ahead and do this again let me rerun python of validate dopy and test my own email address to make sure I've not made things work and we're good now let me go ahead and clear
554:25
Speaker A
my screen and run python of validate dopy again and do mailin harvard.edu crossing my fingers this time and finally this now is invalid why I'm allowing myself to have one at sign in the middle of the user's input but everything to the left per
554:42
Speaker A
this new syntax cannot be an at sign it can be anything but one or more times and everything to the right of the at sign can be anything but an at sign one or more time followed by lastly a
554:55
Speaker A
literal. edu so again the new syntax is quite simply this square brackets allow you to specify a set of characters that you literally type out at your keyboard a bcde e f or the complement the opposite the carrot symbol which means
555:10
Speaker A
not and then the one or more symbols you want to exclude questions now on this syntax here so right after add sign can we use the curly brackets M uh one so that we can only have one repetition of the ad
555:24
Speaker A
symbol absolutely so we could do this let me go ahead and pull a VSS code and let me delete the current form of a regular expression and go back to where we began which was justar at and star I
555:36
Speaker A
could absolutely do something like this and require that I want at least one of any character here and then I could do something more to have any more as well so the curly brace syntax which we saw on the slide earlier but didn't yet use
555:49
Speaker A
absolutely can be used to specify a specific number of characters but honestly this is more verbose than is necessary the best solution arguably or the simplest at least ultimately is just to say do plus but there too another
556:02
Speaker A
example of how you can solve the same problem multiple ways let me go back to where the regular expression just was and take other questions as well questions on these sets of characters or complimenting that set so can you use
556:18
Speaker A
that same syntax to say that you don't want a certain character throughout the whole stream you could it's going to be uh you could absolutely use the same character to exclude a um you could absolutely use the syntax to exclude a certain
556:33
Speaker A
character from the entire string but it would be a little harder right now because we're still requiring edu at the end but yes absolutely other questions what happens if the user inputs edu in the beginning of the thinging a good question what
556:51
Speaker A
happens if the user types in doedu the beginning of the screen well let me go back to VSS code here and let's try to solve this in two different ways first let's look at the regular expression and see if we can infer if that's going to
557:02
Speaker A
be tolerated well according to the current cryptic regular expression I'm saying that you can have any character except the at sign so that would work I could have the dot for the edu but then I have to have an at sign so that
557:17
Speaker A
wouldn't really work because if I'm just typing in.edu we're not going to pass that constraint so now let me try this in uh by running the program let me type in just literally doedu that doesn't work but but but I could do this doedu
557:33
Speaker A
at.edu that too is invalid but let me do this uhedu at something. edu that passes so it's starting to get a little weird now maybe it's valid maybe it's not but I think we'll eventually be more precise too how about one more question on this
557:52
Speaker A
regular expression and these complimenting of sets can we use uh another domain name as a string input can you use another domain name absolutely I'm using my own just for the sake of demonstration but you could absolutely use any domain or top level
558:07
Speaker A
domain and I'm using doedu which is very us-centric but this would absolutely work exactly the same for any top level domain all right let me go ahead now and propose that we improve this regular expression further because if I pull it
558:21
Speaker A
up again in V vs code here you'll see that I'm being a little too tolerant still it turns out that there are certain requirements for someone's username and domain name in an email address there is an official standard in
558:34
Speaker A
the world for what an email address can be and what characters can be in it and this is way to accommodating of all the characters in the world except for the at symbol so let's actually narrow the definition of what we're going to
558:46
Speaker A
tolerate in usernames and companies like Gmail could certainly do this as well suppose that it's not just that I want to exclude at sign suppose that I only want to allow for say characters that normally appear in words like letters of
559:00
Speaker A
the alphabet A through Z be it uppercase or lowercase maybe some numbers in heck maybe even an underscore could be allowed too well we can use this same square bracket syntax to specify a set of characters as follows I could do a b
559:14
Speaker A
c d e f g h i j oh my God this is going to take forever I'm going to have to type out all 26 letters of the alphabet both lowercase and uppercase so let me stop doing that there's a better way
559:25
Speaker A
already if you want to specify Within These square brackets a range of letters you can actually just do a hyphen if you literally do a hyphen Z in these square brackets the computer is going to know you mean a thusy you do not need to type
559:40
Speaker A
26 letters of the alphabet if you want to include uppercase letters as well you just do the same no spaces no commas you literally just keep typing a through capital Z so I have little a hyphen little Z big a hyphen big Z no spaces no
559:57
Speaker A
commas no separators you just keep specifying those ranges if I additionally want numbers I could do 0 1 2 3 4 NOP you don't need to type in all 10 decimal digits you can just say 0 through n using a hyphen as well and if
560:11
Speaker A
you now want to support underscores as well which is pretty common in usernames for email addresses you can literally just type in underscore at the at the end notice that all of these characters are in inside of square brackets which
560:25
Speaker A
just again means here is a set of characters that I want to allow I have not used a carrot symbol at the beginning of this whole thing because I don't want to complement it complement it with an E not complement it with an i
560:39
Speaker A
I want don't want to complement it by making it the opposite I literally want to accept only these characters I'm going to go ahead and do the same thing on the right if I want to require that the domain name similarly come from this
560:52
Speaker A
set of characters which admittedly is a little too narrow but it's familiar for now so we'll keep it simple I'm going to go ahead and paste that exact same set of characters over there to the right and so now it's much more restrictive
561:06
Speaker A
now I'm going to go ahead and run python of validate I'm going to test my own email address and we're still good I'm going to clear my screen and run it once more this time trying to break it let me
561:17
Speaker A
go ahead and do something like how about davidor maen harvard. e do you enter but that too is going to be valid but if I do something completely wrong again like ma harvard.edu that's still going to be invalid why because my regular
561:36
Speaker A
expression currently only allows for a single at in the middle because everything to the left must be alpha numeric alphabetical or numeric or an underscore the same thing to the right followed by the edu now honestly this is
561:52
Speaker A
a regular expression that you might be in the habit of typing in the real world as in as cryptic as this might look this is the world of regular Expressions so you'll get more comfortable with this syntax over time but thankfully some of
562:04
Speaker A
these patterns are so common that there are builtin shortcuts for representing some of the same information that is to say you don't have to constantly type out all of the symbols that you want to include because odds are some other
562:16
Speaker A
programmer has had the same problem so built into regular Expressions themselves are some additional patterns you use and in fact I can go ahead and get rid of this entire set a through z lowercase A through Z uppercase 0
562:30
Speaker A
through 9 and an underscore and just replace it with a single back slw back slw in this case represents a word character which is commonly known as a alpha numeric symbol or the underscore as well I'm going to do the same thing
562:47
Speaker A
over here I'm going to highlight the entire set of square brackets delete it and replace it with a single backs slash W and now I feel like we're making progress because even though it's cryptic and what if it looked way
562:58
Speaker A
cryptic a little bit ago um and even though it would have looked even more cryptic a little bit ago now it's at least starting to read a little more friendly the carrot on the left means start matching at the beginning of the
563:10
Speaker A
string back slw means any word character the plus means one or more at symbol literally then another word character one or more then a literal dot then literally EDU U and then match at the very end of the string and that's it so
563:26
Speaker A
there's more of these two and we won't use them all here but here is a partial list of the patterns you can use within a regular expression one you have back SL D for any decimal digit decimal digit
563:39
Speaker A
meaning 0 through n commonly done here too is if you want to do the opposite of that the complement so to speak you can do back slash capital D which is anything that's not a decimal digit so it might be letter and punctuation and
563:54
Speaker A
other symbols as well Meanwhile Back SLS means Whit space characters like a single hit of the space or maybe hitting tab on the keyboard that's whites space back slash capital S is the opposite or complement of that anything that's not a
564:09
Speaker A
whit space character back slw we've seen a word character as well as numbers and the underscore and if you want the complement or opposite of that you can use back SL capital W to give you everything but a word character
564:23
Speaker A
again these are just common patterns that so many people were presumably using in yester year that it's now baked into the regular expression syntax so that you can more succinctly express your same ideas any questions then on this approach here where we're now using
564:40
Speaker A
backw to represent my word character uh so what I want to ask about uh was the uh actually the previous approach like the square bracket approach could we accept like uh lists in there yes we'll see this before long
564:54
Speaker A
but suppose you wanted to tolerate not just edu but maybe edu or do you could do this you could introduce parentheses and then you can or those together I could say Comm or edu I could also add in something like in the US or gov or
565:11
Speaker A
net or anything else or org or the like and each of the vertical bars here means something special it means or and the parentheses simply group things together formally you have this syntax here A or B A or vertical Bar B means a has
565:27
Speaker A
to match or B has to match where A and B can be any other patterns you want in parentheses you can group those things together so just like math you can uh combine ideas into one phrase and do
565:38
Speaker A
this thing or the other um and there's other syntax as well that we'll soon see other questions on these regular expressions in this syntax here what if we put spaces in the expression sure so if you want spaces in there you can't
565:52
Speaker A
use back slw alone because that is only a word character which is alphabetical numerical or the underscore but you could do this you could go back to this approach whereby you use uh square brackets and you could say A through Z
566:05
Speaker A
or a through z or 0 through n or underscore or I'm going to hit the space bar a single space you can put a literal space inside of the square brackets which will allow you then to detect a
566:17
Speaker A
space alternatively I could still use back slw but I could combine it as follows I could say give me a back slw or a back SL s because recall that back SLS is wh space so it's even more than a
566:30
Speaker A
single space it could be a tab but by putting those things in parentheses now you can match either the thing on the left or the thing on the right one or more times how about one other question on these regular
566:44
Speaker A
Expressions perfect so I was going to ask um does the back slw um include a DOT uh because no nope it only includes letters numbers uh and underscore that is it and I was wondering you gave an example at the beginning that had uh
567:01
Speaker A
spaces like this is my email so on so um I don't think our current version even quite quite a long while ago stopped accepting it was that because of the carrot uh or because of something no the reason I
567:17
Speaker A
was handling spaces and other English words when I typed out my email address is mailing at doedu was because we were using initially star or plus which is any character uh and even after that we said anything except the at sign which
567:33
Speaker A
includes spaces only once I started using square brackets and a through z and 0 through 9 and underscore did we finally get to the point where we would reject whitespace and in fact I can run this here let me go into the current
567:48
Speaker A
version of my code in VSS code which is using again the back slw's for word characters let me run python of validate and incorrectly type in something like my email address is mailen harvard.edu period which has spaces to the left of
568:04
Speaker A
my username and that is now invalid because space is not a word character yorgo notes too that technically I'm not allowing dots and some of you might be thinking wait a minute my gmail address has a dot in it that's something we're
568:17
Speaker A
going to still have to fix a back slw is not the end all here it's just allowing us to express our previous solution a little more succinctly now one thing we're still not handling quite properly is uppercase versus lowercase the back
568:31
Speaker A
slw technically does handle lowercase letters and uppercase because it's the exact same thing as that set from before which had little a through little Z and big a through big Z but watch this let me go ahead in my current form run
568:45
Speaker A
python to validate dopy and just because my caps slot key is down maen harvard.edu shouting my email address it's going to be okay in terms of the ma it's going to be okay in terms of the Harvard because those are matching the
568:59
Speaker A
back slw which does include lowercase and uppercase but I'm about to see invalid why why is mailing at harvard.edu invalid when it's in all caps here even though I'm using backw yeah so you are asking for the domain. edu in lowercase and you're
569:22
Speaker A
typing it in an uppercase exactly I'm typing in my email address in all uppercase but I'm looking for literally edu and as I see you with airpods and so many of you with headphones I apologize for yelling into my microphone just now
569:35
Speaker A
to make this point but let's see if we can't fix that well if my pattern on line five is expecting it to be lowercase there's actually a few ways I can solve this one would be something we've seen before I could just force the
569:49
Speaker A
user's input to all lowercase and I could put on the end of my first line lower and actually force it all to lowercase alternatively I could do that a little later instead of passing an email I could pass in the lowercase
570:02
Speaker A
version of email because email addresses should in fact be case insensitive so that would work too but there's another mechanism here which is worth seeing it turns out that that function before called re. search supports recall a third argument as well these so-called
570:18
Speaker A
flags and flags are configuration options typically to a function that allow you to configure it a little differently and how might I go about configuring this call to re. search a little bit differently in so far as I'm
570:31
Speaker A
currently only passing in two arguments well it turns out that some of the flags you can pass into this function are these it turns out that the regular expression library in Python AKA re comes with a few built-in variables so
570:45
Speaker A
to speak things that you can think of as constants that have meaning to re.
570:51
Speaker A
search and they do so as follows if you pass in as a flag re. ignore case what re. search is going to do is ignore the case of the user's input it can be uppercase lower case a combination
571:02
Speaker A
thereof the case is going to be ignored it will be treated case insensitively and you can do other things too that we won't do here but if you want to handle the user's input that maybe spans multiple lines maybe they didn't just
571:13
Speaker A
type in an email address but an entire paragraph of text and you want to match different lines of that text that is multiple lines another flag is for re multi-line for just that or re doall whereby you can con uh you can configure
571:27
Speaker A
the dot to rep to recognize not just any character except new lines but any character plus new lines as well but for now let me go ahead and just make use of this first one let me pass in a third
571:39
Speaker A
argument to re. search which is re. uh ignore case let me now reun the program without clearing my screen python of validate dopy let me type in again in all caps effective ly shouting ma harvard.edu enter and now it's
571:56
Speaker A
considered valid because I'm telling re. search specifically to ignore the case of the input and that two here is fine and why might I do this approach rather than call do lower in one of those other locations if I don't actually want to
572:09
Speaker A
change the user's input for whatever reason I can still treat it case insensitively without actually changing the value of that variable itself are any final questions now on this validation of email addresses uh so the pattern is a string
572:26
Speaker A
right M uh can we use an F string you can you yes you can use an F string so that you could plug in for instance the value of a variable and pass it into the function other questions on this access
572:39
Speaker A
W character could we take it as an input from the user technically yes that's not a problem we're trying to solve right now we want the user to provide literal input like their email address not necessarily a regular expression but you
572:51
Speaker A
could imagine building software that asks the user especially if they're more advanced users to type in a regular expression for some reason to validate something else against that and in fact that's what Google's doing if you play around with Google forms and create a
573:04
Speaker A
form with response validation and select regular expression Google lets you and I type in our own regular Expressions would be a per which would be a perfect example of that all right well let me propose that we try to solve one other
573:17
Speaker A
problem here whereby if I go into the same version as before which is now ignoring case but I type in one of my other email addresses let me go ahead and run python of validate dopy and this time let me type in not mailen
573:30
Speaker A
harvard.edu which I use primarily but my another email address of mine maen cs50.h harvard.edu which forwards to the same let me go ahead and hit enter now and huh invalid even though I'm pretty sure that is in fact my email address
573:45
Speaker A
well let's put our finger on the reason why why at the moment is mail at cs50.h harvard. edu being considered invalid even though I'm pretty sure I send and receive email from that address too why might that be because there is a
574:05
Speaker A
DOT that has come after the ad symbol exactly there's a DOT after my cs50 and I'm not expecting any dots there I'm expecting only again word characters which is a through z 0-9 and under score so I'm going to have to retool here but
574:24
Speaker A
how could I go about doing this well it turns out theoretically there could be other email addresses even though they'd be getting a little excessively long for instance mailin at something. cs50.h harvard.edu which is not technically exist but it could you can have of
574:39
Speaker A
course multiple dots in a domain name like we see here wouldn't it be nice if we could handle that as well well let me propose that we modify my regular expression as follows it turns out that you can group ideas together and you can
574:53
Speaker A
not only ask whether or not this pattern matches or this one using syntax like a vertical Bar B which means either A or B you can also group things together and then apply some other operator to them as well in fact let me go back to VSS
575:08
Speaker A
code here and let me propose that if I want to tolerate a subdomain like cs50 that may or may not be there let me go ahead and change it as follows I could naively do this if I want to support
575:21
Speaker A
subdomain I could say well let's allow for otherw characters plus and then a literal Dot and notice I'll highlight in blue here what I've just added everything else is the same but I'm now adding room for another sequence of one
575:36
Speaker A
or more word characters and then a literal dot so this now I think if I rerun python of validate dopy will work for Ma at cs50.h harvard.edu enter unfortunately does anyone see where this is going let me rerun python of validate
575:53
Speaker A
dopy and type in as I keep doing maen harvard.edu which up until now has kept working despite all of my changes but now finally I've broken my own email address so logically what's the solution here well there's a bunch of ways we
576:09
Speaker A
could solve this I could maybe start using two regular expressions and support you uh email addresses of the form username at domain. TLD or username at subdomain dodoma TLD where TLD just means top level domain like edu or I
576:26
Speaker A
could maybe just modify this one because I'd prefer not to have like two uh regular expressions or one that's twice as big why don't I just specify to re.
576:35
Speaker A
search that part of this pattern is optional what was the symbol we saw earlier that allows you to specify that the thing before it is technically optional the straight bar we are using the Straight bar as a optional make the opt the argument
576:54
Speaker A
optional so we could we could use a vertical bar and some parentheses and say either there's something here or there's nothing we could do that in parenthesis but I think there's actually an even easier way uh actually is a
577:07
Speaker A
question mark indeed question mark think back to this summary here of our first set of symbols whereby we had not just Dot and star and plus but also a question mark which means literally zero or one repetitions which affect ly means
577:22
Speaker A
optional it's either there one or it's not zero now how can I translate to that to this code here well let me go ahead and Surround this part of my pattern with parentheses which doesn't mean I want literally a parenthesis in the
577:38
Speaker A
user's input I just want to group these characters together and in fact this now will still work I've only added parentheses around the new part for the subdomain let me run python of validate dopy let me run maen cs50.h harvard.edu
577:52
Speaker A
enter that's still valid but to be clear if I rerun it again for ma harvard.edu that is still invalid but not if I go in here and say after the parentheses which now is one logical unit it's one big
578:06
Speaker A
group of ideas together I add a single question mark there this will now tell re. search that that whole thing in parentheses can either be there once or be there not at all zero times so what does this translate into when I run it
578:23
Speaker A
well let me go ahead and rerun it with maen cs50.h harvard.edu so that the subdomain is there that works as before let me clear my screen and run it again python of validate dopy with ma harvard.edu which used to work then
578:38
Speaker A
broke is are we back in business now we are that's now valid again questions now on this approach where we've use not just the question mark But the parenthesis as well okay yeah you works for zero or one repetition what if you
578:55
Speaker A
have more what if you have more that's okay that's where you could do star star is zero or more which gives you all the flexibility in the world yeah so I was just asking that uh uh with question
579:10
Speaker A
mark there's only one repetition allow it means zero or one repetition so it's either not there or it is there and so that's why this pattern now if I go back to my code even though again it admittedly looks cryptic let me
579:24
Speaker A
highlight everything after the at sign and before the dollar sign this now represents a domain name like harvard.edu or a subdomain within the domain name why well this part to the right is the same as always backw plus
579:41
Speaker A
means something like Harvard or Yale back.edu means literally doedu so the new part is this in parentheses I have another set of back w+ back SL do now but it's all in parentheses I'm now having a question mark right after that which means that
580:00
Speaker A
whole thing in parenthesis either can be there or it can't be there it's either of those that are acceptable so a question mark effectively make something optional it would not be correct to remove the parentheses because what would this mean if I remove the
580:15
Speaker A
parentheses that would mean that only this dot is optional which isn't really what we want to express I want the subdomain like cs50 and the additional dot to be what's there or not there how about one other question on Rex is here
580:31
Speaker A
can they use this for the usernames absolutely we still have other problems right we're not solving all of the problems today just yet but absolutely right now we are not letting you have a period in your username and again some
580:44
Speaker A
of you with Gmail accounts or other accounts you probably have not just underscores numbers and letters you might have periods too well we could fix that not using question mark here per se but now that we have these parentheses
580:55
Speaker A
at our disposal what I could do is this I could use parentheses to surround the back slw to say any word character which is the same thing again as a letter or a number or an underscore but I could also
581:08
Speaker A
or in using a vertical bar something else like a literal dot now a literal dot needs to be escaped otherwise it represents any character which would be a regression a step back but now notice what I've done in parentheses I'm
581:23
Speaker A
telling re. search that those first few characters in your email address that is your username has to be a word character Like A through Z uppercase or lowercase or 0 through n or an underscore or a literal dot we could do this differently
581:38
Speaker A
too I could get rid of the parentheses and the or and I could just use a set of characters I could again manually say a through z a through z 0 through 9 underscore and then I could do a literal
581:52
Speaker A
dot with a back slash period and now I technically don't even need the uppercase because I'm already telling the computer to ignore case I can just pick one or the other which one is better is really up to you whichever one
582:03
Speaker A
you think is more readable would generally be the better design all right let me propose that I rewind this in time to where we left off which was here and let me propose that there are indeed still limitations of this solution not
582:19
Speaker A
just with the username not just with the domain name we're still being a little too restrictive so would you like to see the official regular expression that at least browsers use nowadays whenever you type in an email address to a web form
582:31
Speaker A
and the web form the browser tells you yes or no your email address is syntactically valid ready ready here is and this isn't even officially the right regular expression it's a simplified version that browsers use because it catches most mistakes but not all here
582:50
Speaker A
we go this is the regular expression for a valid email address at least as browsers nowadays Implement them now it's crazy cryptic at first glance but not and it's wrapping onto many lines but it's just one pattern but just
583:07
Speaker A
notice the now familiar symbols there is the carrot symbol at the very top there is the dollar sign at the very end there is a square bracket over here and then some of these ranges plus other characters turns out you don't normally
583:21
Speaker A
see these characters in email addresses it looks like you're swearing at someone in their username but they're valid characters they're valid officially that doesn't mean that Gmail is going to allow you to put dollar signs and other punctuation in your username but
583:34
Speaker A
officially some servers might allow that so if you really want to validate a user's email address you would actually come up with or copy paste something like this but honestly this looks so cryptic and if you were to type it out
583:48
Speaker A
manually you are so likely to make a mistake what's the better solution here instead this is where P past week's libraries are your friend surely someone else on the internet a programmer more experienced than you even has come up
584:03
Speaker A
with code that validates email addresses properly using this regular expression or even something more sophisticated than that so generally if the problem at hand is to validate input that is pretty conventional an email address a URL something where there's an official
584:17
Speaker A
definition that's independent of you yourself find a the popular library that you're comfortable using and use it in your code to validate email addresses this is not a wheel necessarily that you yourself should invent we've used email addresses though to iteratively start
584:34
Speaker A
from something simple too simple and build on top of that so you could certainly imagine using regular Expressions still to validate things that aren't email addresses but are data that are important to you so we at least now have these building blocks now
584:47
Speaker A
besides the regular Expressions themselves it turns out there's other functions and Python's re library for regular Expressions among them is this function here re. match which is actually very similar to re. search except you don't have to specify the
585:01
Speaker A
carrot symbol at the very beginning of your Rex if you want a match from the start of a string re. match by Design will automatically start matching from the start of the string for you similar in spirit is re. full match which does
585:13
Speaker A
the same thing but not only matches at the start of the string but the end of the string so that you too don't need to type in the carrot symbol or the dollar sign as well but let's go ahead and
585:23
Speaker A
transition back now to some actual code whereby we solve a different problem in spirit rather than just validate the users's input and make sure it looks the way we want let's just assume that the users are not going to type in data
585:35
Speaker A
exactly as we want and so we're going to have to clean up their input this happens so often when you're using like a Google form or Office 365 form or anything else to collect user input no matter what your form question says your
585:47
Speaker A
users are not necessarily going to follow those directions they might go ahead and type in something that's a little differently formatted than you might like now you could certainly go through the results and download a CSV or open the Google spreadsheet or
586:00
Speaker A
equivalent in Excel and just clean up all the data manually but if you've got lots of submissions dozens hundreds thousands of rows in your data set doing things manually might not be very fun it might be much more effective to write
586:13
Speaker A
code as in Python that can allow you to clean up that data and any future data as well so let me propose that we go ahead here and close validate dopy and let's go ahead and create a new program
586:25
Speaker A
Al together called format. the goal of which is to reformat the user's input in the format we expect I'm going to go ahead and run code of format. py and let's suppose that the data we're going to reformat is the user's name so not
586:40
Speaker A
email address but name this time and we're going to hope that they type in their name properly like David ma but some users might be in the habit for whatever reason of typing their name backwards if you will with the comma
586:52
Speaker A
such as men comma David instead now it's fine because both are clearly as readable to the human but if you want to standardize how those names are stored in your system perhaps a database or CSV file or something else it would be nice
587:07
Speaker A
to at least standardize or canonicalize the format in which you're storing your data so that if you print out the user's name it's always the same format David Ma and there's no commas or backwards to it so let's go ahead and do something
587:20
Speaker A
familiar let's go and give myself a variable called name and set it equal to the return value of input asking the user as we've done many times what's your name question mark I'm going to go ahead and proactively at least clean up
587:31
Speaker A
some messiness as we keep doing here by just stripping off any leading or trailing whites space just in case the user accidentally hits the space bar we don't want that ultimately in our data set and now let me go ahead and do this
587:43
Speaker A
as we've done before let me just go ahead quickly and print out just to make sure I'm off to the right start hello and then in curly brace's name so making an F string to format hello comma name
587:54
Speaker A
now let me go ahead and clear my screen and run python of format. let me behave and type in my name as I normally would David space ma enter and I think the output looks pretty good it looks as
588:05
Speaker A
expected grammatically let me now go ahead though and play this game again but this time maybe because I'm not thinking or I'm just in the habit of doing last name comma first I do ma comma David and hit enter all right well
588:17
Speaker A
this now is is weird even though the program is just spitting out exactly what I typed in arguably this is not close to correct at least grammatically it should really say hello David ma now maybe I could have some if conditions
588:31
Speaker A
and I could just reject the user's input if they type a comma or get their names backwards somehow but that's going to be uh too little too late if the user has already submitted a form online and I
588:41
Speaker A
already have the data and now I need to go in and clean it up and it's not going to be fun to go through manually in Google spreadsheets or apple numbers or Microsoft Excel and manually fix a lot
588:51
Speaker A
of people's names to get rid of the commas and move the first name before the last as is conventional in the US so let's do this it could be a little fragile but let's like let's start to express ourselves a little
589:03
Speaker A
programmatically here and ask this if there is a comma in the person's name which is pythonic I'm just asking the question is this shorter string in this longer string then let me go ahead and do this let me go ahead and grab that
589:17
Speaker A
name in the variable split on not just the Comm but the space after assuming the human typed in a space after their name and let me go ahead and store the result of that splitting of ma comma David into
589:30
Speaker A
two variables let's do last comma first again unpacking the sequence of values that comes back now let me go ahead and reformat the name so I'm going to forcibly change the user's name to be as I expect so name is actually going to be
589:44
Speaker A
this format string first name then last name both in curly braces but formatted together with a single space so that I'm overriding the user's input and updating my name variable accordingly for the moment to be clear this program is
589:59
Speaker A
interactive like the users like me are typing their name into the program but imagine the data already is in a CSV file it came in from some process like a Google form or something else online you could imagine writing code similar to
590:12
Speaker A
this but that maybe goes and reads that file into memory first maybe it's a CSV via CSV reader or a dict reader and then iterating over each of those names but we'll keep it simple and just do one
590:22
Speaker A
name at a time but now what's kind of interesting here is if I go back to my terminal window and clear it and run python of format. piy and hit enter I'm going to type in David space ma as
590:33
Speaker A
before and I think we're still good but I'm also going to go ahead and do this python of format. ma comma David with a space in between crossing my fingers and hit enter and voila that now has been
590:47
Speaker A
fixed such a simple thing to be sure but it is so commonly necessary to clean up users input here we see at least one way to do so pretty easily now to be fair there's some problems here and in fact
591:01
Speaker A
can someone imagine a scenario in which this code really doesn't fix the user's input what could still go wrong even with this fix in my code any thoughts if they type their in their name comma and then sign them oh and then something
591:18
Speaker A
else yeah so let me let me try this for instance let me go ahead and run a program and uh I am the only David men that I know but suppose I were uh uh let's say junior like this and it's
591:30
Speaker A
common in English at least to sometimes put a comma there you don't necessarily need the comma but I'm one of those people who uses a comma that's now really really broken so I've broken some assumption there and so that could
591:42
Speaker A
certainly go wrong here what else well let me go ahead and run this again and if I did ma comma David no space because I'm being a little sloppy I'm not paying attention which is going to happen when
591:51
Speaker A
you have lots of users ultimately well this really broke now notice I have a value error an actual exception why well because split is supposed to be splitting the string into two strings by looking for the comma and a space but if
592:06
Speaker A
there is no comma in space it can't split it into two things and the fact that I have two variables on the left but I'm only getting back one thing on the right means that I can't do this
592:18
Speaker A
code quite as this so it's fragile to be sure but wouldn't it be nice if we could at least improve it for instance we now know some regular expression syntax what if I at least wanted to make this space
592:28
Speaker A
optional well I could use my new found regular expression syntax and put a question mark question mark means zero or one of the things to the left what's the thing to the left it's literally a space I don't even need parentheses if
592:41
Speaker A
there's just one thing there so that would be the start of a pattern that says I must have a comma and then I may or may not have a space zero or one spaces there after unfortunately the version of split that's built into the
592:56
Speaker A
stir variable as in this case doesn't support regular Expressions if we want our regular Expressions we need to go use that Library here so let me go ahead and do this let me go in and leave this code AS is but go up to the top now and
593:10
Speaker A
import re to import the library for regular expressions and now let me go ahead and start changing my Approach here I'm going to go ahead and do this I'm going to use the same function called re. search and I'm going to
593:24
Speaker A
search for a pattern that I think will be last comma first so let me use my new found regular expression syntax and represent a pattern for something like ma comma space David how can I do this well inside of my quotes for re. search
593:40
Speaker A
I'm going to have something so plus sorry I'm going to have something so plus then I'm going to have a comma then I'm going to have a space then I'm going to have something plus now I'm going to
593:53
Speaker A
preemptively refine this a little bit I want this whole pattern to start matching at the beginning of the user's input so I'm going to add the carrot right away and I want the end of the user's input to be matched as well so
594:05
Speaker A
that I'm literally expecting any character one or more times then a comma then a space then any other character one or more times and then that is it and I'm going to pass in the name variable as before now when we've used
594:19
Speaker A
re do search in the past we really used it just to answer a question does the user's input match the following pattern or not true or false effectively but re.
594:32
Speaker A
search is actually more powerful than that you can actually get back more information and you can do this you can specify a variable and then an assignment operator and get back more precise answers to what has been found
594:46
Speaker A
when searched for but what is it you want to get back well it turns out there's this other feature of regular Expressions which allow you to use parentheses not just to group things together but to capture them it turns
595:00
Speaker A
out when you specify parentheses in a regular expression unbeknownst to us up until now everything in the parentheses will be returned to you as a return value from the re. search function it's going to allow you to extract specific
595:16
Speaker A
amounts of information from the user's own input you can reverse this process too by using the non-capturing version as well you can use parentheses and then literally a question mark and a colon and then some other stuff and that will
595:29
Speaker A
say don't bother capturing this I just want to group things but for now we're going to use just the parentheses themselves so how am I going to do this well if I want to get back the user's last name and first name I think what I
595:42
Speaker A
want to capture is the plus here and the plus here so I've deliberately surrounded in par parentheses the dot plus both to the left and the right of the comma not because I'm grouping them together per se I'm not adding a
595:57
Speaker A
question mark I'm not adding of another Plus or a star I'm using parentheses now for capturing purposes why well I'm going to do this next I'm going to still ask a Boolean question like if there are matches then do this so if matches is
596:13
Speaker A
not effectively false like none I do expect I've gotten back some matches and watch what I can do now I can do last comma first equals whatever matches in and get back all of the groups of matches then go ahead and update name
596:30
Speaker A
just like before with a format string and do first and then last in curly braces as well and then at the very bottom just like before print out for instance hello comma name so the new code now is everything highlighted here
596:46
Speaker A
I'm using re search to search for whether the US user typed their name in last comma first format but I am more powerfully using re. search to capture some of the user's input what's going to get captured anything I surround it in
597:02
Speaker A
parentheses will be returned to me as return values how do you get at those return values you ask the variable to which you assigned them for all of the groups all of the groups of parentheses that were captured so let me go ahead
597:17
Speaker A
and do this let me go ahead now and run python of format stop Pi enter and I'm going to type my name as usual in this case nothing happens with this if condition why because I did not type a
597:31
Speaker A
comma and so this search does not find a comma so there are no matches so we immediately just print out hello name nothing interesting or new there but if I now go ahead and clear my screen and run python a format up high and do maen
597:46
Speaker A
commas space David enter we've reformatted my name well how did this work let me be a little more explicit now it turns out I don't have to just say matches. groups I can get specific groups back that I want
598:00
Speaker A
so let me change my code a little bit more let me go ahead now and just say this let's update name uh to well actually let's do this let's say that the last name is going to be in the
598:14
Speaker A
matches but specifically group one the first name is going to be in the matches but specifically group two why one and two because this is the first set of parentheses to the left of the comma this is the second set of parentheses to
598:26
Speaker A
the right of the comma and based on the input this would be the user's last name in this scenario me this would be the user's first name David in this scenario that's why I'm using group one for the
598:38
Speaker A
last name and group two for the first name and now I'm going to go ahead and say name equals uh F string again uh first and then last done and let me refine this one last step before we take
598:54
Speaker A
questions I don't really need these variables if I'm immediately using them let's just go ahead and tighten this up further as we've done in the past for design sake if I want to make the name the concatenation of the person's first
599:06
Speaker A
name and last name let's just do this matches. group two first plus a space plus matches. group one so it's just up to me to know from left to right this is group one this is group two so group one
599:21
Speaker A
is last group two is first so if I want to flip them around and update the value of name I can explicitly get group two first concatenate using plus a single space and then concatenate on group one all right that was a lot let me pause to
599:38
Speaker A
see if there are questions the key difference here is we're still using re. search the exact same way but now I'm using its return value not just to answer a question true or false but to actually get back specific matches
599:51
Speaker A
anything I captured so to speak with parentheses why is it here we're using one and two instead of Z and one really good question caping the first a good observation in almost every other context we've started counting at zero
600:05
Speaker A
and one instead of one and two it turns out there's something else in location zero when it comes back from re. search related to the string itself so according to the documentation of this function only one is the first set of
600:19
Speaker A
parentheses and two is the second set and onward from there just a different convention here other questions uh what if we write nothing like white space comma whes space uh how how we check um true of condition before I answer
600:36
Speaker A
directly let me just run this and make sure I've not broken anything further let me run python of format. let me type in David space maen the right way let me run it once more let me type it Ma comma
600:46
Speaker A
David the wrong way that we're fixing and we're still good but I think it will still break let me run it a third time with me comma David with no space and now it's still broken why because I'm
600:59
Speaker A
still looking for comma space now how can I fix that one way I could do that is to add a question mark here which again is zero or more of the thing before so if I have a space and then a
601:11
Speaker A
question mark literally no need for any parentheses then I can literally tolerate both ma comma space David or ma comma David so let's try again before this did not work let's do me comma David with no space now it does actually
601:27
Speaker A
work so we can tolerate different amounts of white space if I am a little more precise with my formula let me go ahead and try once more let me very weirdly but possibly hit the space bar a few too many times so now they're really
601:40
Speaker A
separated this again is uh not going to work quite right because it's going to consume all of that white space so now I might want to strip left and right any of the leading white space on the result
601:52
Speaker A
or what I could do here is say this instead of zero or one I could use a star here so space star and now if I run this once more with ma comma space space space David enter now we've cleaned up
602:07
Speaker A
things further so you can imagine depending on how messy the data is that you're cleaning up your regular Expressions might need to get more and more sophisticated it really depends on just how many problems we want to solve
602:18
Speaker A
at once well allow me to propose that we Forge ahead further just to clean this up even more so using a feature that's actually relatively new to python itself it is very common when using regular Expressions to do exactly what I've done
602:32
Speaker A
here to call a function like re. search with capturing parentheses inside such that you get back a return value that I'm calling matches you could call it something else but I'm calling it by default matches and then notice on the
602:45
Speaker A
next line I'm saying if matches wouldn't it be nice if I could just tighten things up further and do these all on the same line well you can sort of let me go ahead and do this let me get rid of this if and let
602:59
Speaker A
me just try to say something like this if matches equals re search and then colon so combining my if condition into just one line instead of those two um in C or C++ or Java you would actually do
603:15
Speaker A
something like this surrounding the whole thing with parentheses sometimes double sets to suppress any warnings if you want to do two things at once if you want to not only assign the return value of re. search to a variable called
603:28
Speaker A
matches but you want to subsequently ask a Boolean question is this effectively true or false that's what I was doing a moment ago let me undo this a moment ago I was getting back the return value and assigning it to matches and then I was
603:43
Speaker A
asking the question well it turns out this need to have two lines of code presumably rubbed people wrong for too long long in Python and so you can now combine these two kinds of lines into one but you need a new operator you
603:57
Speaker A
cannot just say if matches equals re search and then an cin at the end you instead need to do this you need to do colon equals if and only if you want to assign something from right to left and
604:12
Speaker A
you want to ask an if or an L if question on the same line This is affectionately known as you can see here as the wall operator and it's new to python in recent years and it both allows you to
604:25
Speaker A
assign a value as I'm doing from right to left and ask a Boolean question about it like I'm doing with the if or equivalently L if does anyone know why this is called The Walrus operator if you kind of look at it like this perhaps
604:42
Speaker A
if you're familiar with walruses it kind of sort of looks like a walrus so a minor detail but a relatively new feature of python that honestly you'll probably continue to see online and in source code and in textbooks and so
604:53
Speaker A
forth increasingly so now that it does exist it does not change the logic at all if I run python of format. piy and type maen commas space David it still fixes things but it's tightened up my code just a bit more all right let's go
605:06
Speaker A
ahead and look at one final problem to solve that of extracting information now as well so at this point we've now validated the user's input by checking whether or not it meets a certain pattern we've cleaned up the users input
605:20
Speaker A
by checking against a pattern whether it matches or not and if it does match we kind of reorganize some of the users information so we can clean up their input and standardize the format in which we're storing or printing it in
605:31
Speaker A
this case let's do one final example where we're very specifically extracting information in order to answer some question so let me propose this let me go ahead and close format. and create a new file called twitter. the goal of which is to prompt
605:46
Speaker A
users for the URL of their Twitter profile and extract from it infer from that URL what is the user's username now why might you want to do this well one you might want users to be able to just
605:59
Speaker A
very easily copy and paste the URL from their own Twitter profile into your form into your app so that you can figure out what their uh username is or you might have a form that asks the user for their
606:11
Speaker A
Twitter username and because people aren't necessarily paying very close attention some people type their username some people type their whole URL or something else altogether it would be nice now that you're a programmer to just be more tolerant of
606:25
Speaker A
different types of input and just take on the burden of canonicalizing standardizing the data but being flexible with the users it's arguably a better user experience if you just let me copy paste or type in what I want you
606:37
Speaker A
clean it up you're the programmer not me LS for a better experience perhaps well let me go ahead and do this with twitter. let me first go ahead and prompt the user here for a value for a variable that I'll call you URL and just
606:51
Speaker A
ask them to input the URL of their Twitter profile I'm going to go ahead and strip off any leading or trailing whitespace just in case users accidentally hit the space bar that's like literally the least I can do quite
607:01
Speaker A
easily but now let's go ahead and do this suppose that the users address is the following let me print out what they type in and let me clear my screen and run python of twitter. I'm going to go
607:14
Speaker A
ahead and type in for instance https twitter.com David J ma which happens to be my own Twitter username for now we're just going to print it back onto the screen just to make sure I've not messed up yet okay so I've printed back out the
607:28
Speaker A
exact same URL but the goal at hand is to extract the username only now let me just ask perhaps a straightforward question logically what do I need to do to get at the user's username well um we just ignore what's before the username
607:46
Speaker A
and then just extract the username perfect yeah I mean it is simple as that if you know the usernames at the end well let's just somehow ignore everything to the beginning well what's at the beginning well it's a URL so
607:57
Speaker A
we're probably going to need to ignore an https a colon a twitter.com and a slash so we just want to throw all of that away why because if it's a URL We Know by how Twitter works that the
608:09
Speaker A
username comes at the end so let's use that very simple idea to get at the information we want well I'm going to try this a few different ways let me go back into my program here and instead of
608:19
Speaker A
just printing it out which was just to see what's going on let me do this let me create a new variable called username and let me call url. replace it turns out that if URL is a string or a stir in
608:32
Speaker A
Python it again comes with multiple methods like strip uh and split and others as well one of which is called replace and replace will do just that you pass a two arguments the first of which is what do you want to replace the
608:46
Speaker A
second argument is what do you want to replace it with so if I want to get rid of as I've been proposed really just everything before the username that is the Twitter URL or the beginning thereof let's just say this go ahead and replace
609:00
Speaker A
https twitter.com close quote that's what I want to replace and comma second argument what do you want to replace it with nothing so I'm literally going to pass in quote unquote to effectively do a find and replace that's what the
609:15
Speaker A
replace method does just like you can do it in Microsoft Word or Google Docs this is the programmer's way of doing find and replace now let me go ahead and print out just the username so I'll use an F string like this I'll say username
609:28
Speaker A
colon and then in curly braces username just to format it nicely all right let me go ahead and clear my screen and run python of twitter. enter URL here we go https [Music] twitter.com davidj maen enter okay now
609:46
Speaker A
we've made some progress done for the day right well what is suboptimal about this can anyone critique or find fault with my program it is working now but it's a little fragile I bet we could contrive some scenarios where I think it
610:02
Speaker A
works but it doesn't well I have a few ideas actually well first of all uh if we if we don't specify https it will broken secondly if we have slash at the end it also will be broken if we if we
610:17
Speaker A
have like question mark up the after question mark it also w't work so lot of scenar actually oh my God I mean here we are I was pretending to think I was done but my God like Alex gave us a whole
610:28
Speaker A
laundry list of like problems and just to recap then what if it's not https it's HTTP slightly less secure but I should still be able to tolerate that programmatically uh what if the protocol is not there what if the user just typed
610:40
Speaker A
twitter.com davidj maen it would be nice to tolerate that rather than show an error and make me type in the protocol why it's not good user experience what if it had a flash at the end of the username or a question mark If you think
610:52
Speaker A
about URLs you've seen on the web there's very commonly more information especially if it's been shared on social media there might be HTTP parameters so to speak just stuff there that we don't want there could be a www. twitter.com
611:05
Speaker A
which I'm also not expecting but does work if you go to that URL too so there's just so many things that can go wrong and even if I come back to my contrived example as earlier what if I
611:15
Speaker A
run this program and say this uh my username is H H gtps twitter.com davidj maen enter well that too just just didn't really work it got rid of the U actually okay actually that kind of worked but the goal here is to actually
611:36
Speaker A
get the user's username not an English sentence describing the user's username so I would argue that even though I just accidentally created perfectly correct English grammar I did not extract the Twitter username correctly I don't want words like my username is as part of my
611:51
Speaker A
input so how can we go about improving this and maybe chipping away at some of those problems one by one well let me clear my screen here let me come back up to my code and let me not just replace
612:01
Speaker A
it but let me do something else instead I'm going to go ahead and instead of using replace I'm going to use another function called remove prefix a prefix is a string or a substring that comes at the start of another so if I remove
612:15
Speaker A
prefix I don't need a second argument for this function I just need one what prefix do you want to remove so this will at least now fix the problem I just described of typing in like a whole sentence where the URL is there but it's
612:27
Speaker A
not the beginning it's only at the end so here this still is not correct but we don't create this weird looking output that just removes the URL part of the input uh my username is htps twitter.com davidj maen a moment
612:44
Speaker A
ago it did remove the URL and left only the David J ma this is not perfect still but at least now it does not weirdly remove the URL and then leave the English it's just leaving it alone so
612:57
Speaker A
maybe I could handle this better but at least it's removing it from the part of the string I might anticipate well what else could we do here well it turns out that like regular Expressions just let us express patterns
613:09
Speaker A
much more precisely we could spend all day using a whole bunch of different python functions like remove prefix or remove and strip and others and kind of make our way to the right solution but a regular expression just allows you to
613:21
Speaker A
more succinctly if admittedly more cryptically Express these kinds of patterns and goals and we've seen from parentheses which can be used not just to group symbols together as sets but to capture information as well we have a very powerful tool now in our toolkit so
613:39
Speaker A
let me do this let me go ahead and start fresh here and import the re Library as before at the very top of my program I'm still going to get the user's URL via the same l of code but I'm now going to
613:51
Speaker A
use another function as well it turns out that there's not just re. search or rd. match or re. full match there's also re. sub in the regular expression Library where sub here means substitute and it takes more arguments but they're
614:06
Speaker A
fairly straightforward the first argument to re.sub is the pattern the regular expression that you want to look for then you have a replacement string what do you want to replace that pattern with and where do you want to do all
614:19
Speaker A
that well you pass in the string that you want to do the substitution on then there's some other arguments that I'll wave my hands at for now among them are the same flags and also a count like how
614:28
Speaker A
many times do you want to do find and replace do you want it to do all or do you want to do it just one or so forth you can have further control there too just like you would in Google Docs or
614:38
Speaker A
Microsoft Word well let me go back to my code here and let me do this I'm going to go ahead and call re not search but re.sub for substitute I'm going to pass in the following regular expression https
614:54
Speaker A
twitter.com uh Slash and then I'm going to close my quote and now what do I want to replace that with well like before with the simple stir replace function I want to replace it with nothing just get rid of it alt together but what uh
615:07
Speaker A
string do I want to pass in to do this to the URL from the user and now let me go ahead and assign the return value of re sub to a variable called username so re sub purpose in life is again to
615:21
Speaker A
substitute some value for some regular expression some number of times it essentially is find and replace using regular expressions and it returns to you the resulting string once you've done all those substitutions so now the very last line of my code can be the
615:35
Speaker A
same as before print and I'll use an F string username colon and then in curly braces username so I can print out literally just that all right let's try this and see what happens I'll clear my terminal window run python of twitter.
615:49
Speaker A
and here we go https twitter.com davidj cross my fingers and hit enter okay now we're in business but it is still a little fragile and so let me ask the group what problem should I now further chip away at they've been said before
616:09
Speaker A
but let's be clear what's one or more problems that still remain the protocols and the uh domain prefixes for good the protocol so HTTP versus https maybe the subdomain www should it be there or not and there's a few other mistakes here
616:26
Speaker A
too let me actually stay with the group what are some other shortcomings of this current solution um if we use a phrase like you do before we are going to have the same problem because it's not taken account in the first part of the the
616:42
Speaker A
text example good I might still allow for like some words uh some English to the left of the URL because I didn't use like my carrot symbol so I'll fix that and any final observations on shortcomings here uh well it could be a
616:56
Speaker A
HTTP or they could be like less than two slashes okay so it could be HTP and I think that was mentioned too in terms of protocol there could be fewer than two slashes that I'm not going to worry
617:06
Speaker A
about if the user gives me one slash instead of two that's really user error and I could be tolerant of it but you know what at that point I'm okay yelling at them with an error message saying please fix your input otherwise we could
617:18
Speaker A
be here all day long trying to handle all possible typos for now I think in the interest of usability or user experience ux let's at least be tolerant of all possible valid inputs or reasonable inputs if you will so let me
617:31
Speaker A
go here and let me start chipping away at these here what are some problems we can solve well let me propose that we first address the issue of matching from the beginning of the string so let me add the carrot to the beginning and let
617:44
Speaker A
me add not a dollar sign at the end though right because I don't want to match all the way to the end because I want to tolerate a username there so I think we just want the carrot symbol
617:55
Speaker A
there there's a subtle bug that no one yet mentioned and let me just kind of highlight it and see if it jumps out at you now it's a little subtle here on my screen I've highlighted in blue a final
618:08
Speaker A
bug here maybe some Smiles on the screen yeah can we take one hand here why am I highlighting the dot in twitter.com even though it definitely should be there so the dot without a backlash mean any character is up a new line yeah exactly
618:25
Speaker A
it's not it's means any character so I could type in something like Twitter uh question markc or Twitter anything com and that would actually be tolerate it's not really that bad cuz why would the user do that but if I want to be correct
618:41
Speaker A
and I want to be able to test my own code properly I should really get this detail right so that's an easy fix too but it's a common mistake anytime you're writing regular Expressions that happen to involve special symbols like dots in
618:53
Speaker A
a URL or domain name a dollar sign in something involving currency remember you might indeed Need to Escape it with a backslash like this here all right let me ask the group about the protocol specifically https is a good thing in
619:08
Speaker A
the world it means secure there is encryption being used so generally you like to see https but you still see people typing or copy pasting HTTP What would be the simplest fix here to tolerate as has been proposed both HTTP
619:25
Speaker A
and https I'm going to propose that I could do this I could do HTTP vertical bar or https which again Means A or B but I think I can be smarter than that I can keep my code a little more succinct
619:39
Speaker A
any recommendations here for tolerating HTTP or https we could try to put an question mark behind the perfect just use a question mark right like both of those would be viable Solutions if you want to be super explicit in your code fine use
619:56
Speaker A
parentheses and say HTTP or https so that you the reader your boss your teacher just know exactly what you're doing but you know if you keep taking the more of a Bose approach all the time it might actually become less readable
620:09
Speaker A
certainly once your regular Expressions get this big instead of this big so let's save space where we can and I would argue that this is pretty reasonable so long as you're in the habit of reading regular expressions and
620:20
Speaker A
know that question mark does not mean a literal question mark but it means zero or one of the thing before I think we've effectively made the S optional here now what else can I do well suppose we want
620:31
Speaker A
to tolerate the www dot which may or may not be there uh but it will work if you go to a browser I could do this www. uh wait I want a backs slash there so I don't repeat the same mistake as
620:45
Speaker A
before but this is no good either because I want to tolerate www being there or not being there and now I've just required that it be there but I think I can take the same approach any recommendations how do I make the www
620:59
Speaker A
dot optional just to hammer this home we can like group uh make a and question mark perfect so question mark is the short answer again but we have to be a little smarter this time as Maria's noted we need parentheses now
621:15
Speaker A
because if I just put a question mark after the dot that just means the dot is optional and that's wrong because we don't want the user to type in wwwt w i TT e r we want the dot to be there or
621:27
Speaker A
just not at all with no www so we need to group this whole thing together put a parenthesis there and then a parenthesis not after the third W after the dot so that that whole thing is either there or
621:41
Speaker A
it's not there and what else could we still do here you know there's going to be one other thing we should tolerate and it's been said before and I'll pluck this one off what about the protocol like what if the user just doesn't type
621:52
Speaker A
or doesn't copy paste the HTTP colon slash or an https colon right honestly you and I are not in the habit generally of even typing the protocol anymore nowadays you just let the browser figure it out for you and automatically add it
622:08
Speaker A
instead so this one's going to look like more of a mouthful but if I want this whole thing here in blue to be optional it's actually the same solution as Maria offered a moment ago I'm going to go
622:19
Speaker A
ahead and put a parenthesis over here and a parenthesis after the two slashes and then a question mark so it's to make that whole thing optional as well and this is okay it's totally fine to make this whole thing optional or inside of
622:35
Speaker A
it this little thing just the S optional as well so long as I'm applying the same principles again and again either on a small scale or a bigger scale it's totally fine to Nest one of these inside of the other
622:49
Speaker A
questions now on any of these refinements to this parsing this analyzing of Twitter what if we put a vertical bar besides this www do what if we use a a vertical bar there so we could do something like that too we
623:06
Speaker A
could do something like this uh instead of the question mark I could do www. or nothing and just leave that in the parenthesis that too would be fine I personally tend not to like that because it's a little less obvious to me wait a
623:21
Speaker A
minute is that deliberate or did I forget to finish my thought by putting something after the vertical bar but that too would be allowed there as well if that's what you mean other questions on where we left things here where we
623:32
Speaker A
made the protocol optional too what coulden if we have parenthesis and then inside we have another parenthesis and another parenthesis to feel with each other if you have parentheses inside of parentheses that too is totally fine and indeed that should be one of the
623:50
Speaker A
reassuring lessons today as complicated as each of these regular Expressions has admittedly gotten I'm just applying the exact same principles in the exact same syntax again and again so it's totally fine to have parentheses inside of parentheses if they're each solving
624:05
Speaker A
different problems and in fact the lesson I would really emphasize the most today is that you will not be happy if you try to write out a whole complicated regular expression all at once like if you're anything like me you will fail
624:19
Speaker A
and you will have trouble finding the mistake because my God look at these things they are even to me all these years later cryptic the better way I would argue whether you're new to programming or as old to it as I am is
624:31
Speaker A
to just take these baby steps these incremental steps where you do something simple you make sure it works you add one more feature make sure it works add one more feature make sure it works and hopefully by the end because you've done
624:43
Speaker A
each of those steps one at a time the whole thing will make sense to you but you'll also have got gotten each of those steps correct um at each turn so please do avoid the inclination to try to come up with long sophisticated
624:58
Speaker A
regular Expressions all at once because it's just not a good use of a time if you then stare at it trying to find a mistake that you could have caught if you did things more incrementally instead all right there Still Remains
625:08
Speaker A
arguably at least one problem with this solution in that even though I'm calling re.sub to substitute the URL with nothing quote unquote I then on my final line of code line six I'm just blindly assuming that it all worked and I'm
625:22
Speaker A
going to go ahead and print out the username but what if the user if I clear my screen here and run python of twitter. doesn't even type a Twitter URL what if they do something like https www.google.com slash like completely
625:36
Speaker A
unrelatedly for whatever reason enter that is not their Twitter username so we need to have some conditional logic I would argue so that for this program's sake we're only printing out or in a backend system we're only saving into
625:50
Speaker A
our database or a CSV file the username if we actually matched the proper pattern so rather than use re.sub which is useful for cleaning up data as we've done here to get rid of something we don't want there why don't we go back to
626:06
Speaker A
re. search where we began today and use it to solve the same problem but in a way that's conditional whereby I can confidently say yes or no at the end of my program here's the username or here it is not so let me go ahead now and
626:20
Speaker A
I'll clear my terminal window here I'm going to keep most of uh the I'm going to keep the first two lines the same where I import re and I get the URL from the user but this time let's do this
626:31
Speaker A
let's this time search for using re. search instead of re.sub the following I'm going to start matching at the beginning of the UR of the string https uh question mark to make the S optional colon SL slash then I'm G to
626:46
Speaker A
make my uh www uh optional by putting that in question marks there then a twitter.com with a literal dot there so I'll stay ahead of that issue too then a slash and then well this is where David J ma is
627:01
Speaker A
supposed to go how do I detect this well I think I'll just tolerate anything at the end of the URL here all right dollar sign at the very end close quote for the moment I'm going to stipulate that we're
627:12
Speaker A
not going to worry about question marks at the end or hashes like for fragment IDs and URLs we're going to assume for Simplicity now that the URL just ends with the username alone now what am I going to do well I want to search for
627:25
Speaker A
this URL specifically and I'm going to ignore case so rei. ignore case uh uh applying that same lesson learned from before rei. search recall will return to you the matches you've captured well what do I want to capture well I want to
627:40
Speaker A
capture everything to the right of the twitter.com URL here so let me surround what should be the user's username with parentheses not for making them optional but to say capture this set of characters Now ar. search recall returns
627:56
Speaker A
an answer matches will be my variable name again but I could call it anything I want and then I can do this if matches now I know I can do this let's print out the format string username colon and
628:09
Speaker A
then uh what do I want to print out well I think I want to print out matches.
628:14
Speaker A
group one for my matched username all right so what am I doing just to recap line one I'm importing the library line two I'm getting the URL from the user so nothing new there line five I'm searching the user's URL as indicated
628:30
Speaker A
here as the second argument for this regular expression this pattern I have surrounded the plus with parentheses so that they are captured ultimately so I can't extract in this final scenario the user's username if I indeed got a match
628:48
Speaker A
and matches is non none it is actually containing some match then and only then print out username in this way let me try this now if I run python of twitter.
628:59
Speaker A
and type in HTTPS www.google.com now nothing gets printed so I've at least solved the mistake we just saw where I was just assuming that my code worked now I'm making sure that I have searched for and found the
629:14
Speaker A
Twitter URL prefix all right well let's run this for real now python of twitter.
629:21
Speaker A
https twitter.com davidj maen but note I could use HTTP I could use www I'm just going to go ahead here and hit enter huh none what has gone wrong this one's a bit more subtle but why does matches. group one
629:43
Speaker A
contain nothing wait a minute let me maybe I maybe I did this wrong Maybe maybe do we need the www let me run it again so here we go https let add it www. twitter.com davidj mail all right
630:00
Speaker A
enter what is going on we have to say group group I have to say group two well wait all right because we had the the subdomain was optional and to make it optional I needed to use parentheses here and so I then said zero or one okay
630:16
Speaker A
so that means that actually I'm unintentionally but by Design capturing the www dot or none of it if it wasn't there before but I have a second match over here because I have a second set of parentheses so I think yep let me change
630:31
Speaker A
matches group one to matches group two and let's rerun this python of twitter. https www. Twitter let's do this uh twitter.com David J ma enter and now we've got access to the username let me go ahead and tighten it up a little bit
630:50
Speaker A
further uh if you like uh our new friend uh it's hard not to like if we like our old friend the wallus uh operator let's go ahead and add this just to tighten things up let me go back to vs code here
631:01
Speaker A
and let me get rid of the unnecessary condition there and combine it up here if matches equals that but let's change the single assignment operator to the Wallace operator now I've tightened things up further but I bet I bet I bet
631:14
Speaker A
there might be another solution here and indeed it turns out that we can come back to this final set of syntax recall that when we introduced these parentheses we did it so that we could do a or b for instance with the
631:28
Speaker A
vertical bar though you can even combine more than just one bar we use the group to combine ideas like the www do and then there's this admittedly weird syntax at the bottom here up until now not used there is a non capturing
631:43
Speaker A
version of parentheses if you want to use parentheses logically because you need to but you don't want to bother capturing the result and this would arguably be a better solution here because yes if I go back to vs code I do
631:55
Speaker A
need to surround the www.t with parenthesis at least as I've written my Rex here because I wanted to put the question mark after it but I don't need the www dot coming back in fact let's only extract the data we care
632:09
Speaker A
about just so there's no confusion down the road for me or my colleagues or my teachers so what could I do well the syntax per this slide is to use a question mark and a colon immediately after the open parenthesis it looks
632:24
Speaker A
weird admittedly those of you who have prior programming experience might recognize the syntax from Turner operators doing an if else allinone line a question mark colon at the beginning of that parenthetical means yes I'm using parentheses to group these things
632:40
Speaker A
together but no you do not need to capture them instead so I can change my code back now to matches. group one I'll clear my screen here run python of twitter. I'll again run here uh https twitter.com davidj maen with or
632:57
Speaker A
without the www and now I indeed get back that username any questions then on these final techniques so first of all could we move the carrot right at the beginning of Twitter and then just start reading from there and then get rid of everything
633:18
Speaker A
else before that the kind of WWE uh issues that we had and then my second question is how would we um use kind of I guess it either a list or a a dictionary to to sort the do kind of
633:33
Speaker A
thing because we have dood UK and that kind of St how would we bring that into uh the re function a good question but no if I move the carrot before twitter.com and throw away the protocol and the www then then the user is going
633:48
Speaker A
to have to type in literally twitter.com username they can't even type in that other stuff so that would be a regression a step back as for the do and the.org and.edu and so forth the short answer is there's many different
634:03
Speaker A
solutions here if I wanted to be stringent about do and suppose that Twitter probably owns multiple domain names even though they tend to use just this one suppose they have uh something like.org as well you could use more
634:16
Speaker A
parentheses here and do something like this Comm or org I'd probably want to go in and add a question mark colon to make it non-capturing because I don't care which it is I just want to tolerate both alternatively we could capture that we
634:30
Speaker A
could do something like this where we do dot plus so as to actually capture that and then we could do something like this if matches. group one now equals equals Comm then we could support this so you could imagine factoring out the logic
634:48
Speaker A
just by extracting the top level domain or TLD and then just using python code maybe a list maybe a dictionary to validate elsewhere outside of the redx if it's in fact what you expect for now though we kept things simple we focused
635:01
Speaker A
only on the Doom in this case let's make one final change to this program so that we're being a little more specific with the definition of a Twitter username it turns out that we're being a little too generous over here whereby we're
635:13
Speaker A
accepting one or more of any character I check the documentation for Twitter and Twitter only only supports letters of the alphabet A through Z numbers 0-9 or underscore so not just dot which is literally anything so let me go ahead
635:28
Speaker A
and be more precise here at the end of my string let me go ahead and say this set of symbols in square brackets I'm going to go ahead and say a through z uh 0 through 9 and an underscore because
635:40
Speaker A
again those are the only valid symbols I don't need to bother with an uppercase a or a lowercase C because we're using re.
635:46
Speaker A
ignore case over here but I want to make sure now that I tolerate not only one or more of these symbols here but also maybe some other stuff at the end of the URL I'm now going to be okay with there
635:57
Speaker A
being a slash or a question mark or a hash at the end of the URL all of which are valid symbols in a URL but I know from the Twitter's documentation are not part of the username all right now I'm
636:09
Speaker A
going to go ahead and run python of twitter. one final time typing in HTTPS twitter.com David M maybe with maybe without a trailing slash but hopefully with my biggest fingers crossed here I'm going to go ahead now and hit enter and
636:25
Speaker A
thankfully my username is indeed David J Ma so what more is there in the world of regular expressions and this own Library not just re. search and also re.sub there's other functions too there's re dosit via which you can split a string
636:39
Speaker A
not using a specific character or characters like a comma and a space but multiple characters as well and there's even functions like re . findall which can allow you to search for multiple copies of the same pattern in different
636:53
Speaker A
places in a string so that you can perhaps and manipulate more than just one so at the end of the day now you've really learned a whole other language like that of regular expressions and we've used them in Python but these
637:04
Speaker A
regular Expressions actually exist in so many languages too among them JavaScript and Java and Ruby and more so with this new language even though it's admittedly cryptic when you use it for the first time you have this new found ability to
637:17
Speaker A
express these patterns that again you can use to validate data to clean up data or even extract data and from any data set you might have in mind that's it for this week we will see you next time
637:35
Speaker A
[Music] [Music] all right this is cs50's Introduction to programming with python my name is David men and this is our week on objectoriented programming or oop it turns out that in the world of programming there's different paradigms of programming languages there's
638:09
Speaker A
different ways of solving problems with code and it's a little hard to see this at first if you've only learned one language but over time if and when you learn other languages besides python you'll start to notice certain patterns
638:21
Speaker A
and certain capabilities of some languages but not another thus far within the world of python you and I have largely been writing code that's procedural in nature whereby we're writing procedures we're writing functions and we're sort of doing things
638:34
Speaker A
top to bottom everything is step by step by step as you would expect in general from an algorithm but along the way we've actually dabbled in another Paradigm known as functional programming with python whereby we've been able to
638:46
Speaker A
pass functions around we even had an anonymous function some weeks ago and that's evidence of features of a functional programming language even though we've just scratched the surface thereof today we focus on another Paradigm and this one in more detail
639:00
Speaker A
namely objectoriented programming and now while some of you might have prior programming experience and have learned languages like Java which are by Design fundamentally objectoriented python indeed allows you a bit of flexibility when it comes to how you solve problems
639:14
Speaker A
with code but it turns out oop object ented programming is a pretty compelling solution to problems that you invariably encounter as your programs get longer larger and more complicated so indeed oop for our purposes is going to be a
639:28
Speaker A
solution to a problem that builds on so many of the lessons past so let's go ahead and do this let's start by writing a program very procedurally by opening up VSS code here I'm going to go ahead and create a program called student. and
639:43
Speaker A
in this program I want to do something relatively simple initially uh as we might have done some weeks ago now where I just ask a user for their name and maybe in the context of the Harry Potter Universe their house and just print out
639:56
Speaker A
where that student is from and let's gradually enhance this program by adding more and more features to it and see if we don't stumble upon problems that up until now we might not have had very elegant well-designed solutions to but
640:09
Speaker A
if we introduce explicitly object-oriented programming as a programming technique I bet we can clean up our code and set the stage for writing even more sophisticated programs longer programs down the line so in student. piy let me go ahead and do a
640:22
Speaker A
name variable setting it equal to the return value of input and just prompt the user for their name like this and then let me go ahead and do the same for a house variable and prompt the user for
640:33
Speaker A
their house using input like this and let's do something super simple now let's just go ahead and print out an F string that says something like name from house just so that I can confirm that the contents of these variables are
640:46
Speaker A
indeed as I expect I'm not do any error checking or trimming or anything like that for now I'm really just going to spit back out whatever the user just typed in all right let me go ahead and run python of studenty let's use our
640:57
Speaker A
go-to like Harry as in Harry Potter from Gryffindor and when I hit enter now let's see if I see that Harry from Gryffindor is indeed the case all right so I think we have a working program at this point but let's now introduce some
641:10
Speaker A
of those Lessons Learned way back from week zero where we started writing our own functions not necessarily because it solves the problem more correctly I dare say this is correct as is but it begins to give us building blocks that we can
641:23
Speaker A
extend so as to solve more complicated programs so let me go back up to student. and let's go ahead now and do this let's put the entire logic I just wrote inside of our typical method called Main and let me indent those
641:36
Speaker A
three lines so that at least they're now combined into one main method but instead of using input on line two and input on line three why don't we go ahead and assume for the moment that we've got some function called get name
641:48
Speaker A
in the world and let's go ahead and assume we've got another function like get house in the world that don't take parameters but their purpose in life is by their Nam going to be to get the user's name and to get their user house
641:59
Speaker A
respectively and then I'm going to print out the exact same F string as before I of course need to implement these functions now so let me go lower in my file and Define a function called get uncore name nothing in these parentheses
642:11
Speaker A
because it's not going to take a parameter and I'm going to go ahead and do something like name equals input quote unquote name just like before and then I'm going to go ahead and return name so it's a super simple function but
642:22
Speaker A
it's a an abstraction I now have a function called get name whose implementation details I don't have to care about anymore I just know that the function exists and I can tighten this up in fact I don't really need a name
642:33
Speaker A
variable on line 8 if I'm immediately going to return that same name variable on line nine so let me just tighten this up a little bit even though it doesn't change the functionality and just immediately return the return value of
642:44
Speaker A
the inputs uh function call here let's do something very similar now for get house which will similarly take no arguments I'm going to go ahead and return the return value of input this time prompting the user for their house
642:57
Speaker A
and I need one final detail at the very bottom let's continue our habit of doing if the name of this file equals equals quote unquote main then let's go ahead and actually call Main and recall that we have that in place so that if this
643:11
Speaker A
eventually becomes part of a module a library of sorts I don't accidentally call Main blindly I only do it if I mean to run main from the command line on this file all right so if I didn't make
643:23
Speaker A
any mistakes here let me go ahead and in my terminal window again run python of student. enter let's type in Harry enter let's type in Gryffindor enter and we're set Harry from Gryffindor seems to still be working so we haven't really solved
643:39
Speaker A
the problem anymore correctly but I've laid the foundation to maybe now do some more interesting things because I've have these building blocks in place all right but let me propose that we could be doing this a little bit
643:52
Speaker A
differently get name get house is fine but at the end of the day I'm really trying to get a student from the user I want their name and their house not just one or the other so maybe it would be a
644:03
Speaker A
little cleaner still to define a function called get student and let get student do all of this work for us now theoretically get student could call get name and could call get house but because these functions are so short I
644:17
Speaker A
think I'm okay with just defining one function called get student that similarly won't take any arguments but it's going to do two things it's going to get the student's name by prompting them with input as before and it's going
644:28
Speaker A
to get the student house by also prompting them as before and then now hm I want to return the student but I think I might have painted myself into a corner here because I now have two variables name and house and yet up
644:42
Speaker A
until now we've pretty much returned one or the other we've returned one value so any suggestions for how we can perhaps solve this problem that I just created for myself whereby I want to return really a student but I currently have a
644:57
Speaker A
name variable and a house variable I'd minimally like to return both of those I believe that we can return a dictionary includes the name and the house yeah so we absolutely could return a dictionary a dict object in Python whereby maybe
645:12
Speaker A
one key is name one key is house and the values thereof are exactly the values of these variables we could totally do that uh I worry that that might be getting a little complicated I wonder if there's a
645:22
Speaker A
simpler way instead any other instincts even if you're not sure it would work return both name and house return both name and house I I like the sound of that it sounds simple I don't have to figure out what a dictionary is going to
645:34
Speaker A
look like and in fact this too would be a valid approach even if you've not seen this before it turns out in Python that you can kind of return multiple values but that's a bit of a white lie or we
645:45
Speaker A
could take Muhammad's approach of actually return rning a dictionary and putting multiple keys there in so here again we have yet another example of how you can solve the same problem in at least two ways and I dare say we're
645:55
Speaker A
about to see even more so one way you could solve this problem whereby you want to return multiple values would be to do something like this I could go ahead and literally return not just name but I could put a comma and also return
646:11
Speaker A
house this is not necessarily something you can do in other languages if you have programmed in other languages before it depends on the language but it looks like thanks to this comma maybe I can in fact return two values as
646:23
Speaker A
actually proposed well if I'm returning two values in this way on line 10 how do I get both values at the same time well there's a couple of ways let me go up to my main function I know minimally I'm
646:35
Speaker A
going to have to change the get name and get house to get student but what am I going to store the return value in I think I could actually do this and we have seen this technique before where
646:45
Speaker A
you can unpack so to speak speak sequences of values that are coming back and indeed consider this to be exactly that name comma house is some kind of sequence that I'm returning of values name comma house so if I want to unpack
646:58
Speaker A
those and store the return values in two separate variables I can in fact use the commas on the left hand side of my assignment operator the equal sign to do just that now to be clear I don't need
647:09
Speaker A
to call these variables name and house here I could simplify this and use just n here and H here and then I could return just n and H but I would argue that's not very uh clear to the reader
647:22
Speaker A
as to what's going on so I think in this case even though it's a coincidence that I've used the same variable names in get student and get Main and in Maine it's a little more readable to someone like me
647:31
Speaker A
so I'm going to leave it as is well let's go ahead and see now if this works let me clear my screen down here and run python of student. enter let's again type in Harry let's again type in
647:41
Speaker A
Gryffindor enter and voila we still see that Harry is from Gryffindor but what are we actually doing here what are we actually doing by returning this value well it turns out that what we've just done is used a tupple a tupple is
647:57
Speaker A
another type of data in Python that's a collection of values X comma y or X comma y comma Z it's similar in spirit to a list in that sense but it's immutable it's not mutable now what does that mean a list as we've seen it before
648:12
Speaker A
is a data structure in Python that you can change the values of you can go into bracket zero for the first location and change the value there you can go to bracket one bracket two bracket three and actually change the values in lists
648:23
Speaker A
but if you have no intention of changing the values of variables and you want to return effectively multiple values you don't have to even return it as a list you can return it as a tle instead just by using a comma and it turns out we can
648:36
Speaker A
make explicit that here's the white lie I'm not actually returning two values per se whenever you use a comma in this way on line nine you're actually returning one one value which is a tupple inside of that tupple now are two
648:51
Speaker A
values so it's similar in spirit to returning one list with two things here I'm returning one tupple with two things and the mere fact that I've used a comma and nothing else tells python that I indeed want to return a tle but there's
649:03
Speaker A
more explicit syntax that we can use instead I can actually more verbosely put explicit parentheses around the values of this tupple just to make more clear to me to the reader that this isn't two values per se this is one
649:16
Speaker A
value with two things inside of it and what I can actually do then too is I don't have to unpack this up here so to speak I can actually go up here and maybe give a more apt name like student
649:27
Speaker A
and I can name the value or rather name the variable in which I'm storing the return value of get student as quote unquote student so maybe this is a little better design now because I'm sort of abstracting away what a student
649:40
Speaker A
is it's implemented at the moment as a tupple with two values but at least now I have a variable called what I mean a student but there's going to be a catch on line three I still want to print out
649:51
Speaker A
that Student's name and their house but I don't have a name variable anymore and I don't have a house and I also don't have a dictionary as was proposed earlier so I can't even go at those keys by name but what a tupple is it's very
650:05
Speaker A
similar in spirit to a list but it is indeed just immutable and what I mean by that is I can still index into it numerically by saying student square bracket Z for the item in the first location in that Tuple and then over
650:19
Speaker A
here instead of house I can say student bracket one student bracket one is going to give me the second location in that tupple let me go ahead and clear my terminal window again run python of student. let's type in Harry let's type
650:32
Speaker A
in Gryffindor enter and we still have some working code let me pause here now and see if there are any questions on this technique of returning a tupple and indexing into it in this way I guess what's a like a actual use case where
650:49
Speaker A
you would use a tupple versus you know a list or something else that's similar it's a really good question when would you use a tuple versus a list when you want to program defensively or in general when you know that the values in
651:01
Speaker A
this variable shouldn't change so why would you use a data type that allows them to be changed it just invites mistakes bugs down the line either by you or colleagues who are interacting with your code so tupple is just another
651:14
Speaker A
way where you can increase the probability of correctness by just not letting anyone yourself included change the contents therein so it's just another tool in your toolkit but let's make clear then what I mean by immutable again I claim that immutable means that
651:29
Speaker A
you cannot change the value well let's go ahead and try to do this let me go ahead and run this program once more as is python of student. let me go ahead and type in for instance uh how about uh
651:43
Speaker A
padma's name and I'm going to go ahead and say that padma's in Gryffindor as in the movies and we see Padma from Gryffindor but technically I went down this rabbit hole and looking at Harry Potter more closely technically in the
651:54
Speaker A
books Padma I believe was from Ravenclaw so this is actually a mistake or an inconsistency between the movies and the books let's see if we can't fix this inconsistency in our code so how about we do this if the student's name that's
652:07
Speaker A
inputed equals Padma why don't we override whatever the uh whatever the house is and change it to be properly Gryffindor let me go ahead and do if student now if I want to get at padma's name I'm going to have to do student
652:20
Speaker A
bracket zero I have to know what location the name is in in this tupple but if that in value equals equals Padma let's go ahead with this if statement and make a change let's change the students F uh bracket one value so the
652:34
Speaker A
second value if we're zero indexing let's change it to be another house in the World of Harry Potter called Ravenclaw so I'm just fixing maybe the user's input they watch the movie so they typee in Padma Gryffindor but mm-
652:47
Speaker A
the books it was Padma from Ravenclaw all right let me go ahead and go down to my terminal window clear my uh terminal and do python of student. enter I'm going to do Harry as well as Gryffindor just to demonstrate that that is still
653:00
Speaker A
working as intended Let Me Clear My screen again though and run python of studenty on Padma and I'll put her too in Gryffindor as in the movies and hit enter and now I just see a big mess of
653:12
Speaker A
errors on the screen some kind of exception has been thrown and indeed a type error has happened happened I'm using a data type wherein there's an error and what is that error well tupple object does not support item assignment
653:25
Speaker A
it's a little arcany expressed that is that's not really very user friendly but if you think about what those words mean tupple object does not support item assignment so assignment is copying from right to left so somehow that's invalid
653:37
Speaker A
and here is a manifestation of the immutability of tuples you cannot change location zero or one or anything inside that is a feature that is the design of a tuple so if I want to override that I think I'm going to have to use a
653:53
Speaker A
different type of data that we've used before namely a list and that's fine if you want to enable yourself and colleagues using your code to change the contents of that container well we can go ahead and return not a tupple using
654:06
Speaker A
explicit parentheses or no parentheses just the comma but I can use square brackets and if I'm using square brackets on the left and the right this is indeed explicitly a list same idea but it's mutable that is to say you can
654:20
Speaker A
change the contents of a list so making no other changes just returning a list with square brackets instead of a tuple with parentheses or just the comma let me go ahead now and run python of student. enter let me type in Harry and
654:35
Speaker A
Gryffindor again that's still working good to see let me run this once more and type in Padma and Gryffindor as in the movies but no now we've corrected it to be Padma from Raven claw as in the books
654:49
Speaker A
instead any questions now on tupples versus lists or this idea of immutability versus mutability uh can we use a nested tle in Pyon like a a nested lists absolutely you can have not only nested lists in Python where one of the elements in a
655:08
Speaker A
list could be another list so you have some square brackets out here you might have some other square brackets inside you can absolutely do the same with a tupple as well there's no constraint on the types of values you can put in there
655:20
Speaker A
we've not had occasion to do that in this case I'm just returning a simple uh simple tupple with two elements but yes you could absolutely do that too other questions on tles versus lists okay for example um when I see the square bracket
655:34
Speaker A
um is it mainly used for the list oh a really good question uh sort of so when you create a value like a list you use square brackets and that would indeed be a visual indicator that this is
655:46
Speaker A
definitely a list uh if you instead see parentheses that's a visual indicator when creating a value that it's definitely a tupple however somewhat confusingly both lists and topples use square brackets when you access the contents of them when you index into
656:03
Speaker A
them at location zero or location one you always use square brackets so that's the distinction there good question allow me to propose now if I may that we solve this problem yet another way and let's see if we're either making things
656:16
Speaker A
Better or For Worse than us recall that dictionaries or dict objects also exist in python and a dictionary is this collection of keys and values and the upside in particular of a dictionary is that they have better semantics right
656:29
Speaker A
you don't just have to assume that a name is always going to be at location zero house is always going to be at location one I mean that's the kind of thing especially if you had three four or more values eventually you or someone
656:40
Speaker A
is going to get confused and forget what the order is and you're going to write buggy code so a dictionary is a little more powerful and that you can semantically associate Keys like little descriptions with the values those keys
656:53
Speaker A
and those values respectively so let me go ahead and do this and we can do this in a few different ways but let me propose that we focus on get student here and let's go ahead and do this let
657:02
Speaker A
me go ahead and uh in delete the implementation of get student as is let me create a student variable and initialize it to an empty dictionary and I can do that with just two curly braces here and then let me go ahead and set
657:16
Speaker A
two keys inside of that dictionary inside of the student there will be quote unquote a name key and the value of that is going to be whatever the return value of input is when I prompt the user for their name and then the
657:29
Speaker A
house key inside of that same student dictionary is going to be the return value of whatever the user types in for their house and lastly I'm going to go ahead and return student so now I am literally returning one thing still but
657:43
Speaker A
this time it's a dict rather than a tupple rather than a list but there's still two things in it technically four things if you count the keys and the values but there's two key value pairs now my code up here is going to have to
657:56
Speaker A
change a little bit and let's simplify this and remove for instance now the the Padma if statement just to focus on what's changing at hand and let me go ahead now and leave line two alone I'm still going to have a student variable
658:08
Speaker A
that gets assigned the return value of get student but what I want to do here now is actually access the keys in inside of that dictionary not by numeric index which was for tuples and lists zero and one but by way of the keys now
658:25
Speaker A
normally I might be in the habit as I personally am of using double quotes quote unquote name inside of there and quote unquote house inside of there but before I even run this code and show you a mistake see an error on the screen
658:39
Speaker A
does anyone want to call out what I have done wrong here this is just an F string I just want to print out the value of the name key the value of the house key in this dictionary but your your audio was a little garbled
658:55
Speaker A
for us but I think I heard double quotes and single quotes so I'm going to assume that indeed you've identified precisely the issue I'm just going to confuse python right now even though this is an F string inside of Double quotes
659:06
Speaker A
prefixed with an F I can't actually use my double quotes inside my double quotes because that's going to potentially confuse python indeed if I run this program now python of student. py and hit enter I get a syntax error so the
659:18
Speaker A
program didn't even run fully it just couldn't be understood because it got confused by those double quotes So the simplest fix here would indeed just be to use not double quotes but single quotes around the keys or conversely
659:31
Speaker A
flip the double quotes on the outside to single quotes then use double quotes on the inside you just want to be consistent so a subtle detail but again this is now specific to dictionary syntax this isn't fundamental to how
659:43
Speaker A
we're solving this current problem at hand all right well let's go ahead and try this let me go ahead now and run python of student. let's go ahead and type in Harry let's type in Gryffindor and hopefully Harry is back from
659:55
Speaker A
Gryffindor no syntax errors no other errors I think I'm back in business here and what I do like to be clear about using a dictionary is that it is allowing me just better semantics again I don't have to remember memorize
660:09
Speaker A
document that zero is name one is house instead name is name and house is house it's just a little clear a little more expressive so that's generally a good thing especially if we stored more data about students than just their name in
660:22
Speaker A
their house if you had three Fields four five 10 different fields no one's going to want to remember or be able to remember forever which is zero which is one which is two and so forth better to introduce uh names like name and house
660:36
Speaker A
in this case but let me tighten this up further in indeed I'm typically in the habit of not introducing variables unnecessarily unless they make the code more readable and an alternative way to format the same code would be this
660:48
Speaker A
strictly speaking I don't need to create an empty dictionary then add one key to it then add a second key to it and then return that dictionary I can actually consolidate this all into one statement if you will let me go ahead and do this
661:03
Speaker A
let me go ahead and say name equals inputs return value house equals inputs return value and then instead of returning any variable name student which I'm going to propose doesn't need to exist anymore let me just create and
661:16
Speaker A
return the dictionary all at once let me do quote unquote name in lower case here and then the variable it's storing the user's name then quote unquote house as my second key the value of which is going to be house the variable now is
661:29
Speaker A
this better maybe maybe not maybe the first wave was a little more readable and that's totally fine to create variables if they improve the readability of your code but just know that you can also create and return a
661:40
Speaker A
dictionary on the fly like this so to speak all in one line and I think it's arguably pretty reasonable in this why it's just pretty short I probably wouldn't do this if it got longer and longer and longer I might minimally then
661:52
Speaker A
start moving my key value pairs to separate lines but this would just be a slightly more compact way of doing this as well but let me propose we do one more change let's go ahead and introduce that same special casing of Padma to fix
662:05
Speaker A
her house from Gryffindor for instance to Ravenclaw how do we do this with dictionaries well dictionaries like lists are mutable you can change what is in them just just like you can lists and how do you do that is just a little
662:19
Speaker A
different syntactically so let's go back into Main and do this fix if the student variable has a name key that equals equals Padma then indented go ahead and change the value of the house key inside of that student dictionary to be quote
662:38
Speaker A
unquote Ravenclaw instead so very similar in spirit to what we did with a list but instead of using location zero and one we're much more clearly explicitly semantically using quote unquote name and quote unquote house because you index into lists and topples
662:54
Speaker A
using numbers but you index into dictionaries using strings as I've done here all right let me go ahead and run python of studenty we'll again do Harry from Gryffindor and I think all as well let me run it one more time this time
663:09
Speaker A
with Padma who in the movies is from Gryffindor but should really be from Ravenclaw are any questions then on this progression from tuples to lists to dictionaries we haven't necessarily introduced anything new other than those tupples which have been available to us
663:27
Speaker A
all this time but the goal at the moment is just to demonstrate this distinction among these different data types and how they each work a little bit differently what if a a combination of lists is there in a tle so is the list like we
663:42
Speaker A
can change the list because tle are imut but lists are mutable correct you can change the contents of lists and you can put most anything you want in them other lists or strings as I've done integers or anything else tuples you can do the
663:57
Speaker A
exact same thing but you cannot change them once you've created them a dictionary is more like a list in that it is mutable you can change it but the way you index into a dictionary is by way of these Keys these strings as we
664:11
Speaker A
keep seeing rather than by numbers those numeric indices all right well let me propose that there is yet another way of solving this problem and indeed I would argue that there's now an opportunity to hand even though this program isn't particularly
664:28
Speaker A
complicated all I'm doing is collecting a name from the user and a uh house from the user you could imagine wanting longer term to collect even more information like the students's Patronis or magical spell or a whole bunch of
664:40
Speaker A
other information that might belong in a student and right now we're just kind of using these very general purpose data types in Python a tuple to combine some values together a list to do the same but let us change it later a dictionary
664:54
Speaker A
which is more powerful because it's a little more structured it does have keys and it has values not just values but you know what this we wouldn't have to be having this conversation if the authors of python had just given us a
665:07
Speaker A
data type called student right wouldn't it have been nice if there were just a type of variable I could create in my code called student then we wouldn't have to figure out well do we use a tuple or a list or a dictionary but
665:19
Speaker A
that's pretty reasonable right you could imagine just a how slippery of a slope that is so to speak if the creators of a language had to anticipate all the possible types of data that programmers like you and me want to store in your
665:31
Speaker A
programs so they just gave us these general purpose tools but they gave us another general purpose tool that's going to allow us to create our own data types as well and actually give them names and that uh terminology is a class
665:46
Speaker A
a class is kind of like a blueprint for pieces of data objects so to speak a class is kind of like a mold that you can define and give a name and when you use that mold or you use that blueprint
665:59
Speaker A
you get types of data that are designed exactly as you want so in short classes allow you to invent your own data types in Python and give them a name and this is a primary feature uh of objectoriented programming to be able to
666:14
Speaker A
create your own objects in this way and in the case of python and classes even give them some custom names so what does this mean in real terms well let me go ahead and come back to vs code here and
666:25
Speaker A
let me propose that we introduce a little bit of new syntax I'm going to go ahead and clear my terminal window first I'm going to go to the top of my file and I'm just going to start a thought
666:34
Speaker A
but not finish it yet I'm going to use this new keyword for classes called literally class so indeed the new keyword we're going to have here and if I go back to our slides here this this would be the official URL where you can
666:47
Speaker A
read up more on this particular feature of python in the official tutorial class is a new keyword we can use now this is coincidentally related to students because students take classes but it has nothing to do with the fact that we're
666:59
Speaker A
dealing with students class is a general purpose term in a lot of languages python among them that allow you to Define these custom containers with custom names for pieces of data so let's go back to VSS code let's use this new
667:12
Speaker A
keyword and let me propose that we create a class called student and by convention I'm going to use a capital S here and I'm going to go ahead and with a colon get to later the implementation of this class so I'm just going to use
667:25
Speaker A
dot dot dot which is a valid placeholder for now that just indicates to me that I'm going to come back to implementing this later but as of now it does in fact exist I now have a student uh class
667:37
Speaker A
defined for me that I can now use in my code here how am I going to use it well first of all let me go down to get student and let me change this code to no longer use a dictionary but to use
667:49
Speaker A
this class I'm going to do this I'm going to give myself a variable called student as I've done before but I'm going to set it equal to Capital student open parenthesis close parenthesis so I'm going to do what appears to be
668:02
Speaker A
calling a function and that function student with a capital S notice matches the name that I gave this class at the top of my file all right what do I next want to do I'm going to go ahead and
668:14
Speaker A
give this student a name now if if I were still using a dictionary I would say student quote unquote name using square brackets but this is not a dictionary it turns out classes have what for now we'll call attributes
668:28
Speaker A
properties of sorts that allow you to specify values inside of them in the Syntax for that happens to be a DOT we've seen dots before we've used it in the context of modules and libraries more generally this is another similar
668:39
Speaker A
INSP Spirit use of a DOT that allows you to get at something inside of something else so student. name is going to be the syntax I use for giving this student a name and that name is going to be
668:51
Speaker A
whatever the return value of name is and then I'm going to go ahead and say student.h house to give another attribute called house and give that the return value of input here prompting the user for house and then as before I'm
669:04
Speaker A
just going to return student but now what's really powerful about class and objectoriented programming more generally is that I've created this custom data type called literally student capital S I've stored one such student in a variable like I can always
669:20
Speaker A
do in a variable called student lowercase s but I could call it anything I want I just makes sense to call it student as well but lowercase for clarity and then I'm returning that variable and because of my syntax in
669:31
Speaker A
lines 14 and 15 that has the result of putting inside of that class a name attribute and a house attribute I just need to make one more change up here I'm going to go ahead and remove our Padma
669:45
Speaker A
code just so we can focus only on what's new rather than fixing her house and I'm going to go in here and change the syntax that previously was for dictionaries again dictionaries use square brackets and then strings in
669:58
Speaker A
quotes either single quotes or double quotes depending on the context here though I'm going to change this to be student. name and over here I'm going to change it to be student. house and that's just going to be my new syntax
670:11
Speaker A
for getting the contents of what appears to be a class called student let me go ahead and rerun python of student. by enter let's type in Harry's name as before let's put him in Gryffindor crossing our fingers as we often do and
670:25
Speaker A
Harry is indeed from Gryffindor what though have I done let's introduce one other bit of terminology here it turns out that I can create a class using that class keyword but anytime you use a class you're creating what are called objects and here is the
670:42
Speaker A
word objects as in objectoriented programming or oop let me go back to my code here and even though I haven't really implemented much of it at all I literally just left it with a dot dot dot that's enough code lines one and two
670:55
Speaker A
to just invent a new data type called student capital s that may or may not have some future functionality as well that's enough to create a class what though am I doing on line 11 on line 11 what I'm technically doing is creating
671:09
Speaker A
an object of that class so this too is another term of art you create objects from classes so if we go back to that metaphor that a class is like a blueprint for a house or a class is like
671:22
Speaker A
a mold an object is when you use that blueprint to build a specific house or something that comes out of in plaster the mold when you actually use that mold to create such an object so a class is
671:34
Speaker A
again the definition of a new data type the object is the Incarnation of or technically instantiation of and another term for objects would actually be an instance you have instances of classes as well so that's a lot of vocabulary
671:49
Speaker A
but at the end of the day it just boils down to this you can Define your own class which is really your own data type you can then store attributes inside of it using this dot notation here and then
671:59
Speaker A
you can access those same attributes using Code like this here and now I have a proper student data type and I don't have to kind of hack something together using a tupple or a list or even a dictionary I now have a proper data type
672:13
Speaker A
called student that the authors of python didn't give me I gave myself any questions now on classes this new keyword class or this idea of these objects or instances thereof is the class object mutable or immutable a good
672:31
Speaker A
question and we've clearly laid the stage for having that conversation about every data type now we will see that they are mutable but you can make them immutable so you can get the best of both worlds Now by writing some actual
672:43
Speaker A
code and we'll write more code than the DOT dot dot in just a bit other questions on classes or these objects thereof then what would be the properties of those glasses uh so at the moment the properties of or the
672:56
Speaker A
attributes of as I've been calling them thus far would just be name and house it turns out that there may very well be other attributes built into classes that we may see before long but for now the only two attributes that I care about
673:08
Speaker A
are the ones that I myself created namely name and house are again what I would call attributes and in a little bit we're going to start calling those same attributes more technically instance variables name and house as I've presented them here in VSS code are
673:23
Speaker A
really just variables called name and called house inside of an object whose type is student all right so what more can we do with these classes well again online 11 is where we're instantiating an object of the student class and
673:40
Speaker A
assigning it to a student variable we're then adding attributes name and house respectively on lines 12 and 13 currently both of those have values that are technically strings or stirs because that's what the return value of input is
673:53
Speaker A
but those attributes values could actually be any data type we're just keeping things simple and focusing on defining students in terms of two strings name and house and then on line 14 we're returning that variable we're returning that object to main so that we
674:07
Speaker A
can actually print out who is from what house well let's go ahead and add a bit more functionality here because right now on lines 12 and 13 this is a little manual and it's a little reckless of me
674:18
Speaker A
to just be putting anything I want inside of this student object it turns out with classes unlike with dictionaries we can actually standardize all the more what those attributes can be and how what kinds of values you can
674:31
Speaker A
set them to so let me go ahead and do this let me propose that it would actually be really nice if instead of doing this here let me go ahead and simplify my code as follows let me go
674:43
Speaker A
ahead and give myself a local variable called name and set it equal to the return value of input like we've done many times now already let me give myself one other variable for now called house and set it equal to the return
674:53
Speaker A
value of input as well prompting the user for their house and now instead of creating a student object from my student class and then manually putting the name attribute inside of it and the house attribute inside of it let me
675:09
Speaker A
actually do something more powerful let me do this let me call that student function which is identical to the class name just by defining a class you get a function whose name is identical to the class name with the capital letter
675:24
Speaker A
included but instead of just doing open parenthesis close parenthesis let me pass in the name that I want to fill this this object with and the house that I want to put in that object as well and now let me set the return value as
675:37
Speaker A
before to be student equals like this so what have I done that's different fundamentally I'm still getting user input in the same same way I'm using input on line 11 and input on line 12 and I just so happen to be storing those
675:50
Speaker A
return values in local variables but now now we're setting the stage for the more powerful features of classes and object-oriented programming more generally notice that I'm deliberately passing to this capital S student function name comma house I'm passing in
676:06
Speaker A
arguments to the function now the student class is not going to know what to do with those yet but now I'm sort of standardizing how I'm passing data into this student class and ultimately it's going to give me an opportunity to error
676:20
Speaker A
check those inputs to make sure that the name is valid that it has a value and it's not just the user hitting enter it's going to allow me to ensure that it's a valid house that it's Gryffindor or Hufflepuff or Ravenclaw or Slytherin
676:31
Speaker A
or not just hitting enter or some random value that the user types in because I'm passing name and house to the student class this particular function I'm going to have more control over the correctness of my data so let's now go
676:44
Speaker A
up to the student class which up until now I left as just dot dot dot it turns out that in the context of classes there are a number of not just uh attributes or instance variables that you can put
676:57
Speaker A
inside but also methods classes come with certain methods or functions inside of them that you can Define and they just behave in a special way by nature of how python works these functions allow you to determine behavior in a
677:14
Speaker A
standard way they are indeed special methods in that sense now what do I mean by this well let me go back to vs code here and let me propose that I start to define a standard function called uh
677:26
Speaker A
underscore underscore or Dunder as it's abbreviated in it underscore underscore and then I'm going to go ahead and do open parenthesis and then I'm going to put in here literally the word self more on that in just a moment but now inside
677:41
Speaker A
of this function I'm going to have an opportunity to customize is this uh classes objects that is to say this underscore uncore init method or Dunder init method is specifically known as an instance method and it's called exactly
677:58
Speaker A
this this is designed by the authors of python and if you want to initialize the contents of an object from a class you define this method and we'll see what it's about to do here let me go back to
678:10
Speaker A
vs code and let me do something like this self. name equals name and self.
678:18
Speaker A
house equals house but I don't want to just init this object very generically I want this method called in it to take in not just self but name comma house as well now what in the world is going on
678:32
Speaker A
because there's a lot of weird syntax here there's this Dunder init method double underscore init double underscore there's all of a sudden this parameter called self and then there's this new syntax self. name and self. house now you're seeing really a manifestation of
678:47
Speaker A
objectoriented programming it's not all that different fundamentally from what we've been doing for weeks with dictionaries by adding keys to dictionaries but in this case we're adding variables to objects AKA instance variables to objects now what's going on
679:03
Speaker A
let's do this in Reverse let's go back to the line of code we wrote earlier on line 15 I am treating the name of this class student with a capital S as a function and I am passing in two values
679:16
Speaker A
name and house what I've highlighted here on the screen on line 15 is generally known as a Constructor call this is a line of code that is going to construct a student object for me using synonyms it is going to instantiate a
679:32
Speaker A
student object for me and again how is it going to create that object it's going to use the student class as a template as a mold of sorts so that every student is structured the same every student is going to have a name
679:46
Speaker A
every student's going to have a house but because I can pass in arguments to this student function capital S I'm going to be able to customize the contents of that object so if you think about the real world if you've ever been
680:01
Speaker A
on a street or a neighborhood where all of the houses kind of look the same but they're might be painted differently they might be decorated a little bit differently on the outside all of those houses might have been built using the
680:12
Speaker A
exact same blueprint sort of a mold if you will but then you can specialize exactly the finer points of those houses by painting the outside a different color or planting different trees you can style them differently similar uh in
680:26
Speaker A
spirit here we have a student blueprint that's always going to have now a name and a house but it's up to you and me to pass in any name in any house that we want now where is this function the fact
680:38
Speaker A
that I'm calling student capital S and then a parenthesis and a Clos parenthesis with arguments inside suggest that there's a function somewhere in the world that has been defined with def that's going to be called well as you might have guessed by
680:51
Speaker A
now the function that will always be called by definition of how python classes work is a function called double underscore in it double underscore why it's a crazy name but it's what the authors of python chose to just
681:06
Speaker A
implement the initialization of an object in Python now the only weird thing especially weird thing I will admit is this it would be way clearer to me too if the only two parameters for in it were just name comma house right that's how we've
681:23
Speaker A
defined every function thus far in the class you just specify the parameters that you want the function to accept and indeed that lines up with what I'm doing on line 15 I am only passing in two things to the student function but it
681:37
Speaker A
turns out that the authors of python need to give us a little bit of help here because suppose that you pass in name and house to this init method and a method is just a function inside of a
681:49
Speaker A
class what are you going to do with the name in the house like literally where are you going to put them if you want to remember the name in the house for this student you've got to be able to store
681:59
Speaker A
those values somewhere and how do you store them in the current object that has just been instantiated well the authors of python decided that the convention is going to be that this init method also semi secretly takes a third argument that has
682:15
Speaker A
to come first by convention it's called self but you could call it technically anything you want but the convention is to always call it self and self as its name implies gives you access to the current object that was just created
682:29
Speaker A
what does that mean again now on line 14 now that it's moved down a little bit this line here is a Constructor it constructs a student object but there's nothing in that object initially there's no name there's no house but the object
682:43
Speaker A
exists in the computer's memory it's up to now you to store the name and the house inside of that object how do you do that well python will just automatically call this init method for you and it's going to automatically pass
682:55
Speaker A
in a reference to a an argument that represents the current object that it just constructed in memory for you and it's up to you to populate it with values and what this means is that inside of your init method you can
683:10
Speaker A
literally do self. name to create a new attribute AKA an instance variable inside of that otherwise empty object and put this name inside of it it allows you to do self. house and store that value of house now you could call these
683:25
Speaker A
things anything you want they could be n they could be H as before but that's really not very self uh explanatory much better to do this kind of convention self. name equals name self. house equals house and this is like installing
683:40
Speaker A
into the otherwise empty object the value name and house and storing them in really identically named instance variables in the object and again an object is just an instance of a class now I know that was a lot of vocabulary
683:55
Speaker A
that's a lot of weird syntax so any questions on this init method whose purpose in life again is to initialize an otherwise empty object when you first create it so what is the difference between the init method and default
684:09
Speaker A
Constructor a good question so in other languages if you programed before for instance Java there are functions that are explicitly called Constructors that indeed construct an object they initialize it with values python technically calls this init method the
684:24
Speaker A
initialization method it initializes the value it's on line 14 uh line 15 now of my code if I scroll back down that I'm technically constructing the object it turns out there's another special method in Python that we won't talk about in
684:38
Speaker A
detail today called underscore underscore new underscore underscore that actually handles the process of creating an empty object in memory for us but generally speaking you the programmer don't need to manipulate the new function it just works for you
684:53
Speaker A
instead you define your own init method here an init function inside of your class and that method initializes the contents of the object so there's technically a distinction between constructing the object with new and initializing it within it but in the
685:07
Speaker A
world of python you pretty much only worry about the init method python generally does the other part for you a good question others uh what about if you want to store more than one name or more than one house a good question if
685:21
Speaker A
you want to store more than one name or more than one house you can do this in different ways you could create other attributes technically called instance variables like self. name one self. name two but we've seen in the past that that
685:35
Speaker A
is not a very good design just to have multiple variables to store multiple things maybe instead you have an instance variable called self. names plural and you set it equal to a list of names or a list of houses now in this
685:49
Speaker A
case I don't think that really solves the problem because I'm trying to implement a student singular so it doesn't really make sense to have multiple first names maybe a nickname maybe a last name so we could add those
685:58
Speaker A
to but I don't think we need multiple names per se and in this case multiple houses but absolutely you could do that using some of our familiar building blocks like lists other questions how are classes or objects represented in
686:11
Speaker A
memory how are classes and objects represented in memory so the class is technically just code it is the code on the top of my file lines one through four that defines that blueprint that template if you will um objects are
686:25
Speaker A
stored in the computer's memory by taking up some number of bytes so you're probably familiar with bytes or kilobytes or megabytes there's some chunk of bytes probably all in the same location in the computer's memory or Ram where those V where those objects are
686:39
Speaker A
stored but that's what python the program handles for you python The Interpreter figures out where in the computer's memory to put it you and I the programmers get to think and solve problems at this level python The Interpreter handles those lower level
686:53
Speaker A
details for you how about one final question on classes and objects now my question is if we can the same do the same thing with the dictionary so I to use classes good question if you can do the same things as you can with
687:06
Speaker A
dictionaries why should you use classes because we are just scratching the surface now of what you can do with classes allow me to go back now to my keyboard and show you more of what you can do with classes but in short you can
687:18
Speaker A
do much more with classes you can ensure the correctness of your data much more with classes you can error check things and generally you can design more complicated software more effectively and we'll continue to see today features of python and object-oriented
687:33
Speaker A
programming more generally that allows us to do just that so let me propose in fact that first let's just tighten up this current implementation which again has us with an init method that just declares two instance variables self.
687:47
Speaker A
name and self. house which again just creates those variables inside of the otherwise empty object and assigns them values name and house respectively let me go ahead and just do one little thing here I don't really need the student
687:59
Speaker A
variable let me just tighten this up so that each time we improve or change the code we're focusing really on just the minimal changes alone so I've not fundamentally done anything different I just got rid of the variable name and
688:11
Speaker A
I'm just returning the return value of this student function that's constructing my new object for me so I'm just tightening things up as we've done many times in the past well what if something goes wrong when in creating
688:24
Speaker A
this student for instance what if the user does not give us a name and they just hit enter when prompted for name like I don't want to put in my computer's memory a sort of bogus student object that has no name right
688:36
Speaker A
I'd ideally like to check for errors before I even create it so I don't create a nameless student it would just be weird and probably a bug to have an object that has no name similarly I don't want the user to be able to type
688:48
Speaker A
in something random as their house at least in the World of Harry Potter there's really only four houses at Hogwarts at least or there's again Gryffindor and Hufflepuff and Ravenclaw and Slytherin a list of four valid houses it would be nice if I somehow
689:03
Speaker A
validated that the user's input is indeed in that list now I could do all of that validation in my get student function I could check is the name empty if so so don't create the student object is the house one of those four houses if
689:19
Speaker A
not don't create the student object but that would be rather decoupled from the student itself right get student currently exists as just my own function in my student. py file but classes and really object-oriented programming more generally encourages you to encapsulate
689:36
Speaker A
inside of a class all functionality related to that class so if you want to validate that a name exists if you want to validate that a house is correct that belongs just uh fundamentally in the class called student itself not in some
689:52
Speaker A
random function that you wrote elsewhere again this is just methodology because again if we think about writing code that gets longer and longer more and more complicated it should make just intuitive sense that if you keep all the
690:04
Speaker A
house and all of the Stu all of the name and all of the house related code in the student it's just better organization right keep all of the related code together and that's probably going to set you up for more success and indeed
690:15
Speaker A
that's part of this methodology of objectoriented programming let me go ahead now and change my students classes init method to do this if the name is blank so if not name and we've seen this kind of syntax before if you say in
690:32
Speaker A
Python pythonic if not name that's like doing something like this if name equals equals quote unquote but I can do this a little more elegantly just say if not name would be the more pythonic way to do it well I want to return an error
690:47
Speaker A
like I might want to do something like this print missing name but this is not good enough it does not suffice to just print out missing name and then let the rest of the code go through all right
690:58
Speaker A
well what could I do instead in the past we've seen another technique I could do cy. exit and I could say something like missing name and I could go up here and I could import CIS but this is a really
691:08
Speaker A
obnoxious solution to the problem just because you or maybe a colleague messed up and called a fun with an invalid name you're going to quit my whole program like that's really really extreme of a response and you probably don't want to
691:23
Speaker A
do that if your program's in the middle of running you might want to clean some stuff up you might want to save files you don't want to just exit a program sometimes in some arbitrary line just because input was invalid so I don't
691:33
Speaker A
think we want to do that either but we do now have a mechanism for signaling errors unfortunately I can't do something like this I could try returning none and say uh this student does not exist I'm going to hand you
691:46
Speaker A
back none instead but it's too late if we scroll back down to where I'm creating the student it's on line 17 now where I've highlighted this code the student has already been created there is an object somewhere in the computer's
692:00
Speaker A
memory that's structured as a student it just doesn't have any values inside of it but it's too late therefore to return none that ship has sailed the object exists you can't just suddenly say nope nope there is no object there is an
692:13
Speaker A
object it's up to to you to Signal an error and how do you signal an error well we've actually seen this before but we haven't had occasion to create our own errors it turns out in Python there's another keyword related to
692:26
Speaker A
exceptions that python itself uses to raise all of those exceptions we've talked about in the past when you've caught things like value errors or other such exceptions that come with python well it turns out you the programmer can
692:40
Speaker A
raise that is create your own exceptions when something just really goes wrong not wrong enough that you want to quit and exit the whole program but enough that you need to somehow alert the programmer that there has been an error
692:52
Speaker A
something exceptional in a very bad way something exceptional has happened and let them try to catch that exception as needed so let me go back to vs code here and propose that if the user passes in an invalid name it's just empty so
693:08
Speaker A
there's not a name well what I really want to do is this I want to raise a value error and we've seen the value errors before we've created value errors accidentally before and generally you and I have tried to catch them if they
693:23
Speaker A
happen well the flip side of this feature of exceptions in a language like python is that you the programmer can also raise exceptions when something exceptional happens and you can even be more precise you don't have to raise a
693:34
Speaker A
generic value error and let the programmer figure out what went wrong you can treat value error and all exceptions in Python like functions and actually pass to them an explanatory message like quote unquote missing name so that at least the programmer when
693:49
Speaker A
they encounter this error knows oh I messed up I didn't make sure that the user has a name and now what do you want to do instead well now if you're the programmer you could do something like this you could try to create a student
694:04
Speaker A
except if there's a value error then you could handle it in some way and I'm going to wave my hand with a dot dot dot at how you would handle it but you would handle it using try and accept just like
694:15
Speaker A
we have in the past and that would allow you the programmer to try to create the student but if something goes wrong okay okay I'll handle it nonetheless so what's new here again is this raise keyword that just lets you and I
694:29
Speaker A
actually raise our own exceptions to Signal these errors well let me go back to my code here and I'm just going to go ahead and not bother trying or catching this error for now we'll just focus on raising it and assume that from our week
694:41
Speaker A
on exceptions you could add try and accept as needed in places let me go back to the code here and propose that something else could go wrong with house right if there is a name we're good but if we're given a house but it's invalid
694:54
Speaker A
we should probably raise an exception for that too so what if we do this if house is not in the list containing Gryffindor quote unquote uh Hufflepuff quote unquote uh let's see Ravenclaw quote unquote or uh Slytherin quote
695:11
Speaker A
unquote then with my colon let's ra raise another type of value error but rather than raise a generic value error let's pass in an argument quote unquote invalid house and so here we now see a capability that we can do with classes
695:26
Speaker A
that we can't with dictionaries if you add an attribute to a dictionary a key to a dictionary it's going in no matter what even if the name is empty even if the house is a completely random string of text that's not one of these four
695:39
Speaker A
houses it's going into that dictionary but with the class and by way of this init method you and I can now control exactly what's going to be installed if you will inside of this object you have a little more control now over
695:53
Speaker A
correctness and so now let me go ahead and uh scroll back down to my terminal window and clear it let me run python of student. let me type in something like Harry let me type in Gryffindor enter and we see that indeed Harry is from
696:07
Speaker A
Gryffindor what if I made a mistake though what if I ran python of student.
696:11
Speaker A
and typed Harry as the name but at this time typed in number four Private Drive which is where he grew up instead of his proper Hogwarts house let me hit enter now and now you see a value error but
696:23
Speaker A
this isn't one that python generated for us per se I raised this error and therefore if I went in and wrote more code in my get student function I could also catch this error with our usual try except syntax so all we have now is not
696:37
Speaker A
just classes in our toolkit but even more Powers when it comes to exceptions and not just catching them ourselves but raising them ourselves too any questions now on this use of class isn't in it and now this ability to raise exceptions
696:55
Speaker A
when something goes wrong inside of the initialization so what if user has a middle name name middle name and last name how would you fix that a good question if you wanted the user to if you wanted the student to have a first
697:09
Speaker A
name middle name and last name we could do this in a bunch of different ways the simplest though if Let Me Clear My screen here and let me just temporarily do this let me propose that the init method take in a first argument a middle
697:22
Speaker A
argument and a last argument and then what I think I would do down here is ultimately have first equals first and then I would do the same thing for middle and last so middle and middle and then last and last and then what I would
697:38
Speaker A
have to do here is when I actually ask the user for their name I might need to really go all out I might need to ask them first for their first name and store that in a variable called First
697:49
Speaker A
and therefore pass in first I might similarly need to ask them for their middle name and store that in a variable and then pass in a second argument middle and then lastly if you will let me go ahead and create a third variable
698:01
Speaker A
called last get the input for their last name and pass that in as well I could instead just use one input and just ask them for their whole name so type in David uh ma enter or David J me all
698:14
Speaker A
three of them and maybe I could use Python split function maybe a regular expression to tease it apart that's probably going to be messy because there's going to be people who don't have just two or three names they might
698:24
Speaker A
have four or five so maybe sometimes it's better to have multiple prompts but that's not a problem because with a class we have the expressiveness to take in more arguments if we want we could even take a list if we wanted but I
698:36
Speaker A
think we'd probably want to have even more error checking then not just for name but for first and then maybe for middle and then maybe for last so it just is more and more code though there would be ways to perhaps consolidate
698:48
Speaker A
that too let me undo all of that and see if there are other questions now on classes I assume this is classes are something I might do at the beginning of a project can I just put them in a
698:59
Speaker A
different file and import them into my project or or or my main code as needed absolutely a really good question you could imagine wanting to use this student class not just in studenty but in other files or other projects of
699:12
Speaker A
yours and absolutely you can create your own library of classes by putting the student class in your own module or package per our discussion in the past about libraries more generally and absolutely you can do that and later
699:24
Speaker A
today will we see that we've actually been using classes you and I before in thirdparty library so you too can absolutely do the same how about one more question on classes can you have optional variables in classes and two
699:39
Speaker A
can you have your own error names like let's be egotistic and say I when AR raise Eric eror short answer yes so you can uh these init functions are just like python functions more generally even though they're special and that
699:53
Speaker A
they're going to get called automatically by python 4 you but if you wanted to make house optional you could do something like this you could give it a default value in the init functions uh signature so to speak in that first line
700:05
Speaker A
of code on line two and that would allow me to not have to pass in house in this case I'm going to continue to always pass in name and house but you could make things optional and yes to your
700:14
Speaker A
second question if you wanted to have your own error message like an Eric error you could actually create your own Eric error exception and we'll see in a little bit that there's actually a whole Suite of exceptions that exist and you
700:27
Speaker A
too can invent those as well let me propose though that we now introduce one other aspect of this whereby we try printing out what a student looks like at the moment if I scroll back down to my main function I'm still printing the
700:42
Speaker A
student's name and house very manually I'm going inside of the object doing student. name and I'm going inside of the object again and getting student.
700:49
Speaker A
house just to see where uh the student is from but wouldn't it be nice if I could just print the student like I've been printing for weeks any int or float or stir or any other data type well
701:02
Speaker A
let's see what happens if I just try printing the student instead of manually going inside and trying to create that sentence myself well in my terminal window let me go ahead and run python of student. py again let me type in Harry
701:13
Speaker A
let me type in Gryffindor and we voila Harry whoa okay main student object at o x102 733 e80 well what is going on well if you were to run the same code you might actually see something different on your
701:27
Speaker A
computer in terms of that number but what you're really seeing is the underlying representation as a string of this specific object in particular you're seeing where in the computer's memory it is this number o x102 733 e80 refers to essentially a specific
701:44
Speaker A
location in the computer's memory or Ram that's not really that interesting for me or you or generally speaking programmers but it's just a default way of describing via print what this thing uh is but I can override this as well it
702:00
Speaker A
turns out that there are other special methods in Python when it comes to classes not just underscore underscore in it uncore underscore But continuing in that same pattern underscore uncore stir underscore underscore so this too is a special method that if you define
702:17
Speaker A
it inside of your class python will just automatically call this function for you anytime some other function wants to see your object as a string print wants to see your fun your object as a string but by default if you don't have this method
702:34
Speaker A
defined in your class it's going to print out that very ugly esoteric Incarnation thereof where it says main.
702:39
Speaker A
student object at Ox dot dot dot well how can I then Define my own stir function well here back in VSS code let me propose that I go in and Define not just underscore underscore uh in it but
702:53
Speaker A
let me Define a second function in this class here as follows def underscore underscore stir underscore underscore there are indeed two even though the font in VSS code is putting the two underscore so close it just looks like a
703:05
Speaker A
longer underscore there are indeed two there on the left and the right just like for in it this one only takes one argument that by convention is always called self so that you have access to it and then indented below that after a
703:19
Speaker A
colon I'm going to go ahead and create a format string and return it so let me go ahead and return how about something generic first like a student so I'm not going to bother even trying to figure out what this Student's name or house is
703:32
Speaker A
I'm just going to always return a student let me go back now to my earlier code which has print student on line 16 Let Me Clear My terminal window and rerun python of student upy enter type in Harry type in Gryffindor last time I
703:47
Speaker A
saw that very cryptic output this time I see more generically a student you know more readable but not very enlightening which student is this well notice that the uh double underscore stur method takes in this self argument by default
704:04
Speaker A
it's just the way the python authors designed this method it will always be passed a reference to the current student object what do I mean by that when this line of code on line six is called print because it's hoping it's
704:19
Speaker A
going to get a string is going to trigger the underscore uncore stir underscore uncore method to be called and python for you automatically is going to pass into that method a reference to the object that's trying to be printed so that you the programmer
704:35
Speaker A
can do something like this here's an F string with double quotes as usual I'm going to use some curly braces and say print out self. name name from self house so there's nothing new in what I've just done it's just an F string an
704:51
Speaker A
F on the beginning two double quotes a couple of pairs of curly braces but because automatically this stir method gets past self so to speak a reference to the current object I can go inside of that object and grab the name I can go
705:05
Speaker A
inside that object again and grab the house so now when I go back to my terminal window previously it just printed out a student but but now if I run python of student. py enter type in Harry type in Gryffindor and one more
705:19
Speaker A
time hit enter Harry is again from Gryffindor but if I run this yet again let's for instance do Draco is from Slytherin enter Draco from Slytherin now it's customized to the specific object that we're trying to print questions on
705:38
Speaker A
this function here this thunder stir method is there anything else that the uncore uncore stir method can do um the other question is what's the difference between stir and repper a good question so there are many other methods that
705:55
Speaker A
come with python classes that start with underscore underscore we're just scratching the surface and we'll pretty much Focus primarily on these but yes there are many others and we'll see at least one other in just a little bit
706:05
Speaker A
there is an among the others is indeed one called uh repper which is a representation of the Python object generally speaking the _ uncore rcore uncore method is meant for developers eyes it typically has more information than Harry from Gryffindor it would also
706:21
Speaker A
say what type of object it is like a student capital S whereas underscore uncore stir underscore uncore is generally meant for users uh the users of the program and it's meant to be even more userfriendly but both of those can
706:34
Speaker A
be overridden as you see fit well let me propose now that we pick up where we've left off on student and just add even more functionality but not just these speci methods like double underscore init and double underscore stir like
706:47
Speaker A
let's create our own methods because there in lies the real power and flexibility of classes if you and I as the programmers can invent new functionality that's specific to students for instance uh students at Hogwarts over the time in in school
707:01
Speaker A
learn how to cast a certain type of spell so when they say expecto patronum something comes out of their wand that typically resembles an animal or something like that it's a special spell that they have to practice and practice
707:12
Speaker A
so let's see if if we can't store not just a student's name and their house but also their Patronus what actually they conjure when using this spell well let me go ahead and clear my terminal window and in the top of my code here in
707:25
Speaker A
the init method of student let me go ahead and start expecting a third argument in addition to self which automatically gets passed in called petronis and I'm not going to worry uh for now on validating the petronis from
707:39
Speaker A
an official list of valid patronises or petroni I'm instead going to go ahead and just blindly assign it to self.
707:46
Speaker A
Patronis equals petronis and we're going to let the user type whatever they want for now but I could certainly add more error checking if I wanted to limit the patronises to a specific list of them here let me go ahead now and prompt the
707:59
Speaker A
user for this petronis as by in my get student method uh get student function defining a variable called petronis or anything else prompting the user for input for their petronis and now I'm going to go ahead and pass in that third
708:13
Speaker A
variable here so again similar in spirit to just adding more and more attributes to the class I'm going to pass in all three of these values instead of just two I'm not going to do anything interesting with that value yet but just
708:24
Speaker A
to make sure I haven't made things worse by breaking my code let me run python of studenty I'll type in Harry I'll type in Gryffindor and it turns out his Patronis was a stag and hit enter I haven't seen
708:36
Speaker A
what his Patronus is in my output because I didn't change my stir method yet but at least I don't have any syntax error so at least I've not made anything worse but suppose now I want to have functionality not just for initializing
708:49
Speaker A
a student and printing out a student if my class is really meant to be a student what I can do is not just remember information about data about students what's powerful about classes unlike dictionaries alone is that classes can
709:05
Speaker A
have not just variables or instance variables so to speak those attributes we keep creating they can also have functions built in AKA methods when a function is inside of a class it's called a method but it's still just a
709:19
Speaker A
function at this point we've seen two functions already two methods called uh double underscore init and double underscore stir but those are special methods in that they just work if you define them python calls them automatically for you but what if you
709:34
Speaker A
wanted to create more functionality for a student so that your class really represents this real world or maybe fantasy world notion of a student where students not only have names and houses and patronises they also have functionality they have actions they can
709:50
Speaker A
perform like casting a charm a spell magically could we Implement therefore a function called charm that actually uh uses uh their magical knowledge well let's go ahead and Define our very own function as follows Let Me Clear My
710:06
Speaker A
terminal window scroll back up to my student class and instead of creating yet another function that's special with double underscores I'm going to invent my own function or method inside of this class I want to give uh Harry and
710:21
Speaker A
Hermione and and all of the other students the ability to cast charms so I'm going to define a function that I can completely on my own called charm I could call this function anything I want but because it's a method inside of a
710:33
Speaker A
class the convention is that it's always going to take at least one argument called self by convention so that you have access to the current object even if you don't plan to use it per se all right let me go ahead and propose that
710:46
Speaker A
we Implement charm in such a way that the method returns an emoji that's appropriate for each student's petronis all right how to implement this well inside of the charm method let's go ahead and match on self. Patronis which
711:01
Speaker A
is the instance variable containing a string that represents each student's Patronis and in the case that it matches a stag for instance for Harry let's go ahead and return maybe the closest Emoji this horse here how about in the case of
711:15
Speaker A
an otter well in that case let's go ahead and return oh maybe the closest match to the otter which might be this Emoji here and let's see in the case of a for Fon rather than Herm a Jack
711:29
Speaker A
Russell Terrier let's go ahead and return how about don't have as many options here why don't we go ahead and return the cutest available dog in that case and in the case of no Patronis recognized as might cover
711:47
Speaker A
someone like Draco let's go ahead and use a default case using the underscore as as in the past and let's go ahead and return for this oh what should happen if someone doesn't have a petronis why don't we just see a magical wand that
711:58
Speaker A
seems to fizzle out as in this case all right well now rather than just print the student let's go about printing their actual Patronis so I'm going to go down to my main function here I'm going to still get a student using the get
712:10
Speaker A
student function but rather than print student let's go ahead and declare expecto patronum printing out just that as pure text and now let's go ahead and print out not the student but rather the return value of their own charm Method
712:26
Speaker A
All right so let me go back down to my terminal window and run python of student. py and enter name let's start with Harry he lives in Gryffindor uh petronis is a stag and let's see expecto patronum and of course we see the Stag
712:41
Speaker A
emoji what about someone like Draco who at least in the books doesn't have a known petronis well let's go ahead and clear my terminal window rerun python of student. and this time let's type in Draco for name Slytherin for house and
712:56
Speaker A
Patronis is unknown so I'm just going to go ahead and hit enter and now expect o patronum and just kind of sizzles instead questions now on what I've done by implementing this charm method can we uh like call a method outside the
713:15
Speaker A
function absolutely and we're seeing that already if I scroll back down to my main function which is outside of the class because it's all the way down in the file it's all left align just like the class notice on line 28 I'm calling
713:28
Speaker A
student. charm and I'm accessing a method that's inside of the student object even though my main function is outside of the class and what's different between our init function or method and our stir method that we've seen before those are
713:46
Speaker A
called automatically when you try to create a student or when you try to print a student for the first time we're now seeing a method that I invented inside of the student class that I can call anywhere I want and if I'm calling
713:58
Speaker A
it outside of the class like I am here I just use the name of the variable containing that student object and I just do charm just like I could access the individual attributes or in instance variables inside of that object as well
714:13
Speaker A
other questions on classes and this new method charm in a parentheses you are you put self supposed to be like a initializer but like in the top part you didn't you didn't um Define it the same way would you have to put the class on
714:31
Speaker A
why you didn't put the class right there so notice the indentation here so on line one I've of course said class student colon and then everything below that is indented at the moment that means that my init method my my stir
714:43
Speaker A
method and this new charm method are all inside of part of that class by convention then each of these methods inside of a class should expect that python will automatically pass in at least one argument to every method in a
714:58
Speaker A
class and that argument will always be a reference to the current object the Harry object or the Draco object that is currently trying to cast a charm or be printed so whenever you create a method inside of a class you should always have
715:14
Speaker A
it take at least one argument called self and then zero or more other arguments that are entirely up to you in it for instance takes three more name house Patronis stir takes zero more charm takes zero more but the convention
715:27
Speaker A
is to always call that default argument self and python just automatically gives you access to the current object other questions how about one more on classes and charms sir I just wanted to ask that uh you you have put
715:43
Speaker A
the emojis in double quotes So does it take the Emojis as a form of strings or something else yes if unfamiliar an emoji is just a character it's part of a mapping of numbers to letters known as Unicode and so whenever you see these
716:00
Speaker A
emoji on the screen like the horse or the otter or the dog here specifically that's really just like a key from your keyboard you and I on Max and PCs can't typically type it because you see English characters or some other human
716:12
Speaker A
language but Emoji are increasingly available uh via menus and drop down and in my case copy paste on Macs and PCs and Android devices and iPhones they are just characters even though they look like pictures you can think of it like a
716:25
Speaker A
graphical font almost so they're just text and indeed if you put them between double quotes or single quotes you can print Emoji just like you can any other human character as well well let me propose now that we remove this Patronis
716:40
Speaker A
code just to simplify our world and focus on some of the other core capabilities of classes so at the risk of disappointing I'm going to get rid of all of these beautiful emoji and charms and I'm going to go ahead and stop
716:53
Speaker A
asking the user now for their petronis and I'm going to stop passing it into in it here and I'm going to stop uh doing this here and I'm going to instead just go ahead and restore our use of print
717:06
Speaker A
student here and I'm going to go ahead and get rid of petronis down here so essentially undo all of the fun charm we just created so we're now back at the point in the story where we have a
717:18
Speaker A
student class with only two methods in it and stir the first of those takes of course self as the first argument as it always will plus two more now name and house no more Patronis we're validating name up here we're validating house down
717:32
Speaker A
here and then we're assigning name and house respectively to two instance variables called name and house also but we used self to get access to the current object to store store those values therein we then still have our
717:45
Speaker A
stir method here which takes one argument by default self and that's it and that function is going to be called automatically anytime you want to convert a student object to a string just like print might want to do here so
717:58
Speaker A
let me go ahead and just make sure I haven't broken anything let me run python of studenty I'll type in Harry I'll type in Gryffindor enter okay we're back in business gone are the charms and patronises but at least I'm back to a
718:11
Speaker A
situation where I have names and houses but it turns out at the moment our use of classes is not very robust even though we have this mechanism very cleverly if I may in our init method of making sure that we're validating name
718:27
Speaker A
and house making sure that name is not blank and making sure that house is a valid house among those four Hogwarts houses it turns out that classes will still let me get at those attributes those so-called instance variables using
718:42
Speaker A
notation anyway let me scroll down then and try to do this a little adversarially suppose that on line 16 I go ahead and call get student which exists as before and then I store the return value in a student variable again
718:56
Speaker A
on line 16 that will ensure that get student gets called which calls input and input and then it calls the student Constructor which invokes automatically this init method so by way of how we've laid out my code we're going to ensure
719:12
Speaker A
that name is not blank and house is definitely one of those four values my error correction or error checking is in place but if I'm a little adversarial I can still circumvent it suppose that fine I'm G to you're going to require me
719:27
Speaker A
to type in Harry and griffindor I'm going to go ahead and type in student.h house equals quote unquote number four private drive and you're not going to be able to stop me why well it turns out with classes and objects thereof you and
719:41
Speaker A
I can still access those instance variables using this familiar dot notation that's how we began the story of classes just setting these attributes ourselves but you can also read these attributes themselves and change them later if you want and this will
719:54
Speaker A
effectively circumvent the if condition and the other if condition in our init method because that is only called when you first create the student object there's nothing stopping me at the moment from just changing the house or the name after so if I now now clear my
720:13
Speaker A
terminal window and run python of studenty I'll still type in Harry and Gryffindor to meet my requirements that the house be one of those four but when it's printed notice I've still overridden it so it seems that while
720:26
Speaker A
classes do allow us a little more control over the data we're storing it doesn't necessarily prevent the user be it or rather the programmer be it myself or maybe a colleague from still kind of messing things up so here too in the
720:40
Speaker A
spirit of programming a little more defensively allow me to introduce another feature of python as well namely properties so a property is really just an attribute that has even more defense mechanisms put into place a little more functionality implemented by you to
720:59
Speaker A
prevent programmers like me and you from messing things up like these attributes so again a property is going to be an attribute that you and I just have more control over how we just write a little more code using some python conventions
721:13
Speaker A
and how we're going to do that is going to use in just a moment a feature a keyword known as app property which is technically a function property is a function in Python but we're about to see some new at syntax that allows you
721:26
Speaker A
to decorate functions and this to is a term of Art in the world of python you can have decorators which are functions that modify the behavior of other functions if you will and we'll leave it at that without going too much into the
721:39
Speaker A
weeds and we'll see by example how you can use these decor Ator specifically to define properties so let me go back to vs code here and let me propose that I do this I'm going to go ahead and create
721:52
Speaker A
how about a property called house as follows inside of my uh student class I'm going to go ahead and below my init method and below my stir method I'm going to go ahead and Define a function called house that takes as it always
722:10
Speaker A
must one argument at least called self and what I'm going to do now is return uh self. house so I'm just going to define a method called House whose sole purpose in life is to return the value of house but I'm going to Define one
722:27
Speaker A
other method curiously also called house but that's going to take into as arguments two values self as always and also a value called house and I'm going to now do this uh I'm going to say self rather I'm going to do self. house
722:45
Speaker A
equals house now what have I done well let me just temporarily add some comments here in a moment we're going to start referring to this generally as a getter and down here I'm going to refer to this as a Setter and this is
722:57
Speaker A
terminology you frequently see in the world of java if some of you have programmed in Java before but as the names imply a getter is a function for a class that gets some attribute a Setter is a function in some class that sets
723:12
Speaker A
some value and now even though we're not done and there's a bit of a mistake in the code I've already written intuitively what we're going to do is this we're trying to prevent programmers myself included from circumventing my
723:25
Speaker A
error checking that I put into place for name and house how can I do that well we don't have that many building blocks in programming we have things like variables for data and we have functions for actions well why don't we do this
723:38
Speaker A
why don't we somehow require that in order to access an attribute you go through some function and let's require that in order to set some attribute you go through some function and conventionally those functions are called a getter function and a Setter
723:55
Speaker A
function and why are we using functions or in this case methods inside of a class well once you have functions those are just actions or verbs that you and I can create ourselves we can put any error correction I want in these
724:07
Speaker A
functions because it's code that's going to get executed top to bottom so so how can I now prevent the user from setting the house to an invalid value let me borrow some logic from before rather than blindly do this just set self.
724:24
Speaker A
house equal to the house value that's passed in let's add our eror checking there so if house is not in the following list of Gryffindor or Hufflepuff or slyther or Ravenclaw or slythering in just as before let's go
724:44
Speaker A
ahead and raise a value error just to signify that uh-uh something has gone wrong I'll be more explicit I'll include a message like invalid house quote unquote otherwise I'm going to proceed on now line 21 to set self. houseo house
724:59
Speaker A
so I've just copied if you will or retyped my error checking inside of this so-called Setter function now why have I done that well to be clear whenever the user or the programmer writes code like this student. housee equals what's about to
725:16
Speaker A
happen magically is python will not just let the programmer access student.h housee directly that attribute that instance variable AKA self. house it's instead going to magically automatically call this Setter function for me how does python no to do that well if it
725:35
Speaker A
sees that on the leftand side there is self. housee where house is the name of the getter or Setter and then it sees an equal sign indicating assignment that's just enough of a visual clue to say wait a minute I'm not going to let you access
725:51
Speaker A
that attribute directly I'm going to use the setter instead why because the equal sign means I'm trying to set I'm trying to assign a value from right to left into that attribute so what Python's going to do automatically is call this
726:04
Speaker A
function for me and that's amazing because now I can execute code an algorithm to check do I want to let the user the programmer set that attribute to that value if not I'm going to raise a value error and you're just not going
726:18
Speaker A
to be able to do it if so fine I'll go ahead and set it for you but in order to do this we need a little more syntax and I'm going to get rid of my comment and I'm going to use that decorator I need
726:29
Speaker A
to tell python to treat this method as a getter and then the Syntax for the setter is a little different you now say house. Setter I wish one was getter and the other was Setter that's not the way
726:41
Speaker A
they designed it when you want to define a getter you just say at property above the function and you name the function exactly like you would like the property to be called quote unquote house once you do that you can now use a new
726:57
Speaker A
decorator that sort of automatically created for you called at house because I called it house and then you literally say at house. Setter and this whole line on line 17 is a clue to python that here comes a function whose name is identical
727:12
Speaker A
but notice that it takes two arguments both self so you have access to the contents of the object and house which is just going to be a stir that comes from the programmer from like the human input return value so that you can set
727:25
Speaker A
that value as well but there's one fix I need to make now here everything else I think is still good however watch this I no longer need this error check here why because if I scroll back down to my code
727:42
Speaker A
here I claimed a moment ago that code like this with uh student.h house equals is going to automatically get python to call my Setter for me guess what even up here in my init method calling self.
727:58
Speaker A
housee equals is also going to call my Setter method which is amazing because now I can keep all of my error checking in one place in the setter and it will now get called either E when I create
728:12
Speaker A
the object for the first time because of in it or even if the you the programmer tries to circumvent that init method and change the value of this attribute my Setter will also get called my Setter will get called anytime I access do
728:28
Speaker A
house but there's one fix I need to make unfortunately I have collided names right now if we go up here on line five this is an instance variable it's a string inside of myself inside of the current student object called name and
728:46
Speaker A
this is another instance variable called House unfortunately if I have an instance variable called name and house I cannot also have functions called house they're going to collide you got to decide do you want the variable to be
729:01
Speaker A
called house or do you want the function to be called House unfortunately you can't have both because now Python's going to confuse one for the other so the conventional fix for this is to do this to have the setter not store the
729:16
Speaker A
value that's passed in in self. house but to use an almost identical name but to use a little indicator that you means you know you're doing this correctly you typically by convention put an underscore in front of the instance
729:29
Speaker A
variable's name and when you return it up here you similarly put an underscore so now technically my instance variable is called underscore house but my property which is a fancier attribute if you will is called house alone huge amount of
729:49
Speaker A
syntax I know but it's a very powerful feature and again this is why you can graduate from dictionaries alone and have so much more functionality at your disposal let me go ahead and clear my terminal window and run python of
730:01
Speaker A
student. enter name all right let's go ahead and type in Harry let's go ahead and type in Gryffindor crossing my fingers as always and now look inval house this is a good thing why because notice in my main function I'm still
730:18
Speaker A
trying maliciously if you will to change Harry's house to not be one of the four valid ones I'm trying to change it to his childhood home of number four private drive but because python knows that wait a minute you're trying to
730:31
Speaker A
assign that is set a value and that value AKA house is now defined as a property you're going to have to go through the setter function instead to even let you change that value and because I have this raise value error if
730:47
Speaker A
the house is not as intended you're not going to be allowed to change it to an invalid value so I'm protecting the data on the way in through the init method and I'm even defending the data if you
730:58
Speaker A
try to override it there so I think the only solution for me the programmer is don't try to break my own code let me remove that line because it's just not going to work let me run python of
731:08
Speaker A
studenty and again type in Harry type in Gryffindor enter and Harry is indeed from Gryffindor if I did something incorrect like Harry from number four Private Drive enter we're again going to see the value error because my code just
731:25
Speaker A
doesn't let that value in Via manual input now or via that adversarial change all right that was a lot but any question on properties uh while we are using gets and Setters it's just for the purpose so that we can find that um that fun that
731:45
Speaker A
method that function in in our code the reason that I'm going through the trouble of defining this getter or Setter is because I want to make sure that programmers cannot do things like this if I'm going through the trouble of
731:58
Speaker A
validating the attributes for these student objects I don't want you to be able to go in there and just change them at will I want to have some control over that object so that you can just trust that it's going to be correct as
732:10
Speaker A
designed so using a getter and Setter really just enables python to automatically detect when you're trying to manually set a value the equal sign and the dot as I've highlighted here is enough of a clue to python to realize
732:23
Speaker A
wait a minute you're trying to set a value let me see if this class has a Setter defined and if so I'm going to call that and I'm not just going to blindly assign the value from right to
732:32
Speaker A
left so it's just giving me more control other questions on properties when we use a gets we just have just one argument and if we use Setters is always going to be two arguments is that normal correct it's always going to be one
732:49
Speaker A
argument self for the getter two arguments for the setter self and something else and the intuition for that is if you're getting a value you don't need to pass anything else in because you already know the object it's
733:02
Speaker A
called student in this case so you're just going to get the value of that property but if you want to set the property to something else you got to pass in that argument you've got to pass in the value to which you want to set it
733:13
Speaker A
so it's always zero or one however you see it as one or two because again any function inside of a class AKA a method is going to be automatically passed self so that you have access to that current
733:26
Speaker A
object in memory how about one other question on properties why didn't we use the same underscore house in init meod a good question so even though I'm using the underscore house here in my Setter and the underscore house here in my
733:41
Speaker A
getter I deliberately did not use it up here the reason for that is that by using self. house and this equal sign that's the same pattern that I want python to recognize I want python to automatically call the setter even when
733:57
Speaker A
I'm passing in the house via the init method if I were to change this to do this that would circumvent the setter and now there's no error checking in in it whatsoever so it's such a fine line the only thing standing between us and
734:11
Speaker A
error checking or no error checking is the presence or absence of this underscore but that's typically the convention by not using the underscore there make sure that even that assignment goes through the setter so that honestly I don't have to copy paste
734:25
Speaker A
the same error checking in two places I can put it just in the setter so it's better design and that's why I manually retyped it at first but then I deleted it from in it well allow me to propose
734:35
Speaker A
that we make one other change to this file might as well go ahead and Define a property for name as well and let me go ahead and do this maybe above the house property just to keep things uh in the
734:46
Speaker A
same order as I defined them earlier let me give myself another property this one's going to be called name it's going to take one argument called self as always and this one very similarly is just going to return self. uncore name
734:59
Speaker A
so I'm going to anticipate that I'm going to have to rename name also so that I don't have that same Collision as before but now let me go ahead and Define another uh setter this one for name so the convention is at name.
735:12
Speaker A
Setter why name because the property I just created is called name so the getter and Setter sort of work in conjunction in that in this way if you will let me go down under ATN name Setter and Define another function also
735:26
Speaker A
called name but the key thing here is that it's not identical it's not the exact same function name and the exact same number of arguments the setter again takes a second argument and I can call it anything I want but I'm going to
735:37
Speaker A
call it name because that's what's being passed in and I'm going to air put my error checking here if not name just like we used to do let's go ahead and raise a value error and let's put an
735:47
Speaker A
explanatory message like uh Missing name quote unquote otherwise let's go ahead and update self. uncore name to equal name and I don't have to change in it except to get rid of this duplicate error checking now because again if I
736:06
Speaker A
use self. name equals here and self. house equals here with no underscore for both of those assignments are going to go through my two Setter functions now before we run this let me go ahead and remove this adversarial code which we
736:20
Speaker A
know won't work because we're catching it let me go back down to my terminal window and run python of studenty enter let's type in Harry let's type in Gryffindor and that seems to work let's try though again to run python of
736:32
Speaker A
studenty with Harry from number four privet drive this will not work a value error with invalid house because that's not one of the four WS houses and now for good measure let's run it one more time and let's not even give it a name
736:45
Speaker A
let's just hit enter when prompted I can type anything for the house I'll go ahead and still give it Gryffindor enter now we get another value error but this one is for missing name so we seem now to have all the more of a defense
736:58
Speaker A
mechanism in place to ensure that name is as we expect it's got to have some value that's not blank and house is as we expect it's got to have one of those four values but at the risk of bursting
737:10
Speaker A
everyone's bubble and making you wonder why did we just go through all of that unfortunately python really focuses on conventions not hard constraints and by that I mean this if I go back into my main function after I've gotten a
737:27
Speaker A
student online 30 and I try to adversarially do something like this student. housee equals quote unquote number four Private Drive we know this won't work because my Setter for house is going to catch this watch again again python of
737:43
Speaker A
studenty uh let's type in Harry let's type in Gryffindor which will at least pass our check that's induced by in it but line 31 is going to trigger the same Setter to be called and we're going to raise a value error saying invalid house
737:59
Speaker A
unfortunately and if some of you are already thinking a little adversarially tragically look what you can do you can change house to beore house why well the instance variable is now called underscore house the property is called house no underscore but the underlying
738:17
Speaker A
attribute implemented as an instance variable is still called underscore house and tragically python of student.
738:27
Speaker A
let's type in Harry let's type in Gryffindor which is correct but Watch What Happens now oh my God we slip through so what was the point of all of this emphasis from me on doing things the right way the python iic Way by
738:41
Speaker A
having this getter and Setter well unlike languages like Java that just prevent you from doing things like this python itself allows you to specify that certain instance variables can be public and accessible to anyone's code or protected or private which means that no
738:57
Speaker A
one else should be able to change these values in the world of python it's just the honor System it's not baked into the language itself that there's a notion of visibility public or private or even somewhere in between protected instead
739:10
Speaker A
you're on the honor system and the convention generally is if a instance variable starts with an underscore please don't touch it like just don't like that's on you if you touch that variable and break things the underscore is meant to signify a convention that
739:25
Speaker A
this is meant to be private but it really just means please don't touch this sometimes if there's two underscores which you can use two that's an even greater effort by programmers to say really don't touch this but technically speaking there's nothing
739:37
Speaker A
stopping you or me from circumventing all of these mechanis Ms these properties these Getters and Setters were ultimately just on the honor System not to do so when we see instance variables prefixed with one or perhaps even two underscores all right so this
739:52
Speaker A
is a lot all at once this introduction to object-oriented programming but it might come as quite a surprise that even though we might had have identified oop by name in weeks past we've all been using classes and objects for weeks now
740:08
Speaker A
in this class in fact if you think back on one of the very first things we did in this class we used integers and just got integers from the user but if you haven't already if you go and dig into
740:18
Speaker A
the documentation for integers which again lives at this URL here you would actually find that int itself is and has been for weeks a class and in fact this is the signature of the Constructor call for an INT whereby you pass in X like a
740:36
Speaker A
number quote unquote 50 or quote unquote something else you pass in optionally the base 10 for decimal two for binary or anything else and that int function will actually return to you all this time an object of type int that is to
740:53
Speaker A
say int is a class it is a template a blueprint for creating integers in memory and anytime you and I have converted a string for instance to an INT you and I have been creating an object of type int that was calling
741:07
Speaker A
apparently the underscore underscore in it underscore underscore method that someone else the authors of python wrote to give us back that proper integer besides that if you can believe it stirs strings in Python have been classes since the first week of this class as
741:22
Speaker A
well if you look up the documentation for a stir which lives at a similar URL there you will find that when you instantiate that is create a stir it takes optionally a parameter called object here the default value of which
741:36
Speaker A
is just quote unquote which allows you to create in effect an empty string a blank string string if you will but anytime you and I have created stirs or even used explicitly this stir function you are getting back an object of type
741:49
Speaker A
stir anytime you and I have forced a string to lowercase per the documentation using syntax like this you and I have been taking an object of type stir and forcing it all to lowercase by calling a method called Lower a method
742:07
Speaker A
that the authors of python built into the stir class but it's been there from the gecko so this notion of method is not even new today you would have been doing it for this long if you've ever called strip to remove the leading and
742:19
Speaker A
the trailing Whit space from a string in Python you are calling another method that came with python written by the authors of python and even though we didn't call it a class at the time a stir all this time has been a class and
742:33
Speaker A
instances of strings are themselves objects and those objects come therefore with these functions built in AKA methods that allow us to do things like force to lowercase and strip Whit space from the beginning and end let's do another list anytime you've created a
742:49
Speaker A
list either uh either syntactically with square brackets or literally with l i s open parenthesis closed parenthesis which is also possible you have been using a class if you go to the documentation for list at this similar URL here or more specifically the
743:05
Speaker A
tutorial on lists here in Python you will see that a list is and has been since the early weeks of this class A Class itself and that clist class takes as part of its uh initialization in optional iterable something that can be
743:21
Speaker A
iterated over like one comma 2 comma three or some list of values and you can then get back a list containing those same iterable values if you've ever appended something to a list in this class as I have myself in the past
743:35
Speaker A
you've been using a method called aend that comes with the list class that per the X takes an argument that allows you to append something to the current list AKA self in the context of that method we can do this all day long if you've
743:50
Speaker A
used a dictionary or a dict in Python I've actually all this time been calling them dict objects and that's for a reason dict itself is a class in Python if you pull up its official documentation here and you'll see that
744:03
Speaker A
it is defined indeed as itself a class and that class comes with methods as well and so anytime we've manipulated dictionaries we've been in underneath the hood using all of those same methods and in fact we can see this if we're
744:16
Speaker A
really curious let me go back over here to VSS code and let me go ahead and create a new file that very simply does something like play around with data types and let me go ahead and create a
744:27
Speaker A
new file for instance called say uh type. piy just so that I can poke around inside of some values and in type. pi I'm just going to go ahead and do this I'm going to print out whatever the type
744:39
Speaker A
is of say the number 50 and this is a function you've not necessarily seen me use already and it's not one you would frequently use in your own code there are other ways to te detect if you need
744:50
Speaker A
to what the type is of a variable but in this case type of 50 is just going to tell me and then print out what the data type is of that value now hopefully all of us could guess that 50 is indeed
745:01
Speaker A
going to be an integer that is an INT but we can see it in this way and this too is what's powerful about knowing a bit of programming if you want to know the answer to a question just try it out
745:10
Speaker A
like am here so let me go ahead and run python of type. py enter and there it is when you print out the type of the number 50 you'll see on the screen in this cryptic syntax class quote unquote
745:23
Speaker A
int this is not something that you probably want to show to the user but if you yourself just want to poke around and see what's going on or maybe use that information somehow it's certainly at your disposal to use with this type
745:35
Speaker A
function for that let's change it around a little bit instead of passing is the argument to type 50 as an INT let's type something also familiar like hello comma World in double or single quotes let me go back to my terminal window clear the
745:48
Speaker A
screen and run python of typey again and now voila there it is all this time a stir is also a class we can do this a few more times for instance let's go ahead and change hello world to just an
746:01
Speaker A
empty list open square bracket close square bracket and this is starting to look a little cryptic but again notice what I'm doing in square brackets is an empty list we've done that before that is the sole argument to this new type
746:14
Speaker A
function and that's just being passed to the print function so that the return value of type is the argument to print so if I now run this code python of type. piy there it is a list is a class
746:27
Speaker A
two you might recall that I said that you can also create an empty list by literally doing list open parenthesis close parenthesis this is a bit of an inconsistency as we can now identify that int and stir and Now list they're
746:41
Speaker A
technically all lowercase and I went to Great Lengths of creating my student class to have that capital S that's a convention because int and stir and list and others come with python they decided to make their built-in data types even
746:57
Speaker A
though their classes all lowercase but the convention the recommendation in the python Community when creating your classes is indeed to capitalize the first letter as I did in something like student capital S but list open parenthesis closed parenthesis is
747:12
Speaker A
identical to really just two empty square brackets if I clear my screen and run type dopy again you see the exact same thing the class is called list let's do one more let me change list to be not square brackets but curly braces
747:26
Speaker A
we've done this before anytime I've done two curly braces with nothing in between this of course is an empty dictionary or a dict object in Python well we can see that now let me clear my screen run python of type. enter and there it is
747:39
Speaker A
class dick it's been there this whole time we just didn't call it a class until today I can similarly do this one explicitly instead of two curly braces let's write out dict with two parentheses now we have a lot of
747:52
Speaker A
parentheses again like with list but this is just making even more clear that the type of a dict object is indeed the class dict itself so this is to say that as new as a lot of today's ID and syntax
748:05
Speaker A
might be you've actually been using it perhaps unbeknownst to you for weeks now we now just have terminology to describe what it is we've been doing all this time and you now have the expressiveness with some practice to create your own
748:19
Speaker A
classes inside of which are your own instance variables perhaps wrapped with those properties and your own instance methods but it turns out there's other types of methods in the world thus far I've been deliberate in calling all of
748:33
Speaker A
our variables instance variables and all of our methods uh instance methods it turns out there's other types of variables and methods out there and one of those is called class methods it turns out that sometimes it's not really
748:49
Speaker A
necessary or sensible to associate a function with objects of a class but rather with the class itself an instance or an object of a class is a very specific Incarnation thereof again on that neighborhood that has a lot of
749:05
Speaker A
identical looking buildings but they're all a little bit different because of different paint and such sometimes times you might have functionality related to each of those houses that isn't distinct or unique for any of the houses it's functionality that's going to be exactly
749:20
Speaker A
the same no matter the house in question same in the world of object-oriented programming sometimes you want some functionality some action to be associated with the class itself no matter what the specific objects own values or instance variables are and for
749:36
Speaker A
that we have a keyword called at class method this is another de cator really another function that you can use to specify that this method is not by default implicitly an instance method that has access to self the object
749:51
Speaker A
itself this is a class method that's not going to have access to self but it does know what class it's inside so what do I mean by this well let me go back to VSS code here and let me propose that we
750:02
Speaker A
create a new file this time implementing the notion of a the Sorting Hat from the World of Harry Potter as well to stay on theme I'm going to go ahead and run code of hat. py and in hat. py let's
750:13
Speaker A
implement the notion of this Sorting Hat if unfamiliar in the books and in the films there is literally a pointy hat that when a student put it on their head that Sorting Hat so to speak decides what house the student is in whether
750:26
Speaker A
it's Gryffindor or something else so let's Implement and code this notion of a Sorting Hat such that when we pass to the Sorting Hat the name of a student like quote unquote Harry this Sorting Hat implemented in code will tell us
750:40
Speaker A
what what house that student should be in all right well let's go ahead and do this in hat. py first let's go ahead and define a class called hat and then let's get back to implementing it itself and I
750:53
Speaker A
find this to be a helpful technique not just with teaching but when writing code like I know I want a ha class I don't necessarily know what I want it to do yet so I'm going to create this sort of
751:02
Speaker A
placeholder dot dot dot so I'll come back to that let's now try to use this class as though it existed and from there I perhaps can realize exactly what functionality that class needs to have to support my use case let me go ahead
751:15
Speaker A
and create a variable called hat in all lowercase and instantiate a hat object so no matter what the Hat class ends up looking like this is the common Syntax for instantiating an object of a certain class in the past we saw student all
751:31
Speaker A
lowercase equals Capital student open parenthesis closed parenthesis and then eventually we added in things like name and house for now let's assume that the hat is much simpler than a student and it only has sorting capabilities so I'm
751:45
Speaker A
not going to even pass any arguments there too indeed let me assume that the Sorting Hat has one Function One method inside of it called sort and so if I do hat. sort quote unquote Harry let's propose that that prints out what house
752:03
Speaker A
that student should be in so that's it I'm going to encapsulate that is tuck away inside of a hat class all of this requisite functionality and I'm going to print out on the screen what hat uh what house Harry belongs in all right now I
752:18
Speaker A
think I need to get into the weeds of actually initializing this class well let me go ahead and do this if I don't care to parameterize hat I just want to for instance uh sort values let's go ahead
752:33
Speaker A
and Define this function sort first so let's define sort as taking a first argument self which is always going to be the case when defining an instance method as before but the sort method clearly takes one argument from the
752:46
Speaker A
programmer me namely the student's name and again we've seen this dichotomy before even though I'm trying to pass in one argument when I Define the method it's got to take that many arguments plus one more self which is always going
752:59
Speaker A
to be automatically passed in by python first all right what do I want to do well let's go ahead and do something like this uh print quote unquote or rather print this name how about quote unquote is in quote unquote some house
753:15
Speaker A
I'm going to again use some placeholder code for myself because I'm not quite sure how to finish implementing this Sorting Hat but I think that's enough to just test where my code is at now let me go ahead and run python of hat. py and
753:28
Speaker A
hit enter and it looks like indeed Harry is in some house we're not done yet because it's clearly not doing anything interesting but it at least is running correctly with no errors well let's go ahead now and decide where uh what house
753:44
Speaker A
Harry should actually be in by introducing a bit of Randomness and choosing a house randomly well I can do this in a few ways let me go ahead and do this I need to have a list of houses
753:54
Speaker A
somewhere so where can I put that I could solve this problem in different ways let me propose that I do this let me Define a method called in it as I've done before that takes in self but no
754:03
Speaker A
other arguments and whenever the Sorting Hat is instantiated let's do this let's create a houses instant variable plural that equals this list Gryffindor comma Hufflepuff comma uh Ravenclaw comma Slytherin so the exact same list that we've used before and I'm storing it in
754:24
Speaker A
an instance variable inside of this class I'm not taking any arguments Beyond self in it but I just need this list of values somewhere for instance so what can I do here well let me go ahead and replace some house with the actual
754:39
Speaker A
house well what could I do here well I want to put a house there well let's go ahead and create a variable called house and if you think back to our discussion of libraries in the random module there
754:50
Speaker A
is a function called choice that if you pass in a list of choices like self.
754:56
Speaker A
houses that will pick a random house out of those four and then on line seven I can pass it in if I want to tighten this up let me just go ahead and highlight that code get rid of the variable is
755:06
Speaker A
technically unnecessary and because the line of code is still pretty short I'm okay with just putting it all in one line but I could certainly use the variable like I did a moment ago so what have I done in my init function I have
755:20
Speaker A
defined a initialization of the object that stores and self. houses the list of four houses and then in sort I'm accessing that same list but I'm randomly choosing the set of houses there now why have I done it in this way
755:35
Speaker A
this to is General convention anytime you have a list of things that who knows maybe we'll change over time places like Harvard have constructed new houses over the years so you might have to change the list of available houses it didn't
755:47
Speaker A
happen in seven books or eight films of Harry Potter but you could imagine maybe Hogwarts eventually has a fifth house so there's generally some value in putting list of constants toward the top of your file toward the top of the class so it's
756:00
Speaker A
just obvious what the list of values is you don't want to necessarily tuck it away in some function like sort especially if you might want to use that function in sorry if especially if you want to use that list in multiple
756:12
Speaker A
functions not just sort but if I kept adding to this class you might want to use that same list of houses in multiple functions so let's keep it in the object Itself by storing it in self. houses all
756:24
Speaker A
right well we're about to change the course of history here perhaps let me do python of hat. and I think we're about to assign Harry to one of those four houses randomly huh name error name random is not defined well wait a minute where did
756:40
Speaker A
did I go wrong here thinking back to our class on libraries why did my code break and not tell me where Harry is to be you do not import the random Library exactly if the random library or module is
756:54
Speaker A
something I want to use I need to tell python that at the top of my file so let me go up here and do import uh random and then below that let me go ahead and clear my terminal window and try again
757:05
Speaker A
python of haty crossing my fingers seeing where hair is going to end up and okay Harry as of now is officially in Hufflepuff despite what everything you've read or seen well let's run this again let me clear my window and run
757:20
Speaker A
python of hatai and now he's in Ravenclaw that's consistent with using random let's clear that and run it again he's still in Ravenclaw but that could happen even though there's four choices let's do it again Hufflepuff back in
757:32
Speaker A
Hufflepuff we can't seem to get the right answer so to speak now he's in Gryffindor albeit randomly so we seem to have a program that based on these Limited Test seems to indeed be assigning Harry to a house randomly now
757:44
Speaker A
I'm somewhat lazily just letting sort print out this value I could do something else like return a string and then let me on line 13 do the printing for me but for now I think we have an example of a class called hat that
758:00
Speaker A
nonetheless applies some of our lessons learned thus far today where I've created a class because a Sorting Hat is frankly well a I was about to say real world entity but really A Fant FY World entity and indeed that's a perhaps
758:12
Speaker A
common puristic or mental model to have when should you use a class to represent something in your code very often when you're trying to represent some real world entity or fantasy world entity like a student which is something in the
758:28
Speaker A
real world like a Sorting Hat which okay doesn't exist but hats certainly do so quite reasonable to have a class for hat and that's not always the case that classes represent real world entities but indeed we've seen thus far that int
758:43
Speaker A
and stir and list and dict these are all structures that you might have in the real world we have integers and strings of text and other things so it rather makes sense to represent even those things more technically using a class as
758:55
Speaker A
well you could use just a dictionary to represent a student or a hat but again with classes come all this and even more functionality but I honestly am not using classes in really the the right way here here why well in the World of
759:12
Speaker A
Harry Potter there really is only to my knowledge one Sorting Hat and yet here I have gone and implemented a class called hat and again a class is like a blueprint a template a mold that allows you to create one or more objects
759:27
Speaker A
thereof now most of my programs thus far have been pretty simple and I've just created one student but certainly if I spent more time in wrote more code you could imagine writing one program that has a list of students many more
759:39
Speaker A
students than than just the one we keep demonstrating yet it would be a little weird it's a little inconsistent with the real or the Fantasy World of Harry Potter to instantiate one two three or more sorting hats there really is just
759:52
Speaker A
one really one Singleton if you will which is a term of Art in a lot of contexts of programming so let me propose that we actually improve the design of the Sorting Hat so that we don't have to instantiate a Sorting Hat
760:05
Speaker A
because right now this is kind of allowing me to do something like hat one equals hat hat two equals hat hat three equals and so forth I don't really need that capability I really just need to represent the Sorting Hat with a class
760:18
Speaker A
but I don't really need to instantiate it why because it already exists I need just one so it turns out in Python that up until now we've been using as I keep calling them instance methods writing functions inside of classes that are
760:32
Speaker A
automatically p a reference to self the current object but sometimes you just don't need that sometimes it suffices to just know what the classes and assume that there might not even be any objects of that class so in this sense you can
760:45
Speaker A
use a class really as a container for data Andor functionality that is just somehow conceptually related things related to a sorting hats and there's this other decorator or function called class method that allows us to do just this so let me go back to my code here
761:02
Speaker A
and let me propose that if I'm not going to instantiate multiple houses I don't really need this this in it method because that's really meant to initialize specific objects from that blueprint that template that mold so let me get rid of this but if I get rid of
761:19
Speaker A
this I no longer have access to self but that's okay because it turns out in addition to their existing class methods there are also what we might call class variables and class variables exist within the class itself and there's just
761:35
Speaker A
one copy of that variable for all of the objects thereof they all share if you will the same variable be it an INT or stir or in this case a list so what I've done here is Define inside of my hat
761:49
Speaker A
class in a class variable called houses I don't say self because self is no longer relevant self refers to specific objects I want a variable inside of this class AKA a class variable that equals that list because it's inside of this
762:05
Speaker A
hat now class I can use that list in any of my functions I've only got one now called sort but if I had more it would be accessible to all of those methods as well and with sort it also doesn't
762:18
Speaker A
really make sense to sort within a specific sorting ha because again there I only want there to be one so I can actually specify that this is a class method by saying at class method and I don't pass in self anymore I actually by
762:32
Speaker A
convention pass in the a reference to the class itself it's typically written as CLS y well if you wrote C ass that would actually conflict with the keyword class that we keep using up here so the world realized that oops we uh can't
762:48
Speaker A
reuse that same phrase here so let's just call this class this is useful in some context including this one why well we notice what I can now do I can now change self to be just class why because
763:01
Speaker A
house is now not an instance variable accessible via self. houses it is now a class variable accessible via class ouses or technically CLS do houses in this case but now the final flourish is this now I don't have to instantiate any
763:19
Speaker A
hat objects as I used to on here line 13 I can just use functionality that comes with this class so I'm going to delete that line Al together I'm going to capitalize the Hat on this new line 13
763:31
Speaker A
and just say hat. sort quote unquote Harry so what have I done I've not bothered in intiating an object of type hat I am just accessing a class method inside of the Hat class that you know what is just going to work this is how
763:49
Speaker A
class methods work you use the name of the class capital letter in all do method name passing in any arguments you want python is going to automatically pass in some variable via which you can refer to that class in that function
764:03
Speaker A
that you've implemented inside of that class so that I can do something like this it's not that I want a variable called houses locally in this function I want the variable called houses that's associated with this current class so I
764:16
Speaker A
can still access this same list that I defined on line six and now if I go back down here to my terminal and run python of haty enter Harry is still in Hufflepuff once more Harry is still in
764:29
Speaker A
Hufflepuff once more Harry is back in Gryffindor at least randomly questions now on these class variables or these class methods which are in contrast with instance variables and instance methods and the one thing at least that's a little strange here is
764:47
Speaker A
that even though there's a decorator called at class method there is not one called at instance method a method is just automatically a so-called instant method when you define it without any decorator can you have a class inside
765:02
Speaker A
another class you can you can Define one class inside of another generally speaking this isn't done but there are cases where it can be helpful especially for larger more sophisticated programs so yes it is possible good other questions the question was about the
765:19
Speaker A
self do houses when you when we remove it we uh and we pass data the variable is created itself why we remove the S so in the previous examples both of the Hat demonstration and also all of the
765:35
Speaker A
student demonstrations we were uh create creating a student object by calling student capital S open parenthesis closed parenthesis with eventually name and a house passed in and then we were using the d uh the Double underscore init method to initialize the self. name
765:52
Speaker A
and the self. house instance variables therein to those respective values in this latest version of the Sorting Hat I haven't bothered with self anywhere only because conceptually I don't need or want there to be multiple hats in the
766:08
Speaker A
world I'm just using the class is kind of a container to bundle up this list of houses this sorting functionality maybe eventually I'll add more functionality to it but that's it and so sometimes you can use objectoriented programming in
766:22
Speaker A
this somewhat different way when you want there to be functionality but it's not specific to any one specific hat it's specific to the Sorting Hat itself how about one other question now on these class variables or methods just
766:37
Speaker A
another way of using objectoriented programming but to solve somewhat different problem well what's the difference between the class head and I know like a function of hat a good question so why are we using a class at all and not just having a file called
766:53
Speaker A
hat. py with a variable called houses and a function called sort like why are we adding this complexity in this particular case we don't necessarily need to I could absolutely go in here I could get rid of the class I could uh
767:07
Speaker A
undo this indentation I could could get rid of this decorator and I could get rid of hat Dot and I could just do this and additionally let's see let's get rid of class here let's get rid of class
767:18
Speaker A
Here and Now run python of haty enter and it still works put Harry in the wrong house but that's what we have what happens randomly that's fine too what we're introducing today by way of object-oriented programming is just a
767:31
Speaker A
different way of modeling the world it's not really compelling with an example like this frankly that's relatively simple it's not very complex there's not much functionality honestly the version that we just typed up these 10 lines this is fine this solves this problem
767:45
Speaker A
but as our code gets longer as we start collaborating with other people as the problems we're trying to solve with code get more sophisticated you're going to find that your code gets messy quickly and you're going to find that you have a
767:57
Speaker A
huge number of functions for instance in one file and some of them are related to each other but some of them are not well at that point wouldn't it be nice to just organize them a little differently and in the World of Harry Potter let's
768:08
Speaker A
have a class for student let's have a class for Professor let's have a class for the Sorting Hat let's have a class for something else and so once your world gets much more complicated than some of the demonstrations we do here in
768:19
Speaker A
class when we want to focus on individual ideas object-oriented programming is just a way of encapsulating related data that is variables related functionality that is methods inside of things that have names these things are called classes so it's
768:35
Speaker A
just another way to solve problems and when we focused on libraries a couple of weeks back back that too was another solution to the same problem you could Define your own modules or packages put some of your data Endor functionality in
768:46
Speaker A
there and that's fine too and sometimes which one you should use overlaps if you're familiar with vend diagrams the overlapping region might mean that you could use a class you could use a module or a package you could just use a single
768:59
Speaker A
local file over time you'll develop an instinct and maybe even a personal preference for which tool to use all right let me propose now that we apply this same idea of a class method to clean up one other thing as well let
769:14
Speaker A
me close hat dopy and reopen student. py as we left it earlier and let me go ahead and simplify it just a little bit uh I'm going to go ahead and get rid of the properties not because there's
769:27
Speaker A
anything wrong with them but just because I want us to focus on some of the key ideas when we began with this program so I'm going to go ahead and keep main as well I'm not going to adversar try to change Harry's uh
769:38
Speaker A
address there I'm going to instead go ahead though and just print the student but this is the thing I want to focus on here this in our previous student examples was kind of a missed opportunity to clean up my code well
769:51
Speaker A
what do I mean by that well up here at the top of this file even though I've simplified it by getting rid of the properties and all of that error checking because I want to focus on the essence of this class now just the
770:01
Speaker A
students's name and the house and the printing thereof this is by nature of classes and object-oriented programming theoretic Al all of my student specific functionality that is to say if I have functionality and data related to a student you the programmer my colleague
770:19
Speaker A
would assume that it's all bundled up encapsulated so to speak inside of the student class and yet if you scroll down further what is this like there's a function called get student that just exists elsewhere in this file that
770:31
Speaker A
prompts the user for a name prompts the user for a house creates the student object and then returns it like that's not wrong like it works and we saw many many times it kept working but this is a
770:43
Speaker A
little weird right because what if this is a function that helps you get a student helps you get the name of a student and the house of a student why isn't that functionality in the class itself after all as my code gets more
770:55
Speaker A
and more complicated and does more things I'm going to be looking at the student class for all student related functionality I'm not going to be scrolling down expecting that oh maybe there's some other student functionality just kind of randomly later in this file
771:08
Speaker A
so it's not wrong but this is again evidence of maybe bad design not so much with this small program but this is an example again of code smell like something smells a little off here like this is probably going to get us in
771:20
Speaker A
trouble by separating related functionality so again it's a design principle not a correctness concern but class methods allow us to address this too let me go ahead and do this I'm going to delete get student altogether leaving only main as my other function
771:38
Speaker A
here and inside of my student class I'm going to do this I'm going to define a function even more simply called get and by nature of how class methods work it's going to take in the name of the class
771:50
Speaker A
itself or reference there too as an argument and I'm going to move the functionality from get student into the student class and I'm going to do this name equals input quote unquote name uh house equals input quote unquote house
772:05
Speaker A
and then what this function is going to do is return a new student object by calling class which again is just an automatically passed in reference to the class itself passing in name and house and I will admit this syntax seems a
772:23
Speaker A
little strange that now I'm calling CLS and I'm passing in these arguments but let me do one final fix here let me go to the top of this function and more explicitly say this is a class method this solves a potential Chicken and the
772:36
Speaker A
Egg problem so to speak whereby one needs to come before the other potentially so what am I doing here inside of my student class I now have a function called get it is I shall claim a class method what does that mean it
772:51
Speaker A
just means I can call this method without instantiating a student object first there in lies the potential Chicken and the Egg problem and if unfamiliar that's an expression meaning well did the world have chickens first that laid eggs or was there an egg that
773:06
Speaker A
then Bor uh yielded the chicken but how did the egg get there it's this sort of weird circular problem and that's what we're facing here it would be weird if you had to create a student object in order to call get in order to get
773:21
Speaker A
another student object like that sounds messy let's just get a student via a class method that by definition does not require you to create a student object first just like the Hat in its final form we use the Hat class to just say
773:37
Speaker A
hat Capital H do sort we didn't need to create a hat first we just used the class itself so what am I going to do here now let me go down to Main and instead of saying get student notice
773:49
Speaker A
what I can now do student. get and everything else can stay the same all I've done now is I've migrated all of my logic from get student which was this own Standalone function but clearly related to students by name I've moved
774:05
Speaker A
the same code really to inside of the student class in a more simply named function called get but I could still call it get student if I want it just seems a little redundant to call it get student in a student class so I'm
774:18
Speaker A
simplifying so I have a method called get but I'm calling it a class method to avoid that chicken in the egg problem I want to be able to call get without having a student object in my universe already and the syntax for that is at
774:34
Speaker A
class method the convention is to give this method at least one argument by by convention called CLS for class which is just going to be a reference to the class itself lines 11 and 12 are identical to what they've always been
774:46
Speaker A
and get student the only new syntax here is this but this again is one of the features of object-oriented programming you can now instantiate a student object by just using CLS that's passed in I technically could use student capital S but it turns
775:04
Speaker A
out I'm doing what's more conventional because this will both solve and avoid problems down the line with more complicated code this line here on line 13 just means create an object of the current class what class is that well
775:16
Speaker A
whatever CLS is well that by definition of how it all works is going to be student and I want you to initialize it as always with name and house so now scrolling down my code is this and this
775:29
Speaker A
is just nice to read you did perhaps have to acquire a taste for this and I sound a little odd saying this is nice to read but indeed student. just tells me what's going on I'm going to get a
775:40
Speaker A
student I don't need a separate function written by me called get student in the file itself the get functionality is built into the class all my student related code now is together so let me go down to my terminal window and run
775:52
Speaker A
python of student. enter let's type in Harry let's type in Gryffindor and we're back to where we began but but but everything related to students now is in this here class the only other thing in the file is Main and this conditional
776:07
Speaker A
that we always use to avoid accidentally executing main when we're making a module or a package or the like so again a solution to a problem not a big one in the case of a relatively small program but one that you will eventually
776:21
Speaker A
encounter as your programs get longer and longer with more and more entities to represent questions now on this use of a class method does the does the class have to be defined before the main function in terms of the order of the of
776:37
Speaker A
the program really good question so when in doubt let's try this so let's try to change the order let's move main to the top which I've often encouraged so let's go ahead and above the class do this and
776:47
Speaker A
notice now that technically line two is mentioning student which does not exist until line six and Below let me go ahead and clear my terminal and run python of studenty so far so good Harry Gryffindor okay uh indeed Harry's from Gryffindor
777:03
Speaker A
the reason Michael it does not matter in this case is because we're not actually call main until the very end and just as in the past that means that python has a chance to read everything top to bottom
777:14
Speaker A
left to right so everything exists I would say generally classes are defined at the top of the file however it would be even maybe cleaner to move the classes definition to its own file and then import it so essentially to make
777:28
Speaker A
reusable code by putting it into your own module or package so that not just this program but many others can use that definition of student as well other questions now on classes class methods or the like I wanted to ask is there a
777:42
Speaker A
way to um like declare all the all the possible all the possible attributes of the class because it looks so inconsistent um well so my takeaway there is this is Python's approach to these principles different languages like Java just take a different approach
778:01
Speaker A
but have very similar features the syntax just tends to vary and this is how the python Community chose to implement this idea the right mental model ultimately is that these instance variables instant methods belong to or operate on specific objects a specific
778:19
Speaker A
student a specific hat class variables and class methods operate on the entire class itself or in turn all objects of that class which we've not seen them a demonstration of but it's sort of a higher level concept so it turns out
778:34
Speaker A
besides these class methods which are distinct from those instance methods which to be fair do not have their own decorator they just are by default instance method there's yet other types of methods you can have in classes in
778:45
Speaker A
Python they tend to be called Static methods and they too come with another decorator called at static method which is a rabbit hole we won't go down but realize that there is yet other functionality that you can leverage
778:56
Speaker A
within object-oriented programming but what we thought we'd do is focus really on some final core features that you see not just in Python but other languages as well and perhaps one of the most compelling features of objectoriented programming that we haven't yet used
779:10
Speaker A
explicitly though it turns out we've seen implicitly over the past weeks is this notion of inheritance it turns out via object-oriented programming there's actually an opportunity to design your classes in a hierarchical fashion whereby you can have one class inherit
779:28
Speaker A
from or borrow attributes that is methods or variables from another class if they all have those in common so what do I mean by this here well let me propose that we Implement uh over in vs code here a brand new file called
779:44
Speaker A
wizard. let me go ahead and run code of wizard. py and then let's start as before defining a class called student and let's go ahead and first Define the underscore uncore init method which of course is minimally going to take an
779:59
Speaker A
argument traditionally called self and in this case let's also have it take as before a name and a house and then in this init method let's go ahead and assign the instance variables self. name equals name and self. house equals house
780:14
Speaker A
let's assume that there's some other functionality in this class as well dot dot dot but let's move on now to implementing the notion of a a professor in The Wizarding World as well so for this class let's call it
780:27
Speaker A
professor and a professor let's say is also going to have its own initialization method so underscore underscore in it it's going to take self as always as the first argument uh a professor also has a name so we'll pass
780:39
Speaker A
that in second two and even though some professors are heads of houses let's assume that a professor is really identified by their name and their subject area the class that they teach so we'll call this third argument subject now as before let's go ahead and
780:53
Speaker A
assign self. name equals name and let's assign self. sub equals subject here and as before let's assume that there's some more functionality associated with professors as well well what do you notice already here in my definitions of St students and
781:09
Speaker A
professors typically we're a bit reluctant to allow for any redundancy in our code and here I feel like my init method is taking a name for students my init method is also taking a name for a professor and I have these identical
781:23
Speaker A
lines of code like self. name equals name and this is only going to get exacerbated if I now go and add some error checking so for instance How about if uh if not name we should probably be in the habit of raising something like a
781:35
Speaker A
value error in an explanatory message like missing name and you know what if a professor is missing their name I should probably copy paste that code down here and that's where Red Flag should be going off whereby as soon as you start
781:48
Speaker A
copy pasting code there's probably a better way so that we can write the code once and perhaps reuse it in some way and here too object-oriented programming offers a solution it turns out that object-oriented programming in Python also supports inheritance whereby you
782:04
Speaker A
can Define multiple classes that somehow relate to one another they don't need to exist sort of in parallel in this way there could actually be some hierarchy between them so for instance in The Wizarding World we could argue that both
782:16
Speaker A
a student and a professor are at the end of the day Wizards so maybe what we should really Define is a third class for instance called wizard that has any of the common attributes for students and professors alike and for now we've
782:29
Speaker A
kept it relatively simple the only thing they have in common is a name and a name in student and Professor respectively so why don't we minimally factor that out first all right so let me go ahead here and just to keep things organized at the
782:42
Speaker A
top of my file let's define a third class called Wizard and a wizard will have its own initialization method so decore uncore init underscore uncore and self as always and a wizard let's say for now is only going to be initialized
782:56
Speaker A
with their name in this way and now I'm going to go ahead and do some of that error checking so if not name we'll raise a value error in the Wizard class otherwise we'll go ahead and do self.
783:08
Speaker A
name equals name and heck dot dot dot maybe some other functionality as well but not a subject which is specific to professors and not a house which I've claimed is specific to students now I think we can begin to maybe remove some
783:21
Speaker A
of the redundancies in our other classes here so for instance down with student why don't I go ahead and remove this error checking here and remove this error this assignment of self. name equals name because I'm already doing
783:35
Speaker A
that in Wizard and similarly down here in Prof Professor why don't I do the same let's get rid of the error checking let's get rid of self. name equals name because I'm again I'm doing that already up there for Wizard as well but at the
783:47
Speaker A
moment even though they're all in the same file I haven't told python that a student is a wizard and a professor is a wizard so I really need to link these two together and the way you can prescribe inheritance whereby one class
784:00
Speaker A
should inherit from another or conversely one class should descend for another from another we can do this I can say class student but before the colon I can go in and say in parenthesis a student inherits from or is a subass
784:15
Speaker A
of wizard which conversely is the super class of the student class so this just means that when I Define a student class go ahead and inherit all of the characteristics of a wizard as well and I'm going to do the same thing for Prof
784:29
Speaker A
for Professor so parenthesis wizard after the class name professor and that's going to give me access to some of that same functionality but because my student class and my professor class still have their same init methods those are the
784:43
Speaker A
methods that are going to get called whenever I create a student in code or I create a professor in code I need to somehow explicitly say that I also want to use the functionality in the Wizard classes init method and the way to do
784:56
Speaker A
this in Python is is as follows let me go into my init method for student and let me call Super with no arguments which is a reference to the super class of this class so if this class is
785:07
Speaker A
student the super class that is the parent class is Wizard so super open paren closed paren will have the effect of accessing the super class and then I'm going to go ahead and explicitly call its init method and I'm going to
785:21
Speaker A
pass to the Wizards init method the name that the students init method was passed and I'm going to go ahead and do the same down here in Wizard this is one line of copy paste but I think I'm okay
785:34
Speaker A
with it here because it's still allowing me to do all of the name assignment and the error checking up in the Wizard class instead I think we're okay now by just calling super. init for both student and Professor alike now
785:47
Speaker A
admittedly this syntax is definitely out there the fact that we're calling super and parentheses and dots and underscore underscore on the left and the right of in it here but it's just a combination of these two ideas super open
785:59
Speaker A
parenthesis closed parenthesis is a way of programmatically accessing a current classes parent class or super class and underscore uncore init of course is just referring to now that class's own initialization method now per the dot dot dots there could be a lot more going
786:13
Speaker A
on in these classes but what's nice now is that wizard as a class is taking care of all of the assignment of a Wizard's name whether that wizard is a student or a professor and it's even doing some
786:24
Speaker A
error cheing to make sure that the name was actually passed in meanwhile student is inheriting all of that functionality and using it by calling the super class's own init method but it's additionally taking the house that's presumably passed into the student
786:39
Speaker A
Constructor function and assigning it to its own instance variable self. house and similarly Professor are we storing in self- thought subject the subject that was passed into there that one as well now how might we use these classes
786:53
Speaker A
well we'll continue to wave our hands with a little bit of detail here but if at the bottom of this file or any other file that Imports this one I could now write code like this I could create a
787:02
Speaker A
student variable and assign it the return value of the student Constructor call and maybe that student is named Harry and that student's house for instance might be Gryffindor and meanwhile I might do something like this professor equals professor over here and
787:18
Speaker A
notice the lowercase s on the left capital S on the right same for Professor on the left lowercase and uppercase on the right respectively Professor quote unquote seus and how about defense against the dark arts will be his subject and meanwhile if we want
787:35
Speaker A
more generically just a wizard who at the moment is neither student nor Professor teaching classes actively we could even do that we could do wizard equals wizard in capital W on the right hand side of the equal sign because it's the name of
787:48
Speaker A
the class and someone like Albus passing in only albus's name not a house not a subject because in this case he's known only as a wizard meanwhile with each of these calls this line of code here will ensure that the init method for the
788:04
Speaker A
wizard class is called this line of code here will ensure that the init method of the student class and in turn the init method of the super class wizard is called and then lastly on this final line of code will this syntax ensure
788:16
Speaker A
that the init method of the professor class is called which in turn calls the init method of the super class as well any questions now on this idea of inheritance which is a key feature of a lot of
788:30
Speaker A
objectoriented programming languages um so is there any situation where because uh from what I've seen so far A lot of times there's like a lot of nesting if you do subar does it go one up is there any situation where you know it's nested
788:44
Speaker A
in another class as well um above wizard let's say a really good question if you were to have a super super class so your hierarchy is even taller than the two levels of uh hierarchy that we currently have absolutely but what's nice about
788:58
Speaker A
object-oriented Pro what's nice about inheritance as the name implies is just as you might have inherited certain traits as a human from your grandfather and Grand mother or your great-grandfather or great-grandmother some of those properties can actually uh
789:12
Speaker A
trickle down to you so to speak in the context of code as well so when you descend from another class that is when you subclass a a super class or a super super class you actually do inherit all
789:26
Speaker A
of the functionality not just from one level above you but from two or three so you can indeed access some of that functionality as well and you can even override it if you want some of these classes to behave a little bit
789:36
Speaker A
differently than others other questions on inheritance so it's kind of similar to the last one but can you have like two parents on the same level a really good question so there are ways to implement uh um descendants from
789:52
Speaker A
multiple parents and there's different ways to do this not just in Python but other languages we've kept things simple here though by having a single uh inheritance path a good question how about one more question on inheritance can we have multiple arguments in super
790:09
Speaker A
doubleit yes but in this case I'm only passing in name on line 18 and I'm only passing in name on line 10 why because on line two when I Define the init method for the wizard class I only
790:22
Speaker A
expect a single argument but I could absolutely have under common functionality like I could add in a petronis if both students and professors have patronises that can come out of their wands I could have two arguments instead we've been using this feature of
790:36
Speaker A
object-oriented programming now for quite some time in the form of exceptions indeed if you look at the official documentation for exceptions in Python you'll see that there's not even the ones we've seen in class like value error and others there's any number of
790:49
Speaker A
others as well but they are all themselves hierarchical in nature this is just a subset of the available exceptions that come built into Python and you can actually as a programmer create your own exceptions as well but as this chart here uh captures
791:04
Speaker A
hierarchically all exceptions we've seen thus far actually descend from or inherit from Super classes already so for instance at the bottom of this list here is value error which we've seen quite a bit and if you follow the line
791:18
Speaker A
straight up on this asky rendition of this chart you'll see that value error has a parent class or super class called exception and the exception class meanwhile has a parent class called base exception why did the authors of python
791:30
Speaker A
do this well it turns out that whether you have a uh value error or a key error or an assertion error or any number of others there's a lot of functionality common to all of those types of errors
791:43
Speaker A
that you want uh all that you want a programmer to be able to use and so it turns out that the authors of python decided you know what let's not have a dozen or more different classes that all
791:55
Speaker A
just have copy pasted similar functionality let's create this hierarchy so that even though the exceptions toward the bottom of this list are very precise they at least inherit that is borrow some very common fun fun ality up above so it turns out
792:09
Speaker A
that when you use the try and the accept keyword in Python generally speaking we've tried to catch very specific exceptions like value error but technically you could capture the parent or even the grandparent exception for a given exception especially if you're not
792:24
Speaker A
necessarily sure which one is going to get raised or better yet there could be many exceptions that get raised but you want to handle them all the same and you don't want to necessarily enumerate them in parenthesis separated by commas you
792:36
Speaker A
want to say you want to handle all exceptions of a certain super class in much the same way so this has been latent this whole time anytime we've seen or used or caught or now raised exceptions and built into python is this
792:48
Speaker A
hierarchy and if you were to invent your own exception generally you wouldn't want to start from scratch you would want to descend from that is subclass one of these existing exceptions and add your own twist on it your own
793:00
Speaker A
functionality as well well there's one final feature of object-oriented programming that we'd like to share with you today in that it will perhaps be quite the eye opener is what you can really do now that you have classes at
793:12
Speaker A
your disposal and this too surprise has been a feature you and I have been taking for granted for weeks now this has just worked but it's been implemented in a way that you can now leverage yourself it turns out that
793:24
Speaker A
Python and some other languages too support this notion of operator overloading whereby you can take very common symbols like plus or minus or other such syntax on the on the keyboard and you can Implement your own interpretation thereof plus does not
793:41
Speaker A
have to equal addition and minus does not have to equal subtraction and in fact you and I have already seen another context in which plus means something else plus has not always in Python meant addition per se what else has python
793:58
Speaker A
used Plus for concatenation for concatenation for joining two strings for adding to a list can you use plus as well so plus has actually been funny enough overloaded by the authors of python for us and so we can use the same
794:13
Speaker A
symbol in much the same way as addition but with different data types to solve slightly different problems well let me propose that we go back over to VSS code here and let me go ahead and create a new Final file called vault. py so code
794:26
Speaker A
of vault. py and let me propose that we implement the idea of a vault at grots keeping on theme wherein there's a bank in the World of Harry Potter and within this Bank uh family and individuals have vaults containing all sorts of money in
794:41
Speaker A
The Wizarding World and the type of money that exists in the World of Harry Potter are coins called gallions and sickles and canuts and those are in descending order of value and so inside of a vault might be a whole bunch of
794:52
Speaker A
coins gold silver and bronze essentially each in those denominations tucked away so how can I go about implementing first of all the idea of a vault so that I can store for instance for Harry Potter how much uh coinage is in his family's Vault
795:07
Speaker A
or for Juan resley the same let me go ahead in Vault up high and first create a class called Vault essentially meant to represent a bank vault perfect another real world or fantasy world entity that I want to represent with
795:20
Speaker A
code I could use a tupple or a list or a dictionary but again I'm going to get a lot more functionality with classes and we'll see one final flourish with operators inside of this Vault class let's go ahead and do this let me Define
795:32
Speaker A
my init method taking its first argument of self and let me Define uh three arguments to this when you create a vault in my code here I want to be able to initialize it with some number of gallions some number of sickles and some
795:45
Speaker A
number of conuts I want the use the programmer to be able to pass in one or more of those values ideally but they can be optional so I'll give them defaults so let's go ahead and Define a parameter called gallions whose default
795:57
Speaker A
value will be zero sickles whose default value will also be zero and canuts whose default value will be zero as well so the programmer can pass in one or two or three or heck even none of those and
796:08
Speaker A
they'll all have some implied defaults how do I want to remember those values that are passed in well let me do this self. gallion equals gallion and self.
796:18
Speaker A
sickles equals sickles and self. canuts equals canuts and so I could add some error checking especially if you don't pass in a number I could turn these into properties to do even more validation but let's keep it simple and as always
796:32
Speaker A
Focus only on the new ideas so I'm just going to trust that these values were passed in and I'm going to immediately assign them to these instance variables what now do I want to do well let's come up with a way of printing out what is in
796:45
Speaker A
someone's Vault ultimately but first let's do this let's create a a vault for The Potters by creating via assignment a new Vault and let's say that the Potters have 100 gallions 50 sickles and 24 canuts all right and that's in that
796:59
Speaker A
Vault and let's print out for instance Potter all right let's run this code and see how it works now let me go ahead and run python a vault. pi enter okay seems to work no syntax errors or anything else but this is not very
797:13
Speaker A
enlightening how do I fix this thinking back to what we've done before you have to use the underscore underscore s exactly I need to use one of those special methods that comes with classes and Define for myself how I want a vault
797:28
Speaker A
to be printed as a string so let me go ahead and do that let me Define the stir method taking in self as its sole argument here and let's just return a very simple string that just reveals what's in the vault so I'm going to
797:40
Speaker A
return a formatted F string uh inside of which is self. gallan and then the word uh gallion so I know which those are uh then let's do self. sickles and let's output the word sickles and then lastly let's output self. canuts and then
797:55
Speaker A
canuts here so I know in this string just how many of each of those uh coins I have in this particular family's Vault all right let me go ahead and run python of vault. changing nothing else except the stir method and now we see indeed
798:11
Speaker A
that Harry has 100 gallions 50 sickles and 25 canuts all right well let's do one thing more here below that let's go ahead and Define a Weasley variable and Ron never seemed to have quite as much uh money in the vault as did Harry so
798:24
Speaker A
let's say that the Weasley Vault will have 25 50 and 100 so I'll just reverse the order of those denominations uh rather than Harry's 100 5025 and now let me go ahead and print Weasley like this and let's go ahead and clear my terminal
798:38
Speaker A
window run python of vault. this time that stir method will be invoked twice once for each of those Vault objects and we'll see indeed that the first one for Harry's got 50 and 25 respectively versus Ron's 25 50 and 100 respectively
798:54
Speaker A
but now let's do something interesting suppose that you wanted to combine the contents of two vaults be it Harry's and Ron's or any other two people how would you go about doing this in code well if I wanted to combine the vaults for
799:07
Speaker A
someone I could do this well I could do gallion equals let's do potter. gallion uh plus Weasley do gallion that gives me a variable called gallion that has the sum of Harry and Ron's gallion let's next do sickles equals potter. sickles
799:26
Speaker A
plus Weasley do sickles and then lastly let's do canuts equals potter. canuts plus Weasley do canuts I've got three variables what can I now do with these values well let's create a third a new Vault uh total will
799:41
Speaker A
be the name of this variable equals a new Vault capital V notice and now let's pass in those three new variables gallions sickles and canuts and that's it and let's print out this total Vault so we should now see three vaults one
799:54
Speaker A
for Harry for Ron and the combination the addition of the two let me go ahead and rerun python of vaulty and there we have it uh what was 10050 25 and 25 50 and 100 combined through addition now is
800:08
Speaker A
125 100 125 so pretty straightforward using techniques from weeks ago where we're just declaring a few new variables and doing some addition but wouldn't it be cool if I could do something like this wouldn't it be cool if I could just
800:23
Speaker A
somehow not manually create my own Vault and do all of this annoying math up here what if I could just do Potter plus Weasley and get rid of all of this logic here like wouldn't it be nice if I
800:35
Speaker A
overload the operator no we know as plus just like stir does just like list does to allow me to add two vaults together on the left and the right well it turns out in Python and through operator overla there is a way to do just this if
800:53
Speaker A
you consult the documentation there are there's this and so many other special methods that come with classes the third one we see here is this one here underscore uncore add underscore underscore and you see that it very generically is described in the
801:09
Speaker A
documentation as working for any object be it a vault or a stir or a list or something else by convention it's going to take a first argument called self and then it's going to take some other argument by convention called Other Self
801:21
Speaker A
in effect is going to be referring to whatever object is on the left of a plus sign other is going to be referring to whatever is on the right hand side of a plus sign thereby giving us a way of
801:31
Speaker A
describing in code the operand on the left and the operand on the right of the operator Plus in between that is to say if I go back to vs code here what I'm trying to do is Implement support for
801:44
Speaker A
this well let me try without writing any other code just yet python a vault up high enter type error unsupported operand types for Vault and Vault that is to say python at this moment does not know what it means to add two vaults
802:01
Speaker A
together right you and I might have an instinct probably want to combine the gallions and the sickles and the canuts respectively python doesn't know that it just knows that you have a new class called Vault but let's teach python to
802:13
Speaker A
do this let me clear my terminal window let me scroll back up to the class itself where at the moment I only have two special methods in it and stir but let's add this third all right let me go
802:24
Speaker A
into the class here and Define underscore uncore addcore underscore and then specify its first parameter as self as before and then a second parameter for this particular method called by convention other now as always I could name those parameters anything I want
802:38
Speaker A
but I'm going to stick with convention Here and Now inside of this method am I going to have to now add together the contents of two vaults well what two vaults well if we scroll down to our goal at hand the goal of course is to
802:49
Speaker A
add this Vault plus this other Vault Potter plus Weasley respectively well it turns out in Python that when you do overload an operator like Plus what's going to happen automatically as soon as python sees that is it's going to call
803:02
Speaker A
that underscore underscore ad underscore underscore method and it's going to pass into it to our arguments whatever the operand is on the left Potter in this case and whatever the operand is on the right Weasley in this case and those
803:14
Speaker A
values are going to get passed in as self and other respectively what that means is that we can access their contents up here in our implementation of AD as follows let me go ahead and Define a local variable called gallion
803:26
Speaker A
and set that equal to for instance the sum of self. gallions whatever's in uh Potter's vault in this case plus whatever is in Weasley's vault in this case which would be other do gallion let me do the same for sickles self. sickles
803:41
Speaker A
plus other do sickles and let me lastly do that for canuts so self. canuts plus other. canuts but at the end of the day I'm going to need to return a brand new bigger Vault that contains all of those
803:54
Speaker A
contents together and if we ultimately want to assign that bigger Vault to a variable like total here on the left we better indeed return a value from this ad method so I'm going to go ahead and give myself a brand new vault as by
804:07
Speaker A
returning Capital vault which of course is going to call My Vault function into which I can now pass some of those initialization arguments well how many gallion sickles and canuts do I want this brand new Vault to contain well I
804:19
Speaker A
want it to contain this many gallions this many sickles and this many canuts so ultimately what we're doing in this implementation of ad is adding together those gallion sickles and canuts passing them to the Vault function so that we
804:32
Speaker A
get a brand new bigger Vault and return that all together so now I've defined this new special method called add that should now just make Plus work for two vaults all right let's see let me run down to my terminal window python a
804:48
Speaker A
vault up high and hit enter and voila now we've implemented an overloaded operator plus to do what you and I as humans would hope would be the case when you add two vaults together but I've now written the code more specifically to
805:02
Speaker A
teach python what it means concretely to add two vaults together and it's with very similar code in effect underneath the hood that python is doing this for two strings to concatenate them together to joining to lists into a new list with
805:16
Speaker A
lists and so many other classes as well any questions now on operator overloading or this example here how would you go about creating a function for adding a student and a vault for two two separate classes how would that be
805:35
Speaker A
possible let me see what happens here I don't know off hand let's do this let's create a stir and see what happens if I add Potter plus a stir stir object yeah okay so it would work I'm just figuring this
805:47
Speaker A
out as I go here Eric so just to re be clear what I did was I just changed Weasley to stir just to see what would happen when I add a vault plus a stir and it will work theoretically why
805:58
Speaker A
because so long as the type of value on the left has an add method implemented other can be any type that you want you just have to decide and code what it's going to mean conceptually to add a
806:11
Speaker A
vault plus a string which in this case probably doesn't make any sense at all but it's possible it's going to be the operand on the left and I'm inferring that I did not know the answer a moment ago I'm inferring that because what I
806:22
Speaker A
got was an attribute error here on line 11 because python did not like this other gallion didn't work but I could make it work by figuring something out really good question didn't know that one myself other questions on
806:37
Speaker A
operator overloading can you define new operators in Python I don't think so there is a very long but precise list of operators that you can overload I do not believe you can assign arbitrary characters to be operators in Python uh
806:53
Speaker A
let me defer to Carter in the chat to revoke okay I'm seeing two of my colleagues are saying no not possible so I'm going to go with my first instinct no otherwise that'd be kind of cool you could make Emoji do whatever you want to
807:04
Speaker A
how about one final question on operator overloading is that the only operation you can do uh is a far as like can you do a subtraction as well you can you can do so many others let me um if Carter you
807:17
Speaker A
don't mind pulling up this URL here so this link here special method names in today's slides you'll see a long list of all of The Operators that you can overload you can do less than equals than plus equals minus equals pretty
807:30
Speaker A
much any symbol you've seen me type on the screen can be overloaded in the context of classes so even though today we focused entirely on object-oriented programming this is a technique that we've been using really since the first week of the
807:43
Speaker A
class because indeed those ins those stirs those floats those lists those dictionaries and so much more were already underneath the hood this whole time classes and objects thereof but you now as a programmer have the ability to create your own classes with your own
807:57
Speaker A
instance or class variables with your own instance or class methods with your own properties and even with your own custom behavior for operators so ultimately you can absolutely continue using those simple tles or lists or those dictionaries or other structures
808:12
Speaker A
as well but object-oriented programming and with it classes and now these objects is just another tool in your toolkit and dare say as your code gets more sophisticated and your problems get bigger you'll find that being able to
808:24
Speaker A
model these real world or even fantasy world entities with classes and related data and functionality will ultimately just allow you to Define code that's not just correct but ever well designed as well this was cs50 [Music] [Music] all right this is cs50's Introduction to
809:11
Speaker A
programming with python my name is David me and over these past many weeks have we focused on functions and variables early on then conditionals and loops and exceptions a bit of libraries unit tests file AO regular Expressions object-oriented programming and really
809:27
Speaker A
Etc and indeed that's where we focus today is on all the more that you can do with python and programming more generally Beyond some of those fundamental concepts as well in fact if you start to flip through the
809:38
Speaker A
documentation for python in all of its form all of which is as always accessible at docs. python.org you'll see additional documentation on Python's own tutorial in library uh its reference it's how to and among all of those various documents as well as others more
809:53
Speaker A
online you'll see that there's some tidbits that we didn't quite touch on and indeed even though we themed these past several weeks of around fairly broad topics that are rather essential for doing typical types of problems in Python it turns there's quite a number
810:07
Speaker A
of other features as well that we didn't necessarily touch on that didn't necessarily fit within any of those overarching Concepts or might have been a little too much too soon if we did them too early on in the course and so
810:18
Speaker A
in today our final lecture will be Focus really on all the more that you can do with python and hopefully wet your appetite for teaching yourself all the more too for instance among Python's various data types there's this other
810:30
Speaker A
one that we haven't had occasion to yet use namely a set in mathematics a set is typically a collection of values wherein there are no duplicates so it's not quite a list it's a bit more special than that in that somehow any duplicates
810:42
Speaker A
are eliminated for you well it turns out within python this is an actual data type that you yourself can use in your code and via the documentation here might you be able to glean that it's a useful problem if you want to somehow
810:55
Speaker A
automatically filter out duplicates so let me go ahead and go over to VSS code here and let me go ahead and show you a file that I created a bit of in advance whereby we have a file here called
811:06
Speaker A
houses. and in houses. I already went ahead and whipped up a big uh list of students inside of which is a number of dictionaries Each of which represents a student's name and house respectively now this is a pretty sizable dictionary
811:21
Speaker A
and so it lends itself to iteration over the same and suppose that the goal here was quite simply to figure out well what are the unique houses at Hogwarts in the World of Harry Potter it would be nice
811:31
Speaker A
perhaps to not have to know these kinds of details or look them up online here we have a set of stud students albeit not exhaustive with all of the houses but among these students here what are the unique houses in which they live
811:43
Speaker A
well I could certainly as a human just eyeball this and tell you that it's well Gryffindor Slither and Ravenclaw but how could we go about doing it programmatically for these students as well well let's take one approach first
811:53
Speaker A
here let me go into houses. and let me propose that we first how about create an empty list called houses in which I'm going to accumulate each of the houses uniquely so every time I iterate through this uh list of dictionaries I'm only
812:09
Speaker A
going to add a house to this list if I haven't seen it before so how do I express that well let me iterate over all of the students with for student in students as we've done in the past and
812:20
Speaker A
let me ask a question now so if the current student's house and notice that I'm indexing into the current student because I know they are a dictionary or dict object and if that student's house is not in my houses list then indented
812:37
Speaker A
am I going to say houses. append because again houses is a list and I'm going to append that particular house to the list then at the very bottom here let me go ahead and do something somewhat interesting here and say for each of the
812:51
Speaker A
houses that I've accumulated in I could just say houses but if I just say houses what was the point of accumulating them all all at once I could just do this whole thing in a loop let's at least go
813:01
Speaker A
about and sort those houses with sorted which is going to sort the strings Al alphabetically and let's go ahead there in and print each of the houses let me go ahead now in my terminal window and run python of houses. and hit enter and
813:14
Speaker A
there we have it Gryffindor Ravenclaw Slytherin in alphabetical order even though in the list of dictionaries up here technically the order in which we saw these with was Gryffindor Gryffindor Gryffindor slitherin Ravenclaw so indeed my code seems to have sorted them
813:30
Speaker A
properly so this is perfectly fine and it's one way of solving this problem but it turns out we could would use more that's built into the language python to solve this problem ourself here I'm rather Reinventing a wheel really the
813:43
Speaker A
notion of a set wherein duplicates are eliminated for me so let me go ahead and clear my terminal window and perhaps change the type of object I'm using here instead of a list which could also be written like this to create an empty
813:55
Speaker A
list let me go ahead and create an empty set whereby I call a function called set that's going to return to me some object in Python that represents this notion of a set wherein duplicates are automatic eliminated and now I can tighten up my
814:08
Speaker A
code because I don't have to use this if condition myself I think I can just do something like this inside of my Loop let me do houses. add so it's not a pend for a set it's a pen for a list but it's
814:20
Speaker A
add to a set per the documentation then let me go ahead and add this current student's house and now I think the rest of my code can be the same I'm just now trusting per the documentation for set
814:32
Speaker A
in Python that it's going to filter out duplicates for me and I can just blind add add add add all of these houses to the set and any duplicates already there will be gone python of houses. and enter
814:45
Speaker A
and voila we're back in business with just those three there as well let me pause here to see if there's any questions now on this use of set which is just another data type that's available to you another class in the
814:56
Speaker A
world of python that you can reach for when solving some problem like this how can we locate an item in a set for example find Griffin door in the oh how do you find an item in a set you can use
815:09
Speaker A
very similar syntax as we've done for a list before you can use syntax like if Gryffindor in houses then and you can answer a question along those lines so you can use in and not in and similar functions as well other questions on set
815:26
Speaker A
okay what happens if you have a similar house name let's say instead of slithering it is maybe an O instead of an I will the fall Loop look throughout each of those um letters in the house name uh it would compare the string so
815:43
Speaker A
if Slytherin appears more than once but is slightly misspelled or misc capitalized if I heard you right those would appear to be distinct string so you would get both versions of Slytherin in the result however we've seen in the
815:56
Speaker A
past how we can clean up users data if indeed it might be messy we could force everything to uppercase or everything to lowercase or we could use capitalize the function built into stirs or title case that would handle some of the cleanup
816:09
Speaker A
for us in this case because the data is not coming from humans using the input function I wrote the code in advance it's safer to assume that I got the houses right but that's absolutely a risk if it's coming from users allow me
816:21
Speaker A
to turn our attention back to some of the other features here that we can leverage in Python if we dig further into the documentation and read up more on its features well in some language there's this notion of global variables
816:33
Speaker A
whereby you can define a variable that's either local to a function as we've seen many times or if you put a variable outside of all of your functions perhaps near the top of your file that would generally be considered a global
816:47
Speaker A
variable or in the world of python it might be specific to the module but for all intents and purposes it's going to behave for a given program as though it is global however it turns out that if you do this when solving some problem
816:58
Speaker A
down the line whereby you have multiple functions and you do have one or more variables that are outside of those functions you might not be able to change those variables as easily as you might think so indeed let me go back to
817:12
Speaker A
vs code here and in just a moment I'm going to go ahead and create a new file how about called bank.pay let's go ahead and implement the notion of a bank wherein we can store things like uh money in various
817:24
Speaker A
forms and let me go ahead and do this let me go ahead and Implement a very simple bank that simply keeps track of my total balance the number of dollars or cents or whatever I might be storing in this bank and I'm going to give
817:35
Speaker A
myself a very iable called balance at the top which is an integer a set to zero now let me go ahead and Define a main function as we often do and inside of my main function let me go ahead and
817:45
Speaker A
print out quote unquote balance and then print out the value of balance itself passing to print as we've often done more than one argument so that they get uh separated by a single white space And now since I have a main function really
817:58
Speaker A
setting the stage for doing more interesting things soon let me go ahead and do our usual if the name of this file equals equals underscore uncore main then go ahead and call Main so this is a terribly short program but it's
818:12
Speaker A
perhaps representative of how you might solve some future problem in Python whereby you have a main function that's going to eventually do some interesting stuff and at the top of your file you have one or more variables that are just
818:23
Speaker A
useful to keep there because then you know where they are and perhaps not just main but other functions can access them as well so let's see when I run this program python of bank.pay I would hope based on my own in thus far then I'm
818:37
Speaker A
going to see that my current balance is zero that is to say even though the balance variable is defined on line one hopefully I can still print it on line five inside of main even though balance was not defined in my main function here
818:51
Speaker A
we go hitting enter and voila balance zero so it does seem to work even if you declare a variable in Python outside of your functions it appears that you can access it you can read the value of that
819:03
Speaker A
variable even inside of a function like Maine well let's get a little more adventurous now because this program really isn't solving anyone's problems let's go ahead and Implement more of a bank like the ability to deposit money into the bank and to withdraw money from
819:17
Speaker A
the bank thereby giving me some more functions that might very well need to access that same variable Let Me Clear My terminal window here and let me go ahead and pretend for the moment that I have the ability to deposit say $100 or
819:31
Speaker A
100 coins whatever the unit of currency is here and then maybe I want to withdraw straight away 50 of those same dollars or coins and now let me go ahead and just print out at the bottom of main
819:42
Speaker A
what my new balance should be so that in an Ideal World once I've deposited 100 then withdrawn 50 after starting at zero I'd like to think that my new balance on line 8 should indeed be 50 all right but
819:56
Speaker A
I haven't implemented these functions yet so let's do that as we've done in the past down here I'm going to go ahead and Define another function deposit I'm going to say that it takes an argument called n for number of coins or dollars
820:07
Speaker A
or the like and I'm just going to do this I'm going to go ahead and say balance plus equals n thereby changing the value of N I could do it more verbosely balance equals balance plus n but I'm going to use the shorter hand
820:19
Speaker A
notation here instead and now let's Implement withdraw so Define a function called withdraw it to is going to take a variable uh an argument n for number of dollars or coins and now I'm going to go ahead and subtract from balance using
820:33
Speaker A
minus equals uh n as well and I'm still going to call Main if the name of this file is main so what have I done I've just added not just one but three functions total all of which apparently
820:45
Speaker A
need to access balance by uh printing it incrementing it or decrementing it as we've seen here all right let me go ahead and focus on these three functions here let me go back to my terminal window and run python of bank.pay and
820:59
Speaker A
hit enter and wow seems like we've introduced some number of problems here and what are these problems well Unbound local error is perhaps the first time we've seen this one here local variable balance rep referenced before assignment and that's a bit misleading definitely
821:19
Speaker A
confusing right because I absolutely assigned balance of value on the top of my code and indeed if I scroll back up nothing has changed or been lost up there it's definitely been assigned a value and now on line uh 12 it would
821:32
Speaker A
seem that when deposit is called I'm just trying to access that variable again so intuitively what might explain this error message Unbound local error what is python telling us there that python can or can't do when it comes to
821:48
Speaker A
these so-called Global variables that are at the top of my file uh so if you want to change this V variable you should uh write in inside the function Main and the global variable unchangeable yeah so if you want to change the value it might
822:08
Speaker A
need to be local to the function if you are trying to change a global variable though in a function it clearly does not work so it's okay to read a global variable read meaning access it and print it and so forth but apparently you
822:21
Speaker A
can't write to a global variable in the same way from within one of these functions all right well maybe the fix is to do this let me clear my terminal window in that error and maybe I could just do this let's get rid of the global
822:32
Speaker A
variable and let's go ahead and put it for instance inside of main might this now work well let me try this now python of bank.pay enter that alone did not solve it I still have an Unbound local error this
822:48
Speaker A
time though it's for a different reason it turns out now that balance on line two is by definition a local variable a local variable is one that exists in the context of a function at least in this case a global variable is the opposite
823:03
Speaker A
one that does not for instance at the top of my file so here is another distinction in Python if you declare a variable in a function like main just as I've done on line two with balance it is
823:14
Speaker A
indeed local to that function deposit and withdraw do not have access to that same variable why because it's local to Main and so you would think now we're kind of stuck in this vicious cycle well maybe the solution then is to move uh
823:27
Speaker A
balance globally so all three functions can access it but clearly where we began as oena noted we can't therefore change it so what turns out the solution to this problem in Python is ironically exactly this keyword here it's a little
823:42
Speaker A
different as you might have seen if you programed before in other languages but there's indeed a keyword in Python called Global that allows you to tell a function that hey this is not a variable that's local to you I mean it to be a
823:53
Speaker A
global variable that I want you to edit so if I go back to VSS code here clearing my terminal window to get rid of that error let me go ahead and undo the change I just made and put balance
824:03
Speaker A
back at the top of my file but this time time what I'm going to do is I'm going to inform my two functions that need to change the value of balance that it is indeed Global by typing Global balance
824:17
Speaker A
again here as well as here Global balance I still leave the same lines of code now on lines 13 and 18 that increment and decrement balance but this now use of keyword Global is a little bit of a clue to python that oh okay
824:32
Speaker A
it's not a local variable this is not a bug that you've introduced you mean for to edit this variable up above so now let me go ahead in my terminal window and run python of bank.pay I'm hoping to
824:43
Speaker A
see that my balance is 0 + 100 minus 50 is 50 and indeed it now is it starts off at zero per my first print statement on line five but it ends up at 50 total at below that on line eight let me pause
824:58
Speaker A
here to see if now there's any questions on these Global or local variables what happens when you declare a variable globally and as in the same variable globally and in a function a good question you're always thinking about
825:12
Speaker A
the so-called Corner cases so if you declare a variable both globally like at the top of your file and then an identically named variable inside of a function same name the ladder Will Shadow so to speak the former that is
825:26
Speaker A
you'll be able to use the ladder that is the local variable but it will have no effect on the global variable temporarily python will only know that the local variable exists so in general the rule of thumb is just don't do that
825:40
Speaker A
not only might it create bugs in your code because you don't quite change what you intend to change it's also perhaps uh nonobvious to other readers as well other questions on globals or locals okay what if we decide to add balance as
825:54
Speaker A
an argument inside the main function yeah another good Instinct but in this case that also is not going to solve the problem because if you pass in a variable like balance to each of the function functions and then change it
826:07
Speaker A
within that function it's only going to be changing in effect a local copy thereof it's not going to be changing what's outside of those functions so I think we actually need a better way altogether and in fact allow me to
826:19
Speaker A
transition to perhaps a modification of this same program recall that we looked most recently at this notion of objectoriented programming whereby you can model real world entities for instance a bank and you can model and encapsulate information about that real
826:35
Speaker A
world entity for instance like someone's account balance so let me propose that we actually do this let me start from scratch with bank.pay get rid of the global variable Al together and actually use some objectoriented code let me
826:48
Speaker A
define a class called account to represent someone's bank account and then let me go ahead and initialize with my init method which again takes by convention at least one argument called self let me go ahead and initialize every person's bank account to some
827:06
Speaker A
value like zero now how can I do that well I'm going to go ahead and do self.
827:10
Speaker A
balance equals 0 thereby giving me an instance variable called balance initialized for this account to zero but I'm going to proactively remember how we also introduced this notion of properties which might otherwise collide with the names of my instance variables
827:25
Speaker A
so just by convention I'm going to do this I'm going to rename this instance variable proactively to underscore balance to effectively indicate that it's private even though that's not enforced by python it's just a visual clue to myself that this is something
827:38
Speaker A
that really I should not or other code should not touch just functions in this class now let me go ahead and do this let me go ahead and Define an actual function called balance that really is going to be a property whose purpose in
827:51
Speaker A
life is just to return self. balance and I'm going to go explicitly and say this is indeed a property of this class now let me go ahead and reimplement those other two functions deposit and withdraw but in the confines of this class so I'm
828:06
Speaker A
going to say Define uh deposit it's going to take in an argument self as always but an additional One n a number of dollars or coins to deposit and how do I now manipulate this well I'm going to do self doore balance plus equals n
828:22
Speaker A
and now down here I'm going to do def withdraw self n just like for deposit but here I'm going to do self. balance minus equals n and now if I go down below this class I'm going to go ahead
828:35
Speaker A
and and Define myself a main function just so I can try this now out I'm going to go ahead and create an account object by calling the account Constructor that is the name of the class with two parentheses if I'm not passing in any
828:47
Speaker A
arguments to in it I'm going to go ahead now and print out as before the balance of my account but to do that I'm going to access the property of that account like this and I'm going to go ahead now
828:58
Speaker A
and say deposit another $100 or coins with deposit 100 and I'm going to go ahead like before and also now immediately withdraw for whatever reason 50 of the same and now I'm going to print One Last Time balance followed by
829:13
Speaker A
account. balance again accessing that property and for this whole thing to work of course I need one of these if name equals equals uncore main then go ahead and call Main now before I run this you'll see that it rather escalated
829:26
Speaker A
quickly I had a very simple goal at hand to implement the notion of a bank and I was able to implement that perfectly fine ultimately by declaring balance to be Global but then to tell each of my functions that it is indeed Global but
829:39
Speaker A
that's not really the best form of encapsulation we have at our disposal now right per our focus on object-oriented programming if we're trying to implement some real world entity like an account at a bank that's what classes allow us to do and it
829:52
Speaker A
allows us to solve that same problem perhaps a little more cleanly certainly if we're going to accumulate more and more functions or methods over time so if I didn't make any mistakes here if I run python of bank.pay and hit enter now
830:05
Speaker A
you'll see that it just works just fine because in the world of classes in Python these so-called instance variables are by definition accessible to all of the methods in that class because we're accessing them all by way of that special parameter self so which
830:24
Speaker A
way to do it for a reasonably small script wherein you are simply trying to implement uh a script that has some Global uh information like an account balance that you then need to manipulate elsewhere the the global keyword is a
830:36
Speaker A
solution to that problem but generally speaking in many languages python to some extent among them using Global variables tends to be frowned upon only because things can get messy quickly and it be can become less obvious quickly exactly where your information is stored
830:52
Speaker A
if some of it's up here some of it's in your function so generally the rule of thumb is to use Global variables sparingly though technically speaking in Python these Global variables are technically local to our module if we
831:05
Speaker A
were indeed implementing a library and not just a program so in short try to use Global variables sparingly but when you do there is a solution to these same problems questions now on globals or our reimplementation of the same idea but
831:20
Speaker A
using full-fledged objectoriented programming uh I just uh would like to ask uh what this property does what this property does so if I go back to VSS code here you'll see that this was a Technique we looked at in our lecture on
831:35
Speaker A
object-oriented programming whereby a property is a instance variable that's somehow protected it allows me to control how it can be read and written so in this case I only have what's called generally a Setter and sorry in this case I only have what's generally
831:51
Speaker A
called a getter and there's no mention of the word getter here this is just what app property means that function balance will allow me recall to use syntax like this where I can pretend as though balance is indeed with no
832:04
Speaker A
underscore an instance variable but I can now prevent code like mine in main from trying to change balance because I do not have a Setter I would not be able to do something like account balance equals a th000 to just give myself
832:17
Speaker A
$1,000 doll or coins because I have not defined a Setter so again per our focus on object-oriented programming these properties just allow me some finer grain control some languages allow you to Define variables that are so to speak
832:31
Speaker A
constant that is once you have set a value to them you cannot not change the value of that variable and that tends to be a good thing because it allows you to program defensively just in case you accidentally or someone else
832:43
Speaker A
accidentally tries to modify the value of that variable if you have declared it in some language as a constant it cannot be changed or usually cannot be changed without great effort unfortunately in Python we're again on the sort of honor
832:56
Speaker A
System here where we have conventions to indicate that something should be treated as though it's constant but that's not actually enforced by the language so for instance let me let me go back here to vs code and let me
833:06
Speaker A
create a new file for instance called meow. pie and let's see if we can't implement the notion of a cat meowing on the screen so I'll do code of meow. py and in meow. pie let me go ahead for
833:18
Speaker A
instance and Implement a very simple program that just has a cap meowing three times so how about this for I in the range of three go ahead and print out quote unquote meow all right well we've seen in the past how we can clean
833:31
Speaker A
this up a little bit for instance if I'm not actually using I I might as well pythonic just change the name of that variable to underscore even though that has no functional effect here but here we have this three sort of randomly
833:44
Speaker A
hardcoded that is typed explicitly into my code and it's totally not a big deal when your code is only two lines but imagine that this is a much bigger program with dozens or even hundreds of lines and imagine that one of those
833:56
Speaker A
lines just is a three in there somewhere like you're never going to find that three very easily and it's going to be very easily overlooked by you or colleagues or others that you've hardcoded some magic value like a three
834:08
Speaker A
right there in your code so it tends to be best practice not just in Python but other languages as well anytime you have what is essentially a constant like a number three that shouldn't ever change is to at least let it Bubble Up surface
834:20
Speaker A
it to the top of your code so that it's just obvious what your code's constant values are and so by that I mean this at the top of this file it would probably be a little clear to colleagues and
834:31
Speaker A
frankly me tomorrow after I've forgotten what I did today to Define a variable like meow and set it equal to three and then instead of hardcoding three here or even lower in a much bigger program let me just go ahead and pass in that
834:45
Speaker A
variable's value to my Loop so that now it's just kind of obvious to me that meow is apparently the number of times to meow and if I ever want to change it the only code I have to change is at the
834:55
Speaker A
very top of my file I don't need to go fishing around or figure out what's going to break what do I need to change I just know that I can change these constants up at the top the problem
835:04
Speaker A
though with Pip Pyon is that python doesn't actually make variables constant it's indeed a convention in Python and some other languages to at least capitalize your variables when you want to indicate to the world that you should not touch this it is constant but there
835:19
Speaker A
is literally nothing in my code preventing me from saying you know what today I feel like four meows instead like that would work in other languages though there's typically a keyword or some other mechanism syntactically that would allow you to prevent line three
835:34
Speaker A
current Cy from executing so that when you tried to run your code you would actually get an error message explicitly saying you cannot do that so python again is a bit more on the honor System when it comes to these conventions
835:46
Speaker A
instead now it turns out there's other types of constants quote unquote that python uh typically manifest and in fact let me go ahead and change this around a little bit let me delete this version of meow and let me introduce again a class
835:58
Speaker A
from our discussion of object-oriented programming like a class representing a cat another real world entity recall that within classes you can have not just instance variables but class variables that is variables inside of the class that aren't inside of self per
836:14
Speaker A
se but they're accessible to all of the methods inside of that class here too there's a convention but not enforced by python of having class constants whereby inside of the class you might want to have a variable that should should
836:28
Speaker A
should not be changed but you just want to indicate that visually by capitalizing its name so for instance if the def number of meows for a cat is meant to be three I can literally inside of my class but outside of any of my
836:41
Speaker A
defined methods just create a class variable all capitalized with that same value and then if I want to create a method like uh meow for instance which as an instance method might take in self as we know and then I might have my Loop
836:55
Speaker A
here for underscore in the range of and now I need to access this the convention would be to say cat. meow to make clear that I want the meow variable that's associated with the class called cat then I'm going to go ahead and print out
837:08
Speaker A
one of these meows and now at the bottom of my code outside of the class let me go ahead and do something like this let me instantiate a cat using the cat Constructor notice this is important per our discussion of oop the class is
837:21
Speaker A
capitalized by convention but the variable over here is is lowercase and I could call it just C or anything else but I kind of like the symmetry of calling it little cat here and big cat so to speak over here and now if I want
837:34
Speaker A
this particular cat to meow that default number of three times I can just do cat.
837:38
Speaker A
meow like this and that method meow is going to per line five access that class constant but again it's constant only in the fact only in the sense that you should not touch that not that it's actually going to be enforced by the
837:54
Speaker A
language all right let me go ahead then and run this with python of meow STP and there it is three of our meows meow meow it turns out that python is uh dynamically typed language that is to say it's not strongly typed whereby when
838:09
Speaker A
you want an INT you have to tell the program that you are using an INT you don't have to tell the program that you are using a stir or a float or a set or anything else generally speaking to date
838:20
Speaker A
you and I when we're creating variables we just give a variable a name we frequently assign it using an the equal sign some other value and honestly python just kind of dynamically figures out what type of variable it is if it's
838:32
Speaker A
uh quote unquote hello world the variable is going to be a stir if it's 50 the integer the variable is going to be an INT now in other languages including C and C++ and Java and others it's sometimes necessary for the
838:46
Speaker A
programmer to specify what types of variables you want something to be the upside of that is that it helps you detect bugs more readily because if you intend for a variable to store a string or an integer but you accidentally store
839:01
Speaker A
an integer or a string the opposite or something else Al together your uh language can detect that kind of mistake for you when you go for instance to run the program it can say no you've made a mistake and you can fix that before your
839:14
Speaker A
actual users detect as much in Python 2 here it's again more of a friendly environment where you can provide hints to python itself as to what type a variable should be but the language itself does not strongly enforce these
839:29
Speaker A
rather you can use a tool that will tell you whether or not you're using a variable directly but it's typically a tool you would run as the programmer before you actually release your code to the world or if you have some kind of
839:41
Speaker A
automated process you can run this kind of tool just like you could reformat or lint your code with some other program before you actually release it to the world so how might we go about using these so-called type penss well they're
839:53
Speaker A
documented in the usual place in Python's own documentation and it turns out there's a program that's pretty popular for checking whether or not your code is adhering to your own typ pins and that program here is called mypie
840:06
Speaker A
and it's just one of several but this one's particularly popular and can be easily installed in the usual way with Pip install mypie and its own documentation is at this URL here but we'll use it quite simply to check
840:18
Speaker A
whether or not our variables are indeed using the right types so how can we go about doing this all right let me go back here to vs code clear my terminal window and in fact erase meow. Pie as it
840:29
Speaker A
currently was and let's Implement a different version of meow that quite simply has a function called meow that does the actual meowing on the screen and then I'm just going to go ahead and call that function down toward the
840:39
Speaker A
bottom I'm not going to bother with a main function just for Simplicity so that we can focus as always only on what's new so here we are defining a function called meow it's going to take a number of times T meow for instance n
840:52
Speaker A
for number and inside of this function I'm going to do my usual for underscore in the range of n Go ahead and print quote unquote meow So based on our earlier code I think this is correct not bothered defining the variable as I I'm
841:06
Speaker A
instead using the underscore because I'm not using it anywhere but I think I now have a working function whose purpose in life is to meow zero or one or two or three or more times well let's use this
841:16
Speaker A
function again not bothering with main I'm just going to keep my function at the very top because there's only one and I'm going to write my code uh here on line six so I'm going to give myself I'm going to ask the user for a number
841:28
Speaker A
and I'm going to go ahead and prompt them in the usual way for that number of times to meow and now I'm going to go ahead and call meow on that number now some of you might see what I've already
841:39
Speaker A
done wrong but perhaps I myself don't so let me go into my terminal window and run python of meow. py the goal being to prompt me this seems to be working I'm going to type in three and I would
841:50
Speaker A
expect now the meow function to print out meow three times enter but no there's some kind of type error here stir object cannot be interpreted as an integer why might that be why might that be because the input
842:09
Speaker A
function returns a string instead of an in exactly the input function returns a string or a stir not an INT so in the past of course our solution to this problem has just been to convert the string to an INT by using the int
842:23
Speaker A
function but now let me start programming more defensively so that honestly I don't even find myself in this situation at all let me go ahead and do this let me add what's called a type hint to my function that explicitly
842:36
Speaker A
specifies for meow what type of variable should be passed in I'm going to go ahead now and change the very first line of my code and my function to specify that n colon should be an INT and this
842:50
Speaker A
is a type hint the fact that I've added a Col in a space and the word int is not creating another int or anything like that it's just a hint an annotation so to speak to python that this variable on
843:02
Speaker A
the left called n should be an INT now unfortunately python itself doesn't care because again these type hints are not enforced by the language and that's by Design the language itself in the community prefers that python be dynamically typed not so strongly typed
843:19
Speaker A
as to require these things to be true but if I run meow. py type in three again the same error is there but let me go about trying this mypie program an example of a program that understands typ hints and if I run it proac actively
843:34
Speaker A
myself can find bugs like this in my code before I or worse a user actually runs and encounters something cryptic like this type error here let me clear my terminal window and this time run my Pi space meow. so I'm going to run my
843:50
Speaker A
piie on my program but I'm not running python itself when I hit enter we'll see this all right we see now that my pie found apparently an error on line seven error argument one to meow has incompatible typ stir expected int so
844:07
Speaker A
it's still an error message but mypie is not a program that my users would use this is a program that you and I as programmers would use and because we have run this code now before we for instance released this program to the
844:20
Speaker A
world I can now see even before the code is called or run oh I seem to be M using my argument to meow wrong I had better fix this somehow well I can actually go about in uh hint adding typ hints even
844:34
Speaker A
into my own variables here so as to catch this another way too if I know on line six that I'm creating already a variable called number and I know already that I'm assigning it equal to the return value of input I could give
844:48
Speaker A
my pi and tools like it another hint and say you know what this variable called number should also be an INT that is to say if I now start getting into the habit of annotating all of my variables
845:00
Speaker A
and arguments to functions maybe my Pi can actually help me find things quite quickly as well before I get to the point of running python itself let's go ahead and try this again my piie of meow. Pi and hit enter and this time
845:14
Speaker A
notice that my Pi actually found the mistake a little more quickly notice this time it found on line six that error incompatible types and assignment expression has Type stir variable has Type int so before I even got to the
845:28
Speaker A
point of calling meow line six via this typeint when used and analyzed by mypie has helped me find oh wait a minute I shouldn't be assigning the return value of input to my variable called number in the first place why mypie has just
845:43
Speaker A
pointed out to me that one returns a stir I'm expecting an INT let me fix this now instead all right so let me clear my terminal window and now let me do what most of you were probably thinking I should have done in the first
845:54
Speaker A
place after all of these weeks but now let me go ahead and convert the return value of input to an integer for today's purposes I'm not going to try to catch any exceptions or the we're just going to assume that the user types this in
846:06
Speaker A
properly and now let me go ahead and run my piie of meow. pie having not only added two typeint to my argument to my function to my variable down here on line six and I've also now fixed the
846:19
Speaker A
problem itself let me go ahead and run my piie and success no issues found in one source file now it's more reasonable for me to go and run something like python of meow and just trust that when I type in three at least I'm not not
846:34
Speaker A
going to get a type error that is I didn't mess up as a programmer with respect to the types of my variables why because when I wrote the coder in the first place I provided these annotations these hints that inform tools like my
846:47
Speaker A
piie that my intention had better line up with what the actual code does let me pause here and see if there's now any questions on tight pins or my pie is it common or how common is it for those to
847:00
Speaker A
be used or is it just that it's more used in more complex code um where it's more difficult to ensure that you're actually uh using the correct type in the way that you're using the variables it's a good question
847:14
Speaker A
and it's rather a matter of opinion python was designed to be a little more versatile and flexible when it comes to some of these details partly for uh writeability to make it easier and faster to write code partly for
847:26
Speaker A
performance so that the program like python doesn't have to bother checking these kinds of details we can just get right into the code the reality though is that uh strong type checks do tend to be a good thing for the correctness of
847:38
Speaker A
your code why because programs like mypie can find before your code is even run if there's already known to be an error and it tends to be good for defensive programming um so the the situation essentially is that within the
847:52
Speaker A
python ecosystem you can uh annotate your types in this way you can use tools to use those typin but to date python itself does not enforce or expect to enforce these conventions in larger code bases in professional code bases
848:07
Speaker A
Commercial Code bases probably depending on the product uh project manager or depending on the engineering team they may very well want themselves to be using typ pins why if it just decreases the probability of bugs in fact let me
848:20
Speaker A
propose now that I imagine a situation where instead of expecting that meow prints meow meow meow some number of times suppose that I accidentally uh assume that the meow function just returns returns meow some number of times we saw for instance when focusing
848:37
Speaker A
on unit tests that it tends to be a good thing to have functions that return values be it an INT or a string rather than just having some side effect like printing things out themselves so perhaps I'm still in that mindset and
848:48
Speaker A
I've just assumed mistakenly for the moment that meow returns a value like meow or meow meow or meow meow meow a big string of some number of meows rather than just printing it itself as it clearly does at the moment on line
849:01
Speaker A
three and therefore suppos that I accidentally did something like this rather than just getting the number and passing it to meow suppose I did this uh suppose I declared a number of a new variable called meows the type of which
849:17
Speaker A
I think should be stir and suppose again I assume accidentally that meow returns to me a string of those meows so that I myself can then print them later this would be a little more conducive arguably to testing my meow function why
849:32
Speaker A
because I could expect that it's return rning meow or meow meow or meow meow meow separated by new lines returning a stir that I could then assert equals what I expect it to be in something like a unit test I'm not going to bother
849:45
Speaker A
writing any unit tests now but let's just suppose that's the mindset I'm now in and so on line seven I'm assuming that I want to assign the return value of meow to a new variable called meow's which I've annotated with this type hint
849:59
Speaker A
as being a stir just so we can see another variable this one's not an INT but to stir instead well let me go ahead and run this code now python of meow.
850:09
Speaker A
enter typing in three and you'll see a curious bug meow meow meow none well why is that well it turns out at the moment my meow function only has a side effect it just prints out meow some number of
850:23
Speaker A
times it doesn't explicitly return a value as it would if there were literally the return keyword there by default then when a function in Python does not explicitly return a value it's implicit return value is effect none and
850:37
Speaker A
so what we're seeing here is this on line 8 because I'm assigning the return value of meow which is none to my meow's variable line three is what's still printing meow meow meow and line eight is what's now incorrectly
850:55
Speaker A
printing none because I accidentally thought that meow returns a value but it doesn't so its return value is effectively none so I'm printing very weirdly the word none at the bottom so how could I go about catching this kind
851:09
Speaker A
of mistake too like I might make this mistake but maybe with less frequency if I'm in the habit of annotating my code with this new feature called co uh typ Pence what you can do here is this let
851:20
Speaker A
me clear my terminal window to get rid of that artifact and up here let me additionally specify with some funny looking syntax that my meow function actually by Design returns none so you literally use this arrow notation in
851:35
Speaker A
Python when hinting what the return value of a function is you would do this after the parentheses a space a hyphen a greater than symbol like an arrow and then another space and then the type of the return value for now it's indeed
851:51
Speaker A
going to excuse me return none but now at least I can catch it like this if I now run not python but my P on my code which would be a habit I'm now getting into if using typ hints check that I'm
852:04
Speaker A
using all of my types correctly before I even run my program we'll see that now my Pie has found on line seven that meow quote unquote does not return a value and my Pi knows that because I have
852:16
Speaker A
proactively annotated my meow function as having none as its return value so now my piie can detect that I should now realize oh wait a minute I'm being uh foolish here ma meow clearly does not return a value I should not be treating
852:31
Speaker A
it like it does on line seven let me go about actually fixing this now so how do I go about fixing this well let's practice what we preached in our focus on unit tests having a function like meow not have side effects like printing
852:43
Speaker A
itself but let's have it return the actual string and I can actually do this kind of cleanly let me uh clear my error message in my terminal window here let me get rid of the loop here let me say
852:55
Speaker A
this time that okay fine meow is going to return a value an actual stir or string so I've changed none to stir and now I can implement this in any number of ways maybe even using a loop but
853:06
Speaker A
recall that we have this syntax in Python which will I think solve this problem for us if I want to return a string of n meows what I can actually do recall is this return quote unquote meow back sln times that number n so it's
853:24
Speaker A
kind of a clever oneliner avoids the need for a for Loop or something more involved than that to just say multiply meow back sln against itself three times ENT or end times in this case in general so that I get back a big string of zero
853:39
Speaker A
meows One Two Three or many more meows instead I think now my code on line six is actually correct now I've changed meow to behave the way I was pretending to assume it always worked so I'm storing in meow's plural a variable
853:55
Speaker A
that's of type stir because now meow does have a return value of type stir itself per this typ hint as well all right let me go ahead now and print meows but because each of my meows comes with a a trailing new line the back
854:11
Speaker A
slash n I'm going to proactively fix what would be a minor aesthetic bug and I'm just going to avoid outputting an extra new line at the end of those uh three so if I run python of meow. py now
854:22
Speaker A
type in three there's my meow meow meow and now no mention of none questions now on typ hints and these annot and mypie and using them to defensively write code that just decreases hopefully the probability of your own bugs in the
854:42
Speaker A
return there is a in return there is a double quotes that have meow sln why the program don't take it as a strange why does the program not take it as a a a strange see so so recall that
855:00
Speaker A
um early on in the class we looked at plus as a concatenation operator that allows you to join a string on the left and the right multiplication is also an overloaded operator for Strings whereby if you have a string on the left and an
855:14
Speaker A
INT on the right it will multiply the string so to speak by concatenating or joining that many meows all together so this is a feature of object-oriented programming an OB an operator overloading as we saw it uh in the past
855:30
Speaker A
other questions on typ Pence or mypod can we not type cast this data type of the you know of this variable number no you still and let me correct the terminology it wouldn't be called type casting in this context uh because it's
855:44
Speaker A
not like C or C++ where there's an equivalence between these types you're technically converting on line five a stir to an INT you do still have to do this because my piie for instance would yell at you if you were trying to assign
855:57
Speaker A
a stir on the right to an INT on the left you must still use the int function int it's self is still a function it's not a type hint but the word int is being used in another way now in these
856:10
Speaker A
type hints so this int is still a function call as it always has been this syntax on the left is another use of the keyword int but in the form of these type hint so you still have to do the
856:21
Speaker A
conversion yourself all right let me propose that we transition to another feature of python that's worth knowing especially since it's one that you'll see in the wild when you see code or libraries that other folks have written namely
856:34
Speaker A
something known as a dock string or document strings it turns out in the world of python there is a standardized way per another pep python enhancement proposal this one 257 that essentially standardizes how you should document your functions among other aspects of
856:51
Speaker A
your code and so for instance let me go back to my uh meow. py file here and let me propose that we now start documenting this code too so that I know what the meow function does and in fact the
857:03
Speaker A
standard way of doing this using dock string notation would be as follows to comment this function not above it as you might be in the habit of doing with code in general but actually inside of it but instead of commenting it like
857:17
Speaker A
this with the usual hash comment sign like meow n times it turns out that when you're formally docking when you're formally documenting a function like meow in this case you don't use regular inline comment so to speak you use this
857:33
Speaker A
syntax instead you use triple quotation marks either double or single then you write out your comment meow and times and then you write the same again at the end so either three double quotes at the start and the end or three single quotes
857:48
Speaker A
at the start and the end and python has built into it certain tools and certain assumptions that if it detects that there is a comment using this dock string format triple quotes on the left and the right it will assume that that's
858:02
Speaker A
indeed the doc mentation for that function and it turns out in the pyth python ecosystem there's a lot of tools that you can then use to analyze your code automatically extract all of these document strings for you and even
858:15
Speaker A
generate web pages or PDFs of documentation for your own function so there's these conventions via which if you adhere to them you can start documenting your code as for other people by generating automatically the documentation from your own code without
858:31
Speaker A
writing something up from scratch man manually now it turns out if your function uh does take arguments and perhaps does a bit more there are multiple conventions for how you can document for the human programmers that might be using your function whether
858:45
Speaker A
it's you or a colleague or someone else on the internet to actually use these doc strings to standardize the information they're in so you might see this instead using these same triple quotes above and below now you might see
858:59
Speaker A
your one sentence uh one sentence explanation of the function meow meow and times uh sometimes depending on the style in use it might actually still be on the first line but with a blank line below it but I'll keep everything
859:12
Speaker A
uniformly indented and this is a convention used by some popular python documentation tools as well you would say syntax like this Pam n colon and then a description of what n is number of times to meow then colon Type n colon
859:29
Speaker A
int which just indicates that the type of n is an integer then if this function could actually raise an exception you can document that too and actually it's not really well it's arguably my mistake here if n comes in as an argument and is
859:45
Speaker A
not in fact an INT maybe it's a float or a string or something else the multiplication sign here is not going to work it's not going to multiply the string it's going to trigger what I know from experience to be a type error so
859:57
Speaker A
I'm going to go ahead and proactively say in my own documentation that this function technically if you use it wrong could raise a type error even though I'm hinting up here with this annotation that you should pass in an INT again
860:10
Speaker A
python doesn't enforce that so if you pass in a float this might in fact raise this function a type error and so that might happen if n is not an INT and then lastly I might say for clarity sake for
860:23
Speaker A
other programmers this function returns a string of n meow one per line and the return type of that value R type is going to be now all of this syntax here as I've used it is not python per se this is a
860:39
Speaker A
convention known as restructured text which is a form of markdown like language that's used for documentation for websites for blogs and even more but it's one of the popular conventions within the world of python to document your own functions so this does not have
860:54
Speaker A
anything to do fundamentally with type hints type hints are a feature of python what I'm doing here is just adhering to a third party convention of putting in between a Python doc string from the start to the end a certain standard
861:11
Speaker A
format so that these third-party tools can analyze my code for me top to bottom left to right and ideally generate documentation for me it can generate a PDF a web page or something else so that I or my colleagues don't need to not
861:25
Speaker A
just only write code but also manually create documentation for our code we can keep everything together and use tools to generate the same for us any questions now on these dock strings which again are a Convention of documenting your own code often
861:43
Speaker A
following some standard syntax yeah so when you say like you would document it and put it in a PDF is the purpose of doing this to kind of like publish it and share your function so other users can use it absolutely in the past when
861:58
Speaker A
we have installed some thirdparty libraries for instance cow a few weeks back call that I showed you what functions it had but if you read the documentation you might actually see that uh it was documented for us by the
862:10
Speaker A
author of that program now I don't believe they were using this particular syntax but it was definitely useful for you and me to be able to read some web page or PDF telling us how to use the library rather than wasting time reading
862:22
Speaker A
through someone else's code and trying to infer what functions exist and how to use them it just tends to be much more developer friendly to have proper documentation for our own code or libraries as as well other questions
862:35
Speaker A
yeah um when with Doc strings when you when it's used to generate like a PDF or whatever does it does it include uh any of the code so if you're referencing in the in your in your comment uh if you're
862:46
Speaker A
referencing the code in the comment itself might not make sense without seeing the code does it does do these in include it short answer you can do that not in the convention I'm using here but there's actually a clever way to write
863:01
Speaker A
in your doc strings sample inputs to your functions and Sample outputs for your functions and if you use a different tool that we've not discussed that tool will run your code using those sample inputs it will check that your
863:15
Speaker A
outputs match your sample outputs and if not the program will yell at you saying you've got a bug somewhere so this is just another way where you can use doc strings to not only document but even catch errors in your code this has been
863:28
Speaker A
a lot and there's a bit more to go why don't we go ahead here and take a five minute break and we resume we'll take a look at yet another feature of python yet another library to write code faster
863:38
Speaker A
all right suppose we want to modify this meow program to actually take its input not from the input function and the blinking prompt but from the command line recall in our discussion of libraries that you could use something
863:48
Speaker A
like cy. RGV to get at commandline arguments that a human has provided when you're running your program so why don't we whip up a version of meow that uses commandline arguments instead of again input so I'm going to go ahead and
864:00
Speaker A
delete what we've done here thus far and let me propose that we import CIS as we've done in the past and let's do this how about if the user does not type any command line arguments then my program
864:12
Speaker A
will just meow once just so that it does something visually interesting otherwise let's also give the user an option to specify how many times I want the cat to meow so let's start simple let's first of all go ahead and do this if the
864:27
Speaker A
length of cy. argv equals equals 1 that is the user only typed the name of the program and nothing else after the uh in their command then let's go ahead and just print out one meow like this uh
864:42
Speaker A
else for now let's go ahead and print out something like this else go ahead and print out let's say usage for the program which will be usage of meow. py just so that the user knows that the program itself is called meow. py all
864:56
Speaker A
right now let me go down to my terminal window and start to type python of meow.
865:00
Speaker A
and at this point notice that the length of cy. argv should indeed be one why well python the name doesn't end up in cy. arv at all ever but meow. Pi the name of the file does and it's going to
865:13
Speaker A
go in cy. argv 0 but that's only one element so the length of this thing is one there's nothing more to the right so when I hit enter now we should see indeed one meow if I don't cooperate
865:24
Speaker A
suppose I do something like meow's three enter then I'm going to see a reminder that this is how you use the program and this is a common convention to literally print out the word usage a colon then the name of the program and maybe some
865:37
Speaker A
explanation of how to use it so I'm keeping it very simple but let's be a little fancier what if I really wanted the user to type in maybe not three but something more sophisticated and in fact when uh controlling programs from the
865:50
Speaker A
command line it's very common to provide what are often called switches or Flags whereby you pass in something like dashn which semantically means this number of times then off in a space and then something like the number three
866:05
Speaker A
this still allows me to do other things at the command line if I want but the fact that I've standardized on how I'm providing command line arguments to this program with dashn three is just a more reliable way now of my program knowing
866:19
Speaker A
what does the three mean it's a little less obvious if I just do meow. ppace 3 well what does the three mean at least with syntax like dn3 especially if you've read the documentation for this program ultimately oh dashn means number
866:32
Speaker A
of times got it it's a way of passing in two additional arguments but that have some relationship between them so how do I modify my program to understand- N3 well if I'm using CIS like this I could do this L if the length of cy. argv
866:50
Speaker A
equals this time three because notice there's one two three things at my prompt so cy. arv 0 1 and two three things total separated by spaces if equals 3 and let's be safe and cy. arv bracket 1 equals equals DN then let's go
867:12
Speaker A
ahead and do this let's go ahead and convert uh cy. arv of two to an integer and assign it to a variable for instance called n and then let's go ahead and do this for uh underscore in the range of n let's go
867:30
Speaker A
ahead and print out some of these meaps now there's still an opportunity maybe to consolidate my print lines with meow but for now I'm going to keep these ideas separate so I'm going to handle the default case with no arguments up
867:41
Speaker A
here as before and now more interestingly I'm going to do this to be clear I'm going to check if the user gave me three command line arguments the name of the program- n and a number if indeed the second thing they gave me in
867:55
Speaker A
cy. arv of1 equals equals uh dasn then I'm going to assume that the next thing CIS V of two is going to be an integer and I'll convert it to such and store it in this variable n and now just using a
868:09
Speaker A
loop I'm going to print out meow that many times all right so it's kind of a combination of our earlier focus on Loops our earlier focus on command line arguments just creating a program that allow me to claim is representative of
868:22
Speaker A
how a lot of command line programs work even though we've typically not used many like this but it's very common to configure a program one you're about to run it at the command line with something like these command line
868:32
Speaker A
arguments like dashn or Dash something else now I'm going to go ahead and hit enter and I think I should see indeed three meows by contrast if I do two at the end I should see two meows if I do
868:47
Speaker A
one I should see one meow and frankly if I just omit this all together I should see one meow as well because that was my default case earlier and now let me allow us to uh assume that this program
869:01
Speaker A
eventually gets more more complicated right let's imagine a world where I don't want to support just dasn maybe I want to support- a and-b and- c and d d and a whole lot of others or heck at that point I should maybe give them
869:14
Speaker A
words so maybe it's Das Dash number it's indeed a convention uh in Computing typically to use single dashes with a single letter like n but use double dashes if you're actually using a whole word like number so the command line
869:28
Speaker A
argument might be dhn or maybe it's Das Das number but you can imagine just how complicated the code gets if now you want to support dn- A- B- C and so forth you're going to have to be checking all
869:40
Speaker A
over the place and what if they come in a different order you're going to have to check is dashn first or is it second or is it third or is it fourth I mean this just becomes very painful very
869:50
Speaker A
quickly just to do something relatively simple like allow the user to pass command line arguments into your program well this is why as always there exist libraries and another library that comes with python that's probably worth knowing something about is this one here
870:05
Speaker A
called ARG parse in fact with a lot of the tools I myself or cs50's team writes in Python we very frequently use arars whenever they are more complicated than a lot of our class demos and a little more similar to this one where we want
870:19
Speaker A
to allow the user to pass in configuration options at the command line and by supporting things like dashn or- a or- b or- c arars is a library that per its documentation just handles all all of this parsing so to speak this
870:34
Speaker A
analysis of command line Arguments for you automatically so you can focus on writing the interesting parts of your program not the command line arguments part so how might we use this well let me go back to vs code here let me clear
870:46
Speaker A
my terminal window and let me propose that I rewrite this using not CIS but actually using ARG parse and I'm going to start a little simple and then build back up so let me throw all of this away
870:56
Speaker A
for now and instead import ARG parse uh ARG parse stands for argument parser to parse something means to read it uh kind of pick it apart to analyze it so this is indeed going to do just that for me
871:08
Speaker A
now let me go ahead and do this and for this Library it's helpful to know a little object-oriented programming like we all now do I'm going to create a variable called parser I could call it anything I want I'm going to set it
871:19
Speaker A
equal to the return value of ARG parse dot ARG you parser with a capital A and a capital P A Constructor for a class called argument parser that comes with python itself within in this Library here now I'm going to configure this
871:35
Speaker A
argument parser to know about the specific command line arguments that I myself want to support in my program so I'm going to do this parser do addore argument so that's apparently a method in the parser object I'm going to add an
871:50
Speaker A
argument of- N Easy enough now I'm going to go ahead and actually parse the command line arguments I'm going to do args or I could call the variable anything I want parser dop parse ARS and by default parse ARS is going to
872:04
Speaker A
automatically look at cis.org V for me I don't need to import CIS myself I can leave the argument parser uh its code to import CIS look at cy. argv and figure out where dashn or anything else actually is and what's nice now because
872:20
Speaker A
this line of code here results in the parser having parsed all of the command line arguments I now have this object in this variable called args inside of which are all of the values of those command line arguments no matter what
872:34
Speaker A
order they appeared in not such a big deal when I've only got one because it's only going to go in one place at the end but if I've got- n- A- B- C you could imagine them being in all different
872:44
Speaker A
orders they definitely don't have to be alphabetical the user should be able to type them in any order they want that's better for usability ARG parser is going to figure all of that out for me and all I have to do now is this if I want to
872:56
Speaker A
iterate over that many uh numbers of arguments and that many Ms rather I can do this 4core in the range of the int conversion of args do n so dot is the syntax we kept using to access things
873:11
Speaker A
like properties inside of an object and that's what args is it's an object returned by the parse ARS function form me I'm going to go ahead now and print out quote unquote meow this many times so it's not super simple like these are
873:25
Speaker A
three new lines of code I need to write and rather understand but it's already a little simpler and more compact and my if and my L if and my ores and my ANS and all of that Boolean logic it's
873:37
Speaker A
handling a lot of this for me so if I didn't make any mistakes let me run python now of meow. enter and I did make a mistake here I did make a mistake what's what's wrong here now what's
873:50
Speaker A
wrong well I definitely didn't run it the way I intend so dhn3 enter so it does work but if I don't cooperate this actually seems to be a worse version if I don't pass in dhn and a number it just errors with a
874:04
Speaker A
type error int must be a string none is what came back so there's clearly an error here but the library is more flexible I can actually provide some documentation on how to use this thing so how do I know how to use this well
874:17
Speaker A
typically it's conventional in Python and in a lot of programming environments to run a program with a special argument DH or Das dashel and almost always I will claim you'll then see some kind of usage information indeed that's what I'm
874:33
Speaker A
looking at now I just ran python of meow. space- I'll do it again let me clear my screen and this time do d-el in English enter and I see the same thing it's not very useful at the moment it
874:46
Speaker A
just shows me what the usage is up here and this is kind of interesting this is a standard syntax Inu Computing and we've kind of seen it in Python's documentation before this just means that the program's name is of course
874:57
Speaker A
meow. pie square brackets as almost always in documentation means it's optional so I don't have to type-h but I can I don't have to type-n and another value but I can and then down here is some explanation of these options and
875:14
Speaker A
more verbally showing me that I can also do Dash dasel and not just Dash but this is so generic this has nothing to do with my program this is not going to help my users when I actually release
875:24
Speaker A
this software for the world so let me go ahead and improve it let me add a description to my argument parser that the humans will see meow like a cat quote unquote is going to be the value of this named parameter called
875:36
Speaker A
description and let me also add a help parameter to my dashn argument that just explains what dashn means number of times to meow quote unquote I'm not going to change anything else but I am going to go back to my terminal window
875:50
Speaker A
and run python of meow uh I'm going to run python of meow. py-h or equivalently d-el and now notice that this is a little more user friendly if I scroll up we still see the same usage but there's
876:04
Speaker A
a quick sentence in English of explanation that this program meows like a cat and if I look at the options now oh that's what N means it's the number of times to meow and this capital n a middle variable if you will is just
876:18
Speaker A
indicating to me that I need to type a number by convention after the lowercase dasn so it would be nice though all that said if my program still didn't just break when I run it without any command line arguments right ideally my program
876:34
Speaker A
would handle this just like my manual version did when I used cy. Arvy myself so we just need to add a little more uh functionality to this library and if I read the documentation I'll see that add argument takes yet another named
876:48
Speaker A
argument if you want you can specify a default value for dashn for instance one and I'll do that there and you can further specify that it's got to be an INT and what this will additionally allow me to do is if I tell AR parser to
877:02
Speaker A
make sure that the value of dasn is an INT I don't need to do the conversion manually I can just trust down on line seven that when I access the property called n inside of my args object it's
877:14
Speaker A
going to be automatically an INT for me and again this is the value of a library let it do all of the work for you so you can get back to focusing on the interesting project at hand whatever
877:24
Speaker A
problem it is you're trying to solve like in this case granted not that interesting but meowing like a cat let me go ahead now and run python of meow.
877:33
Speaker A
and hit enter this time no arguments and now it meows why because I specified that if I don't as a user specify dashn it's going to have a default value of one apparently and I don't have to convert that value from a stir to an INT
877:49
Speaker A
because I told AR parser please just make this an INT for me any questions now on AR pars were really this principle of just Outsourcing the commodity stuff the stuff that everyone's program eventually needs to do so that you can focus on the
878:06
Speaker A
juicy part yourself what does ARS that end contain what does args do n contain it contains the integer that the human typed after a space after dashn good question other questions yeah did uh uh the the when you specify the type um for the
878:28
Speaker A
argument uh what happens if does that basically handle the ex C if if the user inputs a string in this case a really good question suppose that the human does not type a number and therefore not an INT well let's see what happen so
878:40
Speaker A
python of meow. dasn dog where dog is obviously not a number enter and voila we see an automatically generated error message little cryptic admittedly but I'm seeing a reminder of what the usage is and a minor explanation of what is
878:57
Speaker A
invalid about this and again this is what allows you this is what allows me to like focus on writing actual code we care about and just letting the library automate some of this stuff for us all right well allow me to propose now that
879:09
Speaker A
we take a look at one other feature of python that we've seen before but it turns out we can use it even more powerfully as our programs become more sophisticated and the problems we're trying to solve themselves become more
879:20
Speaker A
involved let me go ahead and re uh turn to vs code closing out meow. and creating a new file for instance called unpack. so code of unpack. py and let me just remind us like what we mean by
879:33
Speaker A
unpacking because this is actually a feature of python that we've seen before for instance suppose that I write a program that prompts the user for their name like David Space men wouldn't it be nice if we could C of sort of split the
879:44
Speaker A
user's name into two separate variables and when we've done this in the past we've done it in a few different ways but one of them involved unpacking a single value uh that comes back from that like a list or uh some other data
879:57
Speaker A
structure and putting it immediately into two variables so let's do this here let me go ahead and call uh the input function asking someone what's your name question mark then let me go ahead and just split a little naively on a single
880:11
Speaker A
space so I'm assuming that the only users at the moment are people like me David Space men no middle names no multiple names it's just one and two which itself could be buggy for other users but for now I'm keeping it simple
880:23
Speaker A
just to remind us that I can now unpack that return value with something like first underscore last equals the return value of input and now I can go ahead and do something like this like printing out with an F string hello comma and
880:36
Speaker A
then in curly braces first if I just want to greet myself or any other user as hello David without the last name and frankly if I'm not using the last name recall that a python convention is just to name it underscore to make clear that
880:49
Speaker A
you know you're not using that value but it does need to be there because you're unpacking two values at once so if I run this it won't be all that unfamiliar I'm just going to run now python of unpack.
880:59
Speaker A
I'll type in David maen which has a single space and there we have it hello comma David well it turns out that there's other ways to unpack values and there's other features that python offers especially when it comes to
881:13
Speaker A
defining and using functions and this is slightly more intermediate functionality if you will that's useful because you can start to write even more elegant and Powerful code once you get comfortable with syntax like this so let me go ahead
881:25
Speaker A
and propose that we not just play with Hello uh uh hello names anymore but instead do something maybe involving some coinage again so maybe not dollars and cents but maybe again as in the past some gallions and sickles and canuts
881:39
Speaker A
with among which there's a mathematical relationship as to how many of those in the Wizarding World equal each other and let me go ahead and do this let me Define a simple function called total that just tells me the total value of
881:51
Speaker A
someone's vault in grots The Wizarding Bank based on how many gallan sickles and canuts that they have which again are currencies from The Wizarding World as opposed to our actual human world so this total function might take a
882:03
Speaker A
variable like gallions and sickles and canuts like this and then it's going to return the formula which I admittedly had a look up myself and it turns out that the formula for converting gallions and sickles to Kuts would be this
882:17
Speaker A
gallions times 17 plus sickles then times all of that by 29 and then add in the individual canuts not sure in what detail this came up in the uh books or movies but here we have it the official
882:31
Speaker A
formula all right now let's go ahead and do this let me go ahead and call the total function with just some sample inputs suppose that someone like Harry has 100 gallions 50 sickles and 25 canuts let me go ahead and print that
882:44
Speaker A
out on the screen all right well if total returns an integer which I think this arithmetic expression will do let me go ahead and store uh rather pass the return value of total to print and then just for clarity let me write canuts at
882:57
Speaker A
the end so I know that the unit of measure here is indeed canuts in total all right now let me go ahead in my terminal window and run python of unpack. and hit enter and it turns out mathematically that if I got my math
883:11
Speaker A
correct 100 gallions plus 50 sickles plus uh 25 canuts equals in total 50775 canuts just avoiding having to use our own human currency here but I'm not doing anything along the lines of unpacking at least just yet let me
883:28
Speaker A
propose now that I do this just for the sake of discussion let me propose that I leave the total function as is but let me go ahead and just store all of my coins in a list so coins in order from
883:40
Speaker A
left to right 100 50 25 it just because for whatever purposes in this story I have all of my coinage in a a list in this order kind of a a purse or wallet of sorts well how can I pass this in
883:54
Speaker A
well I'm not going to hardcode the same values twice just for the sake of discussion how could I pass in the individual elements of a list to my total function well of course I could treat this list as I always do uh using
884:06
Speaker A
numeric indices by doing coins bracket zero coins bracket one coins bracket two so this is old school stuff with lists if I've got a list called coins and there's three elements the indices or indexes of those elements are zero 1 and
884:20
Speaker A
two respectively from left to right so all I'm doing here now is passing in the first element from that list as gallions the second element of that list as sickles and the third element of this list as my canuts and that lines up with
884:36
Speaker A
of course the signature of this function which as total expects that I've passed in those three things in that order left to right all right let me go ahead and run just to make sure I haven't broken anything unpack. piy and hit enter and
884:48
Speaker A
the math still checks out but this is getting a little verbose a little verbose and wouldn't it be nice if I could just pass the list of coins to this total function wouldn't it be nice if I could just say something like this
885:04
Speaker A
coins but let me pause and ask the group why would this not actually work as is it technically is passing in all three but why would I get some kind of error when I run this Eric uh because
885:20
Speaker A
you are passing a list to gallion yeah I'm passing a list to gallion and nothing for sickles and canuts and notice those don't have default values there's no equal signs on that first line of code code which means Python's
885:32
Speaker A
not going to know what value should be assumed there so it just seems like it's not going to work plus it's the wrong type as Eric notes it's a list and it's not an integer as it was before so let's
885:44
Speaker A
actually run this incorrect version python of unpacked High enter type error and that is probably what you might expect like I'm messing up with the types here and I I'm required to pass in two positional arguments sickles and
885:56
Speaker A
canuts that were not even passed so I've definitely aired here but it certainly seems fortunate if the only solution to this is to do what I previously did which is index into the first element index into the second element index into
886:08
Speaker A
the third like you can imagine with bigger fancier functions that take even more arguments this is going to get very verbose and honestly very vulnerable potentially to just mistakes typos on my part but here too is where you can do
886:21
Speaker A
what's known again as unpacking a value in Python right now a list is kind of packed with multiple values my current list has these three values one 100 50 and 255 respectively but they're all packed up in this one list wouldn't it
886:36
Speaker A
be nice if I could unpack that list just like I previously unpacked the return value of the stir classes split function into multiple things too and indeed I can do just that python actually allows me to pass in not coins but Star Coins
886:54
Speaker A
so if you use a single asterisk at the beginning of your variable that will unpack it and it will take one sequence in this case coins of size three and explode it if you will unpack it into three individual arguments no commas are
887:10
Speaker A
needed python just handles this for you but the effect of passing in Star Coins is to pass in the individual members of that list which in this case are going to be 100 50 and 25 respectively which is perfect because now it's going to
887:25
Speaker A
line up with gallions sickles canuts respectively so now when I run python of unpack. py we're back in business and the math checks out but I've kind of cleaned up my code by just introducing this new symbol which we've used of
887:39
Speaker A
course in other context for multiplication and the like but now it's also used for unpacking in this way questions on what we've just done it's a single operator but it's already quite powerful because it allows us to take a
887:54
Speaker A
data structure and unpack it and pass it in individually does that work for um uh tles sets dicks dictionaries as well tupples yes sets I don't know R Shin I don't know if order is preserved no oh is that no it does not
888:18
Speaker A
or you know you're checking order is not preserved so it wouldn't work with set does not work with set does not work with set sorry I'm verbally Googling here just to save us some keystrokes so it would work for um enumerations that
888:34
Speaker A
where order is indeed preserved and we'll see another example in a moment where it actually can be used in a different way for dictionaries which nowadays do preserve order other questions on unpacking in this way yes hi hello uh can you use unpacking to get
888:48
Speaker A
the value uh for example 10 + 50 + 25 uh instead of a for Loop and then result plus short answer no if you want the individual values you should be just indexing in this case into those specific locations um this is returning
889:06
Speaker A
multiple values the equivalent of a comma separated list so you would use the earlier approach if you cared about the individual locations how about one other question on unpacking what if uh we have declared we we declar some
889:20
Speaker A
default values and if you use this Aster coins will it over right or will it uh skip it good question if I heard you right what if for instance the list has four values like this here and you're
889:35
Speaker A
still unpacking it when it's only three that's expected well let's try it python of unpack. piy enter another type error this time it takes three positional arguments but four were given so the onus is on us as the programmer not to
889:49
Speaker A
do that in this case so potentially fragile but avoidable if I'm controlling the contents of this list in fact let me propose now that we take a look at another variant of this whereby we use not just position IAL uh arguments
890:03
Speaker A
whereby we trust that the first is gallions the second is sickles the third is canuts suppose that we actually passed in the names as we're allowed to do in Python and then technically we could pass them in in any order and
890:13
Speaker A
python would figure it out using named parameters instead well how might I do this well it's going to be a bit of a regression at first so let me get rid of this list here let me change this now to
890:23
Speaker A
just manually pass in the values I care about gallions I want to still equal 100 sickles I want to equal 50 and nuts I want to equal 25 so this is old school parameter pressing it's no longer positional I'm explicitly specifying the
890:39
Speaker A
names of these arguments but that's just going to work because that's exactly what the names of these parameters are in my total function as before let's make sure I nonetheless did not break anything let's run python of uh of
890:52
Speaker A
unpack. piy enter and there we have it still 50775 canuts well once you start giving things names and values names and values that probably should bring to mind one of our most versatile data structures in Python and even other languages that of
891:13
Speaker A
a dictionary remember that a dictionary is just a collection of key value pairs names and their respective values so this kind of opens up an opportunity what if I did this what if I actually had for some reason in my program on a
891:26
Speaker A
variable as before called coins but instead of making it a list of three values like before what if it's a proper dictionary so what if it's gallions quote unquote colon 100 for 100 of those sickles quote unquote and 50 of those
891:41
Speaker A
and Kuts quote unquote 25 of those each of those separated by uh colons and let me fix my square brackets to this time be curly braces which recall is the symbol we use for dictionaries or dict objects in Python so now I have a
891:57
Speaker A
dictionary called coins not a list it's a collection of keys and values three keys gallions sickles canuts and three values 100 50 25 respectively if I were to now pass these individual values into my total function I could do it as
892:15
Speaker A
always with my dictionary so I'm doing it old school now coins is the name of my dictionary I index into it not with numbers like with lists but with words so gallions strings like this uh coins quote unquote sickles in square brackets
892:30
Speaker A
there and then lastly coins square brackets quote unquote canuts so it's getting it's verbose again like this is not maybe the best road to go down but we'll backpedal in a moment this is just how if you happen to have all of your
892:42
Speaker A
coins stored in a dictionary you could pass the gallion sickles and canuts into your function respectively let's make sure I didn't break anything let's rerun python of unpack. py and we're still good now how could we get to a situation
892:56
Speaker A
like this well as always imagine this program is a little longer than this one here and somehow you're using a dictionary maybe just to keep track of someone's purse or wallet like how many coins of each type that they have and as
893:09
Speaker A
such it's perfectly reasonable to use a dictionary but then you want to print out the total and darn it if that total function does not expect a dictionary so you cannot just do something nice and simple like pass in coins for reasons we
893:22
Speaker A
saw earlier that would be a type error total expects three arguments three integers you can't just pass in a dictionary but if that's the data structure you're using to store the person's purse or wallet well it's kind of unfortunate that we have this clash
893:36
Speaker A
between these data types well here's what we can do we can't pass in coins because watch if I try doing that and run python of unpack. we're getting another type error missing two required positional arguments sickles and canuts
893:50
Speaker A
I have to pass in three things but wonderfully python allows you to unpack dictionaries as well for a dictionary you don't use a single as risk you use two and what this syntax has the effect of doing is passing in three values with
894:09
Speaker A
names it has the effect of passing in gallion equals 100 comma sickles equals 50 comma canuts equals 25 and so it has the similar effect to the list unpacking but that just passed in the values 100 50 25 separated by commas in effect when
894:29
Speaker A
unpacking a dictionary it passes in the keys and the values separated conceptually with equal signs just like our function expects so if I now run python of unpack. again we're still good but we've tightened our code up again
894:45
Speaker A
and now I'm giving myself yet another option I can either store a Wizard's purse or or uh wallets in their uh in a list as we did earlier or I can store it a little more vers uh with even more
894:57
Speaker A
specificity using a dictionary instead and so do be clear let me rewind star star coins is the same thing if I rewind a little bit to our first example of named arguments is equivalent to what I've highlighted here when you unpack a
895:14
Speaker A
dictionary it passes in all of the keys and all of the values much like this syntax here but let me tighten it up and go to where we left off questions now on unpacking can we have a in this
895:27
Speaker A
dictionary uh can we have instead of having a con name value pair can we have a variable number of you know name value pairs short answer yes you can have more than three key value pairs as I have here but
895:42
Speaker A
it's not going to work unpacking it if the total function is expecting only three so if I were to add something here like let me introduce pennies to The Wizarding World and suppose I have one penny for instance and now I run this
895:56
Speaker A
same code python of uh unpack. piy where back to a type error again whereby I got an unexpected keyword argument pennies because that is not expected by the total function we will see in just a moment wonderfully a solution though to
896:11
Speaker A
that but for now it does not work other questions on unpacking with dictionaries or lists in list in list values we gave the same number of arguments and we declared a default value in the function now if you use this as trick will it
896:27
Speaker A
overwrite that value or will it skip it skip that default value a good question if you if we did have default values up here for instance equals 0 equals 0 equals zero the upside of that recall from our discussion of arguments to
896:42
Speaker A
functions a while back is that now you don't have to pass in all of those values they will default to those zeros therefore you could pass in fewer than three values either using a list or a dictionary that's unpacked in this
896:55
Speaker A
scenario I deliberately did not do that because I wanted us to encounter this specific error in this case but you could absolutely go back and add those defaults so it turns out that this single asterisk or this double asterisk
897:09
Speaker A
is not only used in the context of unpacking that same syntax is actually used as a visual indicator in Python when a function itself might very well take a variable number of arguments that is to say a function can be vartic which
897:23
Speaker A
means that it doesn't necessarily have to take say three arguments specifically even if they do or don't have default values it can take maybe zero or one or two or three and it turns out the Syntax for implementing the same idea is quite
897:37
Speaker A
similar in spirit in fact let me go back to vs code here and let me propose that we start over with this code and get rid of our notion of gallions and sickles and canuts and do something just a
897:47
Speaker A
little more generic just so that we've seen the Syntax for this suppose that I Define a function as follows Define a function let's call it f and that function is not going to take a specific number of arguments but a variable and
898:01
Speaker A
so I'm going to go ahead and use this syntax here star args which indicates that this function is indeed very adic it takes some variable number of positional arguments positional in the sense that they go typically from left
898:13
Speaker A
to right but I don't know how many just yet I want to support suppose that I additionally want to support some number of keyword arguments that is named parameters that can be called optionally and individually by their own name well
898:26
Speaker A
the convention syntactically here would be to use two stars and then K W ARS I could call args or KW args anything else that I want but a convention you'll frequently see in Python's own documentation is that when you have
898:38
Speaker A
placeholders like this for some number of arguments and some number of keyword arguments um the world tends to use args and key uh KW args well inside of this function let's do something super simple just for now let me go ahead and print
898:52
Speaker A
out literally quote unquote positional just to indicate to myself while wrapping my mind around what's going on here what the positional argument arents are and let me quite simply print out those args this is not something you would typically do you don't typically
899:06
Speaker A
just take in these arguments and print them no matter how many there are I'm just doing this diagnostically for now to show you how the syntax works now let me go ahead at the bottom of my file and
899:15
Speaker A
I won't bother with a main function this time so we can focus only on this function f let me go ahead and just call F with three arguments I'll use the same arguments as before but I'm didn't bother giving them names just yet like
899:26
Speaker A
gallions and sickles and canuts and the like so what do I have a program that no matter what calls this function f but it first defines F at the top of the file is taking some number of positional
899:37
Speaker A
arguments some number of named arguments and for the moment I'm just printing out the positional ones let me go ahead and in my terminal window run python of unpack. piy and hit enter and you'll see that the positional arguments passed in
899:52
Speaker A
are apparently this a sequence 50 25 but notice this if I clear my terminal window there and pass something else like five a fourth argument previously if I try to change the number of arguments I'm passing in to my total
900:08
Speaker A
function which was only defined as taking three I would have gotten a type error some visual indication that no you can't pass in more or fewer arguments than is actually in the function's definition but now watch if I run python
900:21
Speaker A
of unpack. Pi this time passing in 15 25 and five a fourth argument all four of those went through just fine I can get rid of all of those but one for instance now rerun my program after clearing my
900:35
Speaker A
screen and now I'll see just one argument here and even though there's a comma and nothing after it this is actually the syntax when seeing a a tupple in effect whereby The Comma just indicates this is indeed a list but
900:47
Speaker A
there's only one element therein well let's get a little more curious too let me go ahead and Rewind here to where we started with just those three values and this time let me go ahead and print out my named argument so to speak which is
901:00
Speaker A
args but KW args again the positional args in this syntax come first the named arguments KW ARS come second uh that's uh what python prescribes so now let me go ahead and not pass in just these numbers let me go ahead and pass in
901:15
Speaker A
actually named arguments so let me do something now more specifically like gallions equals 100 and sickles equals 50 and canuts equals 25 I'm not going to bother doing any math with total I just want to poke around right now at this
901:29
Speaker A
functionality of having a variable number of arguments and what's neat now is if I run python of unpack. and hit enter no problem what KW args is is automatically a dictionary that contains all of the named arguments that were
901:46
Speaker A
passed to my function which is to say when designing your own functions if you want to support more than one argument maybe more than two or three or four maybe a variable number of arguments indeed you can support both a variable
901:59
Speaker A
number of positional arguments that are just value comma value comma value or any number of named arguments where you actually put the name of the parameter equals the value and then maybe a comma and some more of the same so now it
902:14
Speaker A
turns out we have seen this before uh in some of the functions we've used to date we didn't necessarily see it called args or necessarily see it called KW ARS but we have seen at least one example of
902:28
Speaker A
this in the wild recall our old friend print which we've been using now for weeks and when we first looked at the documentation for print way back when it looked a little something like this the first argument to print was objects and
902:41
Speaker A
I waved my hand at the time at the asteris that was at the start of that variable name but then we had sep for separator the default value of which was a space we had n the default value of
902:51
Speaker A
which was a new line and then some other named arguments that we waved our hands at then and I'll again do now but what you can now perhaps infer from our emphasis on these asterisks today the single stars or the double stars is that
903:05
Speaker A
you know what this is the convention in Python's documentation to indicate that print takes a variable number of arguments so if we were to look at the actual implementation of the print function implemented by Python's own authors it might very well look
903:21
Speaker A
something like this deaf print and then the first argument would be star objects thereby indicating that print takes a variable number of arguments the next one of which might be sep equals quote unquote either using double quotes or as
903:34
Speaker A
in the documentation single quotes too the next one of which might be end the default value of which is a new line and then some of those other named arguments that we've not looked at as well and then maybe inside of the print function
903:45
Speaker A
implemented by the authors of python maybe there's a for Loop like for object in objects that allows them to iterate over each of those variable number of objects and print each of them and this is why in programs past you and I have
903:59
Speaker A
been able to do just print open parenthesis close parenthesis with nothing inside or you and I have been able to print out something like Hello World a single string inside of those parentheses or you and I have been able
904:10
Speaker A
to do a single string hello and then another string quote unquote World thereby passing in two arguments or even more so we've long had this ability to use vartic AR uh functions whereby you can pass in a variable number of
904:24
Speaker A
arguments what you now have via this args and KW ARG syntax but again they do not need to be called that is the ability using that star or two stars to implement those kinds of functions yourself my own F function a moment ago
904:41
Speaker A
did not do anything all that interesting but it hints at how you could if in the future you have a use case for taking zero or one or more of either type of argument any questions now on these types of
904:55
Speaker A
arguments what will happen if you print quarks and the argument is like a list ah so what would happen if you print the argument like it's a list so I think we saw that if I roll back in
905:07
Speaker A
my history here to when I had that F function which I called f just to be very generic just so we could play around with the syntax this is what I had here so this is a um I passed in 100
905:21
Speaker A
comma 50 comma 25 that gets automatically stored in args and when I run it you can actually see that sequence of values by running python of unpack up high there is that sequence all in the form of one single variable
905:35
Speaker A
I'm printing it just for Diagnostic purposes this is not really a useful or pretty program but it hints at how we can access that whole sequence of values other questions on this approach here can we pass kws from one function to another
905:52
Speaker A
function absolutely you can pass either of those to another function which you might want to do if you want to wrap another function provide some additional functionality but still pass in all of the supported arguments to the underlying function as
906:06
Speaker A
well all right how about this next it turns out that a few other tools we can add to your toolkit relate to the types of programming models that python supports we started out quite some time ago focusing really on procedural
906:21
Speaker A
programming in Python whereby we wrote code top to bottom left to right defining some functions or if you will procedures along the way defining Vari and having side effects and assigning values as needed but we then eventually introduced or really revealed that
906:36
Speaker A
python is also very much object oriented and a lot of those variables a lot of those types that we were using all that time were in fact objects objects that were uh came from certain classes and those classes were templates of sorts
906:49
Speaker A
blueprints via which you could encapsulate both data and functionality therein well we also saw along the way some hints of a third Paradigm of programming that python also to some extent it support which is known as functional programming
907:02
Speaker A
whereby functions are ever more powerful in that they tend not to have side effects no printing or changing of State globally but rather they're completely self-contained and might take as inputs and return values and that's generally a paradigm we saw when we started sorting
907:18
Speaker A
things particularly with functions like our sort function or Lambda function when we passed in the function we wanted to use to sort a list way back when well it turns out python has other fun functionality that is reminiscent of
907:32
Speaker A
functional programming and indeed is a powerful way to solve problems a little more differently still let me propose this let me propose that I whip up a new program here in vs code by closing our unpack. and this time creating another
907:45
Speaker A
program called yell suppose the goal at hand is to implement some program that allows the user to pass in input and then it yells the response by forcing everything to uppercase my apologies to those with with headphones there I'll
907:57
Speaker A
I'll modulate so let me go ahead and run code of yell. pi and within yell. Pi let's go ahead and Implement a program that really does just that let's go ahead and Define a main function up here and let's assume for the moment that
908:10
Speaker A
this yell function already exists and yell something like this is cs-50 properly capitalized not in all caps now let's go ahead and implement this yell function with deaf yell it's going to take for now a single uh word or phrase
908:26
Speaker A
uh and let's go ahead and I'll call it phrase here and I'm going to go ahead and just print out the phrase. uper so phrase. upper is going to force the whole thing to uppercase and as usual down here if the name of this file
908:38
Speaker A
equals equals quote unquote uh main then let's go ahead as always and call Main so let's just run this but for the most part it should be fairly straightforward when I run python of yell. py this is cs50 is yelled on the screen all right
908:53
Speaker A
that's nice but it's not great that yell only expects a single uh expects a single phrase wouldn't it be nice like print if I could pass in one phrase or two or three or really multiple words more generally but as individual words
909:08
Speaker A
themselves so let me retool this a little bit and change yel to take in not a phrase but how about something like a list of words so that ultimately I can call Yell like this uh quote unquote this inside of a list quote unquote this
909:24
Speaker A
inside of a list and quote unquote cs50 inside of a list I'm not going to bother with typ pen answer annotations for now but I'll just assume that yel has been defined now is taking a list of words as
909:35
Speaker A
defined here but now I want to force them all to lowercase so I don't quite want to do something as simple as this like for word in words I could for instance print that given word and maybe end the line with nothing right now but
909:50
Speaker A
I think if I do this python of yell. no that's that's not right I haven't forced anything to uppercase so let's fix this well let's go ahead and do the following let me go ahead and accumulate the uppercase words as follows let me create
910:04
Speaker A
a variable called uppercase and initialize it to an empty list using square brackets or or more verbose list syntax and now let me go ahead and iterate over each of those words in Words and for each of them let's go into
910:18
Speaker A
our uppercase list append to it the current words uppercase version so this is a way of creating a new list called uppercase that is just appending appending appending to that list each of the current words in the loop but
910:34
Speaker A
uppercased instead and now just let me go ahead and print out the uppercase list this isn't quite right let's see what happens here python of yelpy okay it's not quite right because I don't think I want those quotes or
910:49
Speaker A
those square brackets what am I seeing I'm actually printing a list but but but here's where some of our unpacking syntax now can be useful I don't have to change my approach to this problem I can just unpack uppercase by adding a single
911:02
Speaker A
star and now let me go ahead and rerun python of yelpy and now it's actually just English there's no remnants of python syntax like the quotes and the commas and the square brackets I've now unpacked this is cs50 as three separate
911:17
Speaker A
arguments to print so already now this unpacking technique would seem to be useful well it's a little unfortunate that I now need to call Yell though with a list of values in this way this is just not the norm or at least it's not
911:32
Speaker A
nearly as user friendly as something like the print function where I can pass in zero or one or two or three or any number of arguments why are you making me for your yell function pass in only a
911:42
Speaker A
list well we can do better let's adopt some of the new conventions we've learned and let's go ahead and get rid of the list by removing the square brackets and let's just pass yel three arguments now I don't want to do
911:53
Speaker A
something like change the definition of words to take in like word one word two like that's not going to scale and it's not going to handle different number of words but we have a technique now we can say star args which will allow the yell
912:07
Speaker A
function to accept any number of arguments and just for specificity let's not call it generically arcs let's name it something a little more self-explanatory like star words this just means I have a variable number of words being passed in now I think I've
912:22
Speaker A
made a marginal Improvement let me run this again python of yell. py this is cs50 is in all caps but is just a little better right because now I can treat yel just like I've long treated print pass
912:35
Speaker A
in as many things as you want and print will deal with it now my yell function is just as powerful it would seem and better still it also forces everything to uppercase well it turns out python comes with this function called map
912:48
Speaker A
whose purpose in life is to allow you to map that is apply some function to every element of some sequence like a list so for instance if we want to force to Upper case each of the words this is
913:03
Speaker A
cs50 in the list of words that's been passed in well we essentially want to map the uppercase function to each of those values so using map in Python can I do just that let me go back here to vs
913:15
Speaker A
code and let me propose now that I reimplement this as follows I get rid of all three of these lines here getting rid of uh that Loop in particular let me still declare a variable called uppercase but let me set it equal to the
913:31
Speaker A
return value of this new function called map map takes two arguments here in this case the name of a function that I want to map onto a sequence of values well what function do I want to apply to
913:46
Speaker A
every word that's been passed in well it turns out thanks to my knowledge now of object-oriented programming I know that in the stir class there is a function called upper we've usually called it by using the name of a string variable Dot
914:00
Speaker A
Upper open paren close paren but if you read the documentation for the stir class you'll see that the function is described indeed as stir. uper I'm not using parentheses open and close at the end of stir. uper because I don't want
914:15
Speaker A
to call it now I want to pass this function to the map function so that map can somehow add those parentheses so to speak and call it on every one of these words and this is what map does quite
914:29
Speaker A
powerfully and is an instance indeed of functional programming whereby I'm passing to this map function another function not calling it I'm just passing it in by a reference of sorts and what map is going to do for me is iterate
914:43
Speaker A
over each of those words call stir. Upper on each of those words and return to me a brand new list containing all of those results together in one list it completely obviates the need for me to do this more manually using that list
914:59
Speaker A
I'm still going to print the whole thing using star uppercase so that if I get back a three a list of three uppercase words I'm going to unpack them and print them all out so let's run this again
915:10
Speaker A
python of yelpy enter and voila it's still working but the code now is even more tight uh even tighter than before so it turns out there's another way we can solve this problem in a way that's even more pythonic or at least quite
915:26
Speaker A
common and that's using a feature known as a list comprehension and it's a a big phrase if you will but it refers to the ability in Python for you to very easily construct a list on the fly without
915:38
Speaker A
using a loop without calling a pendant a pend but to do everything in one dare say elegant oneliner so how can I go about using this notion of a uh of a list comprehension well let me go ahead
915:51
Speaker A
and do this in yelpy in vscode here let me go ahead and change my Approach as follows instead of using map which is perfectly fine and correct in this way let me just show you this other way as
916:02
Speaker A
well a list comprehension is the opportunity to create a list like this using square brackets like this but inside of those square brackets to write a python expression that in effect is going to dynamically generate a brand new list for you using some logic you've
916:19
Speaker A
written and the approach I might take here is this if I want to store in this list the uppercase version of every word in that word list I can do this word.
916:32
Speaker A
uper for word inword now this is a mouthful but I dare say python programmers love this capability of being able to Define on the fly a list inside of which is any number of values that you would ordinarily at least as we've done it
916:50
Speaker A
construct with a loop and again calling a pend and a pend in a pend but that usually takes two three four or more lines this list comprehension that that I've highlighted here is now an alternative way to create the exact same
917:04
Speaker A
thing a list inside of which are a whole bunch of uppercased words which words for each word in the words list that was passed into yell is what ends up in this list questions on this syntax here it
917:20
Speaker A
definitely takes a little bit of getting used to because you've got like this value on the left this function call here you've got this Loop inside of the square bracket but if you become accustomed to reading the code in this way from left to right
917:33
Speaker A
this means give me the uppercase version of the word for each word in my words list questions here on list comprehensions uh can you do conditional so also like if else or uh combine if L if else indeed you can and let me come
917:51
Speaker A
back to that where we'll see an opportunity to do things conditionally but for now I'm just upper casing every word in the list a good question other questions yeah um is is this is this functional programming or u i mean this
918:04
Speaker A
particular thing where you saying words do upper for word in word not necessarily this is more of a feature of python I would say yeah map was uh one uh very specific incarnation of thereof our use of Lambda and passing it in as a
918:19
Speaker A
key attribute to the sort fun sorted function a while back was an example and we're about to see uh one other so we can even use these list comprehensions to filter values in or out of our resulting list so in fact in vs code
918:32
Speaker A
here let me close yel up high and close my terminal window and let me create a new program here whose purpose in life maybe is to take a same list of students as before with a shorter version thereof
918:43
Speaker A
and just filter out all of the students in Gryffindor so let me go ahead and create a file called gryffindors dopy I'm going to go ahead and copy paste from before really my list of students at least hermion Harry Ron and Draco
918:57
Speaker A
from the start here just so that I can focus on uh one student who happens not to be from Slytherin and what I'm going to do here now if I want to filter out only the Gryffindor students let me go
919:08
Speaker A
ahead and do this let me create another variable called gryffindors which is going to equal the following list and this is going to be a bit of a longer line so I'm going to proactively move my square brackets onto two separate lines
919:20
Speaker A
and I'm going to create now a list comprehension I want to do this I want this new list called gryffindors to contain every students's name for each student in the students list but but but if the students house equals equals
919:39
Speaker A
quote unquote Gryffindor so this is nearly identical in spirit to what I just did earlier to create a list comprehension out of each of the words passed to my yell function but here I'm doing so conditionally and so I'm
919:52
Speaker A
borrowing inspiration from our focus on Loops borrowing some inspiration from our focus on uh conditionals combining that into this same square bracket notation so that what gryffindors ultimately is is zero or more students names and the names that are included
920:09
Speaker A
are the result of iterating over each of those students and only including in the final result these students whose house happens to be Gryffindor so when I go ahead and run this with python of gryffindors dopy and hit enter you'll
920:24
Speaker A
see huh nothing actually happened here well that's because I didn't finish the program let me go and actually finish the program with this how about for each Gryffindor in Gryffindor plural and better yet so that it's sensible that I
920:37
Speaker A
did all of this work in advance let me go ahead and sort all of those names with our familiar sorted function let's go ahead now and print out each of these gryffindors so now notice if familiar with the books and the movies you'll
920:50
Speaker A
know that only three of these four students are actually in Gryffindor and if I run python of Gryffindor dopy there we see Harry Hermione and Ron but now in sorted order as well so that's just one way we can solve this same problem using
921:04
Speaker A
not just a list comprehension but a list comprehension that has this conditional therein but there's yet other ways to solve this same problem too and we come back to some functional features of python in addition to functions like Map
921:16
Speaker A
There's also this one called filter that can be used to achieve the same effect but with a more functional approach if you will let me go back to vs code here and with the same example let me do this
921:27
Speaker A
let me leave the original list up above as before including Draco who's not in fact from Gryffindor and let me temporarily Define a function called is Gryffindor that takes in as uh value something uh like a student s and then
921:42
Speaker A
let's do this let's go ahead and say if s quote unquote house equals equals Gryffindor then go ahead and return true otherwise go ahead and return false now we've seen before conditionals like this that are a bit unnecessarily
922:00
Speaker A
verbose I don't need to have a conditional if I'm already asking a Boolean question up here so I can actually tighten this up as we've done in the past and just return does the student's house equal equal Gryffindor
922:12
Speaker A
either it does and it's true or it doesn't and it's false I don't need to explicitly return true or false I can just return the value of that Boolean let's go ahead now and do this I'm going to create as before a variable called
922:24
Speaker A
gryffindors a list for all of my Gryffindor students that equals to this time the result of calling filter filter takes at least two arguments here one of which is the name of a function to call is Gryffindor and I'm going to apply
922:40
Speaker A
that function to each of the elements of this sequence here so similar in spirit to map I'm passing in a function that's going to be applied to each of the elements in the sequence but map returns one value for each element in the
922:54
Speaker A
sequence that's how we forced all of the words to uppercase but if I want to conditionally include a student in my resulting gryffindor's list I can use filter instead filter expects its first function to be not something like stir.
923:09
Speaker A
upper but a function that returns true or false tell me whether or not I should include or not include the current student from the final list and the question being asked is do they live in Gryffindor we're checking the
923:23
Speaker A
dictionary's house key for that answer and so ultimately I think we'll be left with something quite similar for Gryffindor in the sorted ver let's do for Gryffindor in gryffindors let's go ahead then and print out the current students Gryffindor name it's not going
923:40
Speaker A
to be sorted just yet but when I run this version here python of Gryffindor stpy and hit enter we're back in business it's unsorted but we have Hermione Harry and Ron but not Draco and if you recall from a few weeks back if
923:53
Speaker A
we want to sort even a list of dictionaries we can still do that too I can call sort on Gryffindor plural and I can pass in a key and that key can have a Anonymous function AKA a Lambda function that
924:07
Speaker A
takes in a student as input call it s and then Returns the value s quote unquote name if my goal is to sort by indeed uh students own names if I go ahead now and run python of griffindor
924:20
Speaker A
dopy I see the same list of students but this time it's sorted so here we've seen two approaches to this particular problem of Gryffindor students whereby we can either use something like a list comprehension and inside of that list
924:32
Speaker A
comprehension do a bit of filtration including an if conditional as I did or we can take a more functional approach by just using this filter function passing into it the function that I want to make these decisions for me and then
924:47
Speaker A
include only those for whom true is returned any questions on either of these two approaches uh yeah I just had a question that if we write the code like the previous version where everything is stuffed into one light
925:01
Speaker A
what the if we check for the style of the code then won't it have a don't it have a problem with it because it's less readable so would a formatter like black have a problem with the style of some of
925:14
Speaker A
this code the previous one where the everything was stupped into one line oh a good question would something like black have a problem with this code well let me rewind to that version which was using the somewhat longer uh list comprehension
925:29
Speaker A
which looked like if we go far enough back give me a few more undos which looked like this ultimately let me go ahead and run black on gryffindors dopy and you'll see that I actually it reformatted ever so slightly but I
925:43
Speaker A
proactively fixed this myself had I done this and done it on just one line but I knew that black might not like that it would have fixed it for me so I just proactively fixed it before writing the
925:54
Speaker A
code myself how about time for one other question on gryffindors high in this approach of using a list comprehension or filter yeah when when using filter instead of calling the function is Ginder can you use it ER right there
926:12
Speaker A
inside filter can you use the function is Gryffindor so you don't want to call it like this because you don't want to call it then you want filter to call the function for you if that's what you mean
926:23
Speaker A
so I pass it in only by its name instead no I me if you can write the return as house equals equals the inside F yes indeed in fact so recall that we indeed used these Lambda functions way back when when we
926:42
Speaker A
wanted to pass in a quick and dirty function anonymously to allow sorted to filter by a different key of a dictionary we can do that here I can actually take the essence of this is griffindor function I can change the
926:55
Speaker A
name of this function in my filter call to be another Lambda function passing in an argument like s and returning exactly that I can now delete my is Gryffindor function all together and now when I run python of gryffindors dopy I still get
927:11
Speaker A
the same answer and I've not bothered defining a function only to then use it in one and only one place well let me propose too that we equip you with one other tool for your toolkit namely dictionary comprehensions as well and
927:26
Speaker A
admittedly the syntax is starting to get even weirder but as you get more comfortable with all of these Primitives and others these are just tools that you can optionally but perhaps powerfully use to solve future problems down the
927:37
Speaker A
road and with a dictionary comprehension we have the ability to create on the fly a dictionary with keys and some values without having to do it sort of old school by com creating an empty dictionary and creating a for Loop and
927:50
Speaker A
iterating over that Loop and inserting more and more keys and values into the dictionary we can rather do it all at once so in fact let me go back to vs Cod here and let me propose now that I do
928:01
Speaker A
this let me go ahead and initially do it the oldfashioned way here as follows let me go ahead and simplify and get rid of the houses Al together so that we can focus for now just on a list of students
928:13
Speaker A
names I'm going to go ahead and run students uh I'm going to go ahead and write students equals quote unquote hermion quote unquote Harry and we'll keep it even shorter this time quote unquote Ron only those three students in
928:26
Speaker A
Gryffindor I'm going to now proactively as we've done in the past give myself an empty list so that I have something to accumulate some answers to this problem in and now I'm going to do something like this for student in students so I
928:38
Speaker A
can iterate over each of them let's go ahead and with the gryffindors list append to it the name of the students so quote unquote name and then student which is indeed their name from that list and now let's go ahead and just put
928:52
Speaker A
these students all in Gryffindor I know these three students are in Gryffindor so suppose that the problem at hand is that I want to build up a list of dictionaries that only contains the Gryffindor students so it's sort of a
929:03
Speaker A
step back from the previous version where I already had the names and the houses for now just assume that the problem is I have all of their names but I don't yet have the student dictionaries themselves so I'm
929:14
Speaker A
rebuilding that same structure that I previously took for granted now let's go ahead and just for the sake of discussion just print out these gryffindors so we can see what we've built if I run python of gryffindors dopy in my prompt I see a bit of a
929:28
Speaker A
cryptic syntax but again look for our little hints I've got a square bracket at the end and a square bracket at the beginning and that indicates as always this is a list I then have a whole bunch of curly braces with a whole bunch of
929:41
Speaker A
quoted keys they happen to be single quotes by convention when using print on a dictionary but that's just a visual indicator that that is my key and the first value thereof is Hermione second key is a house this value thereof is
929:55
Speaker A
Gryffindor then there's a comma which separates one dict object from the next and if we look past Harry and Gryffindor there's a third a second comma which separates Harry and Gryffindor from Ron and Gryffindor as well so in short here
930:07
Speaker A
is some code whereby I fairly manually built up with a for Loop and an otherwise initially empty list the same data structure as before minus Draco just for Gryffindor students but here's where again with dictionary comprehensions or really list
930:24
Speaker A
comprehensions first can we do this a little more succinctly Let Me Clear My terminal window let's get rid of this initially empty list and this for Loop that appends appends appends to it and let's just do this a gryffindors
930:38
Speaker A
variable will equal the following list comprehension inside of that list I want a dictionary structured with someone's name and their name someone's house and only for now Gryffindor and that's it but I want one of these objects here in these curly braces for each
931:00
Speaker A
student in students so here too inside of my list comprehension with my square brackets I want an object as indic I want a dictionary as indicated by the curly braces I want each of those dictionaries to have two keys name and
931:17
Speaker A
house respectively the values thereof are the student's name from earlier here and Gryffindor only which students do I want to create those objects from well for student in students so again on the left I have what I want in the final
931:32
Speaker A
list and on the right I have a loop and this time no conditional I want all of these students in Gryffindor as their house now let's print this again uh python of gryffindors dopy and hit enter and now we have the exact same output so
931:45
Speaker A
instead of three lines it's just one it's a little more uh cryptic to read at first glance but once familiar with list comprehensions and this sort of syntax is just another way of solving that same problem what if I want to change this
931:58
Speaker A
and simplify what if I don't want a list of dictionaries which I now have again per the square brackets I have a list of three objects here what if I just want one bigger dictionary inside of which is a key like Hermione colon
932:13
Speaker A
Gryffindor Harry colen Gryffindor Ron colen Gryffindor I don't need a list I don't need separate objects per student I just want instead one big dictionary where the keys are the students names and the values of their house and I'm
932:27
Speaker A
assuming for now no one's going to have the same first name in this world well I can do this let me get rid of this here and not create a list comprehension but again this thing known as a dictionary
932:39
Speaker A
comprehension and the visual indicator or difference here is that instead of being square brackets on the very outside this time it's going to be curly braces instead so inside of these curly braces what do I want every key to be I
932:53
Speaker A
want every key to be the student's name I want every value for now to be Gryffindor and I want to do this for each student in students and now things are getting really interesting and this is another manifestation of python in
933:07
Speaker A
some views being very readable from left to right absolutely takes practice and comfort but this is creating a variable called Gryffindor which is going to be a dictionary per these curly braces every key is going to be the name of some
933:21
Speaker A
student every value is going to be Gryffindor what names of what students well this dictionary comprehension will be be constructed from the list of students one at a time so when I print this now the syntax will look a little
933:35
Speaker A
different cuz it's not a list of dictionary objects it's just one bigger dictionary object itself but now printing gryffindors gives me Hermione col and Gryffindor Harry colen Gryffindor and Ron colen Gryffindor as well any questions now on what we've
933:52
Speaker A
called dictionary comprehensions as well [Music] any questions on here no well let's introduce one other function from Python's toolkit followed by one final feature and flourish and then you're off on your way well let's go ahead and think back to this recall
934:15
Speaker A
some time ago that we had just a simple list of students as we have here Hermione Harry and Ron and for instance way back when we wanted to print out for instance their ranking from 1 to 2 to
934:27
Speaker A
three unfortunately when you do something like this for student in students you can print out the student's name quite easily of course if I do python of gryffindors dopy I get Hermione Harry Ron in that same order but I don't see
934:41
Speaker A
any numerical rank I see no number one two or three so I could maybe do this with maybe uh a different type of for Loop instead of this why don't I try this so maybe I could do for I in the
934:54
Speaker A
range of the length of the student list and we've done something like this before and then I could print out I and I could print out the student's name by indexing into that list at location I well what does this look like if I run
935:08
Speaker A
python of gryffindors dopy it's close uh but you know these aren't programmers they don't necessarily think of themselves as zero index termy probably wants to be first not zero so how can we fix this well just a little bit of
935:20
Speaker A
arithmetic I could print out i+ one of course and then the student's name so if I clear my terminal window and run python of griffindor high once more now we have this enumeration 1 two three of each of these students but it turns out
935:34
Speaker A
that python actually has had all this time another built-in function that you might Now find useful that is namely enumerate and enumerate allows you to solve this kind of problem much more simply by iterating over some sequence but finding out not each value one at a
935:51
Speaker A
time but both the value one at a time and the index thereof it gives you back two answers at once so if I go back to VSS code here now and take this approach I don't need to do this this complicated
936:05
Speaker A
range and length and then I all over the place I can more succinctly do this I can say for I comma student in the enumerate return value passing in students so this gives me back an enumeration if you will and now I can go
936:21
Speaker A
about printing I + one as before and I can print out the student so I don't need to index into the list with bracket I notation I don't need to call range I don't need to call length again
936:31
Speaker A
enumerate takes a sequence of values like these students and it allows me to get back the current index 012 and the current value Hermione Harry Ron respectively so now just tighten things up further and indeed that's been our theme here can we solve the same
936:47
Speaker A
problems as we've been solving for weeks but tighten things up using just more of this tool kit allow us to equip you with one final tool for your toolkit namely this ability to to generate values in Python from functions this is not a problem
937:01
Speaker A
that we've necessarily encountered before but it turns out if you're writing a function that reads or generates lots of data your function your program your computer might very well run out of memory and your program might not be able to run any further but
937:15
Speaker A
it turns out there's a solution to this problem that's something you might have in your back pocket particularly if after this course you start crunching quite a few numbers and analyzing all the more data in fact let's go back to
937:25
Speaker A
vs code here and let's go ahead and create a program that's perhaps timely at this time of day particularly depending on your time zone you might be feeling all the more sleepy but here in the US it's quite common to be lulled to
937:36
Speaker A
sleep when you're struggling otherwise by counting sheep in your head and typically as depicted in cartoons you might see in your mind's eye one sheep jumping over a fence and then two and then three sheep and then four and then
937:47
Speaker A
eventually you presumably get so bored counting these sheep you actually do fall asleep so in vs code here let's create a program called sleep.i that allows me to print out out some number of sheep as though I'm counting them in
938:00
Speaker A
my mind's eye and Via this program let's do this let's prompt the user for a variable n setting it equal to the integer conversion of the return value of input asking the user what's n for how many sheep do they want to try
938:13
Speaker A
counting and then let's do a familiar for Loop here and we'll start counting from zero as always so we'll first have zero sheep then one sheep then two sheep and so on for I in the range of that
938:23
Speaker A
value n Go ahead and print out and I'll paste here an emoji representing a sheep time I so the first iteration I'll see Zero sheep the second iteration I'll see one and then two and then however many uh specified by n ultimately minus one
938:37
Speaker A
all right let's go down into my terminal window here and run python of sleep. and I should see indeed after typing in say three for my value of n zero sheep then one sheep then two sheep and so forth
938:47
Speaker A
and if I make my terminal window even bigger here we can of course do many more than this typing in for instance 10 and you'll see that we get more and more sheep as time passes presumably becoming all the more tedious to Envision in my
938:59
Speaker A
mind's eye so let's now go ahead and uh practice what we've been preaching when it comes to the design of this program and see if and when we actually run into a problem let me go ahead here now and
939:10
Speaker A
put all of this in a main function by defining main up here as always let me go ahead and indent all of this code here and then let me just do this conditionally as always if the name of
939:19
Speaker A
this file equals equals quote unquote main let's go ahead and call Main let's make sure I didn't break anything just yet even though functionally this should be nearly the same and if I type in three I still have zero then one then
939:32
Speaker A
two sheep on the screen but we've been in the habit of course of creating helper functions for ourselves that is factoring our code in a way that allows us to abstract away certain functionality like uh generating some number of sheep into separate functions
939:47
Speaker A
so that one they're indeed abstracted and we no longer have to think about how they're implemented and we can even reuse them in projects as in libraries but we've also been in the habit too of now testing those functions as with unit
939:58
Speaker A
tests so I probably shouldn't keep all of my logic anyway in Main and let's Factor some of this out wouldn't it be nice if I could for instance just call a sheep function uh as by uh taking this
940:11
Speaker A
line of code here and instead of just printing it here let's print out the return value of a new function called Sheep that tells the function how many sheep to print I in this case let's go down as always and create another
940:23
Speaker A
function here called Sheep the Sheep function now will take a parameter n that's specifies how many sheep do you want to return and so that we can test this as with a unit test though we won't do that here let me go ahead and not
940:35
Speaker A
print the number of sheep as via a side effect but let me go ahead and return one of those sheep times n so that the user gets back a whole string of sheep that's the appropriate number to print
940:47
Speaker A
so here too functionally I don't think we've changed anything too fundamentally python of sleep. typing three still gives us zero then one and then two sheep but now we at least have a framework for focusing on the implementation of this sheep function
941:04
Speaker A
but it's a little inelegant now that it's still up to the main function to do this iteration we've seen in the past way back in week zero wouldn't it be nice to define a function that actually handles the process of returning the
941:17
Speaker A
entire string that we want rather than just one row of sheep at a time well I think we can do this why don't I go ahead and change sheep as follows let me go ahead here and uh first create a
941:30
Speaker A
flock of sheep that's initially empty using an empty list then for I in uh the range of n let's go ahead and append that flock for instance one sheep times I so that I keep adding to this list
941:44
Speaker A
zero sheep then one sheep then two sheep then three and so forth and then ultimately I'm going to return the whole flock of sheep at once so this is going to return the equivalent of all of those strings of sheep so that eh Maine can
941:56
Speaker A
handle the print thereof so back up here in Maine let's do this how about for each sheep I'll call it s since sheep is both singular and plural for s in sheep of n which again returns to me a list of
942:09
Speaker A
all of the sheep the whole flock let's just print out each sheep S one at a time all right so so far so good here I think let me go ahead and run python of sleep. Pi and hit enter what's N3 and
942:22
Speaker A
that still seems to work just fine but let me get a little uh creative here and see not just three sheep on my screen but maybe 10 rows of sheep and that too seems to work fine let me get a little
942:35
Speaker A
more adventurous and type in maybe a 100 sheep and it's starting to look ugly to be fair but they're all printing out pretty fast let me go ahead and try again with maybe 1,000 sheep on the screen and they flew by pretty fast it's
942:48
Speaker A
still pretty messy but they're all there we could count them all up how about not just a th000 but 10,000 sheep well that too seems okay it's it's taking like 10 times as long and that's why you see
942:59
Speaker A
this flickering on the screen all of the sheep are still printing but but but it's a lot of data being printed if I hang in there a little longer hopefully we'll see all 10,000 sheep coming to pass this is here in the video where
943:18
Speaker A
will we will speed up time all a real online oh my God this is a lot of sheep there we go okay and now all of my sheep have been printed so it seems to be working just fine well let
943:31
Speaker A
me just be even more adventurous and okay let me try my luck let me try like uh how about 1 million sheep this time and hit enter huh something's no longer working while we wait for a spoiler here
943:50
Speaker A
does anyone have any intuition for why my program suddenly stopped printing sheep what is going going wrong in this version wherein I'm generating this really big flock of sheep we might have run out of memory or computation power
944:07
Speaker A
yeah so maybe we're actually pushing the limits of my Mac my PCS my cloud serers memory or CPU the brains of the computer's capabilities because it's just trying to generate massive massive massive lists of sheep 1 million of
944:23
Speaker A
those rows of sheep Each of which has a huge number of sheep and it seems that my computer here is honestly just really struggling and this is really unfortunate now because it would seem that even though this program clearly
944:35
Speaker A
works pretty well for a th sheep 10,000 sheep once you cross some threshold it just stops working alt together or it just takes way too long for the program to be useful anymore but this seems a little silly right because theoretically
944:51
Speaker A
I should absolutely be able to print all of these same sheep if I just printed one right away then print two right away then print three then four then five it seems that the essence of this problem if I go back to my code is that per my
945:05
Speaker A
best practices that I'm trying to practice what I'm preaching it seems that the fundamental problem is that I've modularized my code by creating this helper function called Sheep whose purpose in life is to do all of the generation of sheep and then return all
945:19
Speaker A
of them at once wouldn't it be better and I can actually hear my fan turning on now even just trying to generate these sheep wouldn't it be better then to just print the Sheep one 2 3 four at a time well we
945:32
Speaker A
could do that but that's really a a step backwards that rather contradicts all of the Lessons Learned of the past few weeks where generally not putting everything in main is a good thing generally having an additional function that you can then test separately with
945:45
Speaker A
unit test is a good thing do we really need to give up all of those best practices just to print out some sheep and and here fall asleep well it turns out there's a solution to this problem and namely in the form of these
945:59
Speaker A
generators in Python you can define a function as a generator whereby it can still generate a massive amount of data for your users but you can have it return just a little bit of that data at a time and you yourself can implement
946:14
Speaker A
the code in almost the same way but you don't have to worry about too much getting returned all at once these two like all features of python are documented in the official documentation therein but what you'll find ultimately
946:26
Speaker A
that it all boils down down to this keyword here yield up until now when we've been making functions we have been defining functions that return values if at all using the keyword return and indeed if we go back to our code here
946:42
Speaker A
that's exactly what I've been waiting for I've been waiting to return the whole flock at once unfortunately if you wait too long and here we have it my program was quote unquote killed that is to say my computer got so fed up with
946:55
Speaker A
how much memory and CPU it was trying to use it just said nope you're not going to run at all and that's unfortunate now my program no longer works for large numbers of sleeps sheeps which is not good if I'm really having trouble
947:08
Speaker A
falling asleep some night so how can I use yield to solve this problem instead well let me do this instead of building up this massive list of sheep in this big list called flock let's just do this instead let me go ahead and simplify
947:25
Speaker A
this whole function as follows where by I iterate for I in the range of N and then on each iteration in the past I might have been inclined to use return and return something like one sheep times I but this won't work here right
947:41
Speaker A
because if you want a million sheep and you start a for Loop saying for I in the range of a million you're going to return accidentally zero sheep right away and then this function is essentially useless you shouldn't return
947:53
Speaker A
a value in the middle of a loop like this because you're not going to get to any of these subsequent iterations of the loop it's going to iterate once and boom you return but thanks to this other keyword in Python called yield you can
948:06
Speaker A
tell python to effectively return just one value at a time from this Loop so if I go back to this version of my code here and I say not return but yield this is like saying return one value at a
948:22
Speaker A
time return one value at a time return one value at a time the four Loop will keep working and I will keep counting from zero to one to two all the way up toward 1 million but each time the
948:36
Speaker A
function is just going to hand you back a little piece of data it's going to generate so to speak just a little bit of that data not all of the data at once and that's good because my computer has
948:45
Speaker A
a decent amount of ram certainly enough to fit one row of sheep it just doesn't have enough memory to fit apparently 1 million rows of so many sheep so now if I go to my terminal window and run python of sleep. Pi and hit
948:59
Speaker A
enter what's in three would still work zero then one and then two let me go ahead and increase the size of this here and run python of sleep.i let's try 1 million as before and hit enter and now
949:13
Speaker A
I immediately see results I don't think we'll wait for all of these sheep to be printed because then we will literally all be asleep but what you'll notice happening now is the program is not hanging so to speak it's not waiting and
949:26
Speaker A
waiting and thinking thinking and trying to generate the entire flock at once it's just generating one row of sheep at a time and it's flickering on the screen because there's so many of them and that's all thanks to yield it's
949:37
Speaker A
generating a little bit of data at a time not all at once any questions now on this feature called generators any questions at all to add one more piece of terminology to the mix just so you've heard it this same
949:55
Speaker A
feature of uh this same feature here is returning what we'll technically Now call an iterator yield is returning an iterator that allows your own code your own for Loop in Maine to iterate over these generated values one at a time how
950:12
Speaker A
how does uh this yield uh actually works under under the hood I I mean is it is it using multi trading you can think of the implementation as being asynchronous in this sense whereby the function is uh returning a value immediately and then
950:32
Speaker A
subsequently giving you back another one as well underneath the hood what's really happening is the generator is just retaining state for you it does not going to run the entire loop from top to bottom and then return a value it's
950:44
Speaker A
going to do one iteration and yield a result and the python for you is going to suspend the function if you will but remember on what iteration it was so the next time you iterate over it as it's
950:56
Speaker A
going to happen again and again in this for Loop in main you get back another value again and again so yield returns indeed this thing called an iterator and that iterator can be stepped over as in a loop one element at a time but the
951:09
Speaker A
language python handles all of that for you so that you don't need to do all of the underlying uh Plumbing yourself how about time for one other question on these generators and iterators as our sheep continue to fly by so in every
951:24
Speaker A
iteration the program will return to the memory to the system so the program will not crash correct on each iteration it's only returning the one string of sheep that's appropriate for the current value of I it is not trying to return all
951:39
Speaker A
million rows of the same and therefore it uses really one millionth the amount of memory although that's a bit of an oversimplification all right as these sheep continue to fly across the screen let me now uh go ahead and interrupt
951:54
Speaker A
this as you might have had to in the past with infinite Loop in your own code even though this isn't infinite it's just really long contrl c will interrupt with your keyboard that program giving me back control of my computer well here
952:07
Speaker A
we are at the end of cs50's introduction to programming with python and if today in particular of all days felt like a real escalation real quickly realize that these are really these are just additional perhaps optional Tools in
952:21
Speaker A
your toolkit that you can add to all of the past Lessons Learned so that as you exit from this course and Tackle other courses or projects of your own you have all the more of a mental model and all
952:30
Speaker A
the more of a toolbox with which to solve those same problems if we think back now just a few weeks ago it was probably in our focus on functions and variables that you first started struggling but now in retrospect if you
952:42
Speaker A
look back at those problems and those same problem sets odds are those same problems would come all too easily to you now conditionals was the next step in the class wherein we gave you the ability to ask questions and get answers
952:53
Speaker A
and therefore do things conditionally in your code we came full circle today and you can can see that you can now use those same kinds of conditionals now to do fancier things with list comprehensions and D dictionary comprehensions and the like Loops of
953:05
Speaker A
course have been omnipresent now for weeks including today as we built up those same structures and of course something can go wrong and exceptions and exception handling was our mechanism for not only catching errors in code but also raising your own exception so that
953:18
Speaker A
if you're laying the foundation to write code for other people as in the form of libraries you can do that too libraries of course are things you can not only use but now write on your own be it a
953:27
Speaker A
small module or whole package of code that you want to share with others around the world and even better can you write tests for your own code for your libraries for others code as well so that ultimately you can be all the more
953:39
Speaker A
confident that not only your code is correct today but if you make a change to your code tomorrow you haven't broken anything at least according to your tests if they continue to pass file IO though meanwhile was a way of now
953:51
Speaker A
storing data not just in the computer's memory like all of these sheep but actually storing things persistently longer term to dis being in a CSV or something more like a binary file like an image with regular Expressions you
954:03
Speaker A
then had the ability to express patterns and actually validate data or extract data from information all the more of a useful technique nowadays when so much of the world is trying to analyze and process data at scale some of which
954:15
Speaker A
might uh in fact be uh quite messy uh from the get-go and then of course most recently object-oriented programming an opportunity to solve the same kinds of problems but with a slightly different perspective a way to encapsulate and to
954:28
Speaker A
represent real world entities this time in code and today of course Etc with so many other tools that you can add that didn't necessarily fall under any of those earlier umbrellas but are useful functions and data types and techniques
954:42
Speaker A
just to have again in your back pocket as yet other mechanisms for solving problems as well not just putting everyone to sleep but I thought another way to end might be a little more vocally to try writing one final program
954:55
Speaker A
together this one using a Library we've seen in the past as well as one other I've taken the liberty of installing a text to speech library on my computer here and I'm going to go ahead perhaps and open a new file here called uh uh
955:08
Speaker A
say dopy in vs code and I'm going to go ahead here and first import our own friend import cow and I'm going to import this new library here import Pi TT sx3 the python text to speech library and now perit documentation which I read
955:26
Speaker A
in Advance I'm going to go ahead and create a variable for myself here engine equals pyttsx3 init to initialize that library for text to speech I'm going to then ask the user well what do I want to hear spoken and I might do something
955:41
Speaker A
like this a variable called this equals the return value of input what's this shall be my simple question and I'm going to keep it this time as a string we've seen how to use C we can do c.ca
955:53
Speaker A
of this turns out this new library can allow me to use its own to say this as well but then ultimately I'm going to have to run the engine. run and wait just in case it's a long phrase or
956:04
Speaker A
sentence to be said but that's it in just eight lines of code not only am I apparently going to have a cow appear on the screen to close us out now but also some synthesized text ultimately then we
956:17
Speaker A
hope with this course that you not only learned python that you've not only learned programming but you've really learned how to solve problems and ultimately how to teach yourself new languages a funny enough I myself only learned python just a few years ago and
956:30
Speaker A
even though I certainly went through some formal documentation and resources online I mostly learned what I know now and even what I had to learn again for today by just asking lots of questions be it of Google or friends who are more
956:42
Speaker A
versed in this language than I and so having that instinct having that vocabulary very which to ask questions of others to search for answers to questions you absolutely now have enough of a foundation in Python and programming to go off and stand on your
956:55
Speaker A
own so you can certainly and you're welcome and encouraged to go on and take other courses in Python and programming specifically but better still as quickly as you can is to find some project that's personally of interest that uses
957:06
Speaker A
python or some other language because at least from my own experience I tend to learn best and I hope you might too by actually applying these skills not to problems in the classroom but really truly to problems in the real world
957:19
Speaker A
allow me with all that said to look at my full screen terminal window here run python of s.p crossing my fingers one final time in hopes that I've not made any mistakes or bugs and here we go python of sey prompting me what's this
957:35
Speaker A
how about we end on this note here this was cs50
Topics: Python programming CS50 Harvard coding debugging unit testing file I/O object-oriented programming beginner programming

Get More with the SozAI App

Transcribe recordings, audio files, and YouTube videos — with AI summaries, speaker detection, and unlimited transcriptions.

Or transcribe another YouTube video here →