All language subtitles for English (auto-generated)_en_0_Harvard CS50_s Introduction to Programming with Python – Full University Course(1080P_HD)

af Afrikaans
ak Akan
sq Albanian
am Amharic
ar Arabic
hy Armenian
az Azerbaijani
eu Basque
be Belarusian
bem Bemba
bn Bengali
bh Bihari
bs Bosnian
br Breton
bg Bulgarian
km Cambodian
ca Catalan
ceb Cebuano
chr Cherokee
ny Chichewa
zh-CN Chinese (Simplified)
zh-TW Chinese (Traditional)
co Corsican
hr Croatian
cs Czech
da Danish
nl Dutch
en English
eo Esperanto
et Estonian
ee Ewe
fo Faroese
tl Filipino
fi Finnish
fr French
fy Frisian
gaa Ga
gl Galician
ka Georgian
de German
el Greek
gn Guarani
gu Gujarati
ht Haitian Creole
ha Hausa
haw Hawaiian
iw Hebrew
hi Hindi
hmn Hmong
hu Hungarian
is Icelandic
ig Igbo
id Indonesian
ia Interlingua
ga Irish
it Italian
ja Japanese
jw Javanese
kn Kannada
kk Kazakh
rw Kinyarwanda
rn Kirundi
kg Kongo
ko Korean
kri Krio (Sierra Leone)
ku Kurdish
ckb Kurdish (Soranî)
ky Kyrgyz
lo Laothian
la Latin
lv Latvian
ln Lingala
lt Lithuanian
loz Lozi
lg Luganda
ach Luo
lb Luxembourgish
mk Macedonian
mg Malagasy
ms Malay
ml Malayalam
mt Maltese
mi Maori
mr Marathi
mfe Mauritian Creole
mo Moldavian
mn Mongolian
my Myanmar (Burmese)
sr-ME Montenegrin
ne Nepali
pcm Nigerian Pidgin
nso Northern Sotho
no Norwegian
nn Norwegian (Nynorsk)
oc Occitan
or Oriya
om Oromo
ps Pashto
fa Persian
pl Polish
pt-BR Portuguese (Brazil)
pt Portuguese (Portugal)
pa Punjabi
qu Quechua
ro Romanian
rm Romansh
nyn Runyakitara
ru Russian
sm Samoan
gd Scots Gaelic
sr Serbian
sh Serbo-Croatian
st Sesotho
tn Setswana
crs Seychellois Creole
sn Shona
sd Sindhi
si Sinhalese
sk Slovak
sl Slovenian
so Somali
es Spanish
es-419 Spanish (Latin American)
su Sundanese
sw Swahili
sv Swedish
tg Tajik
ta Tamil
tt Tatar
te Telugu
th Thai
ti Tigrinya
to Tonga
lua Tshiluba
tum Tumbuka
tr Turkish
tk Turkmen
tw Twi
ug Uighur
uk Ukrainian
ur Urdu
uz Uzbek
vi Vietnamese
cy Welsh
wo Wolof
xh Xhosa
yi Yiddish
yo Yoruba
zu Zulu

Original subtitles

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 Meen and it's

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

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 will'll be focus

on a topic in programming known as

functions and variables mechanisms via

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

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 and code to do

something again and again and again some

number of times we then transition to

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

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

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

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

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

and output the ability to not just store

information inside of a computer's

memory but rather save it persistently

to diss so to speak to files and folders

we'll then take a look at another

technique known as regular expressions

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

we'll then take a look ultimately at

objectoriented 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

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

all the more tools for your toolkit an

additional uh 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

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

after cs50 itself if you'd like to get

all the more versed with python each

week via the course's lectures will we

introduce you to any number of Concepts

that will then drill down more deeply

into in the form of problem sets each

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

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

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

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 VSS code

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

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

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

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

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

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

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

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

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

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

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

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

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

use a command and I'm going to move my

cursor back down to the bottom of the

screen here where previously I already

ran one command the command code which

has the effect of opening vs code in my

computer and then I passed in the name

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

it just is the symbol that's generally

used to indicate your prompt where the

command line interface wants you to put

those commands now the command I can run

here is going to be this I'm going to

run python of

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

to do indeed at the end of the day even

if you don't really know much about

computers you've probably heard that

computers only understand zeros and one

the so-called binary system well if

that's the case then something that says

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

advance there's a program as well as a

language called python so python is not

only a language in which we're going to

write code it's also a program Otherwise

Known As an interpreter that you install

for free on your own Mac or PC or some

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

right and translating it effectively

into those zeros and ones that the

computer can understand so let's do just

that let me go back to vs code here I

already typed out python of hello.py but

I didn't get hit enter and that's what's

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

that same command you will have written

your very first program in this case in

Python well now let's take a step back

and consider what is it that we actually

just did and what is it we're looking

here on the screen well first and

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

predetermined set of functions some very

basic actions or verbs that the computer

will already know how to do for you that

the language really will know how to do

for you and you the programmer the human

can use those functions at will to get

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

doesn't print some pre-ordained string

of text that is to say it prints

whatever it is you want it to print and

here too do we have another piece of

terminology in the world of programming

namely arguments an argument is an input

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

parentheses with the ability to take as

input some string of text be it in

English or any other human language that

is what you want this function

ultimately to print onto the screen and

what is it that the program's ultimately

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

screen and functions therefore can

indeed have these side effects one of

the things they can do as this verb or

action is to display on the screen as a

side effect something like those World

words that we wanted hello world

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

those mistakes of course are refer to a

term you might already know which is

that of a bug a bug is a mistake in a

program and they can take so many forms

and take comfort perhaps in knowing that

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

the weeks to come we're going to give

you a lot of tools both mental and

Technical via which you can solve those

problems but just don't get discouraged

if when writing your program for the

first time it doesn't even work that

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

forgot to include something like the

closing parenthesis at the end of this

line of code you know the code is almost

correct it's like 99% of the way there

but now that I've pointed it out it's

pretty obvious that it's missing that

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

going to be a big deal to the computer a

computer is going to take you literally

and if you don't finish your thought in

the the way the language expects it's

not going to necessarily run at all so

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

deleting the parenthesis I'm going to go

ahead and type python again of

hello.py and this time when I hit enter

I'm hoping I'm going to see hello world

but here we have an error on the screen

a so-called syntax error which refers to

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

close it unfortunately sometimes the

error messages we'll see in the coming

weeks are not going to be nearly that

userfriendly but there too again with

experience with practice will you get

better at debugging such programs let me

now make sure that I indeed fixed it

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

programs uh could I write code inside a

word or for example Microsoft Excel and

what's the barrier to doing that a

really good question and allow me to

very explicitly say to the entire

internet that you should not write code

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

facing underlining paragraphs and the

like we generally want something much

simpler than Microsoft Word or Google

Docs and so VSS code is an example of

just a more general purpose text editor

its purpose in life is to allow you the

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

that if we look at the documentation for

Python's print function we can actually

look up at this URL here docs.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

I can actually go ahead and do something

something like this uh name equals name.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

strings to an integer I think we're okay

so let me try this python of calculator.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

/ 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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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++

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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]

[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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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.

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

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

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

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

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

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

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

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

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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

three human names not the name of the

file itself let me try running this

again I'm going to run python of name.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

type in my name David after the name of

this program it should end up in cy.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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.

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

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

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

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

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

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

let me go ahead now and increase the

size of my terminal once more and go

ahead now and run python of itunes.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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.

py I can say from sayings and it's

inferred by python that I mean sayings.

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

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

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

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

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

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

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

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

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

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

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

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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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.

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

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

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

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

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

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

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

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

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.

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^

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

we want instead of writing four lines a

really good question absolutely right

now if I go back to test calculator.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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.

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

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

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

function passing in ARG now what is this

doing I proposing that eventually I want

to be able to run python of costumes.

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

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

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

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

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

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

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

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

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

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

thing recall that sis. argv contains not

just the words I typed after my

program's name but what else does cy.

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

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

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

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

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

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

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

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

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

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

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

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

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

[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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

address but now I'm at least beginning

to use this Library by using its own re.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

to speak things that you can think of as

constants that have meaning to re.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

then uh what do I want to print out well

I think I want to print out matches.

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

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

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.

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

Twitter URL prefix all right well let's

run this for real now python of twitter.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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.

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

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

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

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

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

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

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

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

[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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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-

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

vs code and let me do something like

this self. name equals name and self.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Gryffindor what if I made a mistake

though what if I ran python of student.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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.

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

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

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

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

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

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

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

defined in your class it's going to

print out that very ugly esoteric

Incarnation thereof where it says main.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

an official list of valid patronises or

petroni I'm instead going to go ahead

and just blindly assign it to self.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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.

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

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

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

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

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

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

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

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

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

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

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

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

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

attribute implemented as an instance

variable is still called underscore

house and tragically python of student.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

is a function called choice that if you

pass in a list of choices like self.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

value like zero now how can I do that

well I'm going to go ahead and do self.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

$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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

this particular cat to meow that default

number of three times I can just do cat.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

right now let me go down to my terminal

window and start to type python of meow.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

how about we end on this note

here this was cs50

Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.