Welcome to Object Oriented Programming.
First things first, let's make a little mental note that
most things in Python are considered objects, even files.
We've actually seen this before when we have a string, and
we can, I did one too far there,
we have a string with a dot and then hit tab, and
we have all these different things that we can do with it.
And even as an example, we can do 'name = "Python"',
and let's do 'print(name)',
and then let's also 'print(type(name))',
and you can see that it's a class.
Anytime you see class, just think object.
So what Object Oriented Programming does, or OOP, is it lets
programmers create their own objects and have their own methods
and attributes.
So a lot like we have 'name.upper', we can create that.
We can create this '.upper', and it looks a lot like a function,
actually. And the reason for that is because behind the scenes,
it is a function.
It's just already pre associated with a particular object.
So moving forward, whenever you see a function inside of
a class, which we'll dive into shortly,
but whenever you see a function inside of a class, we call
that a method. So this is a method.
And this way of calling a function, it's just called a function.
Objects or classes can also have properties or attributes,
and that's really just saying that there is an internal type of variable.
Now, that variable itself could also be an object and likely will be.
But the idea is that whenever you have an object, and you
have some sort of internal variable, a property or an attribute,
and you have a method, that method can easily access that
internal variable.
You don't have to worry about scope or assigning a variable
or anything like that.
It's already inside of that class or inside of that object.
And so it's going to have instant access to it already.
So basically, what OOP does, is it allows you to create your
own methods, create your own internal variables, create a
class, and just like how we have string or int or tuple, it
allows us to create our own objects just like that.
And so basically, we can extend Python to do anything we wanted to do.
We don't just have to stick with just strings.
We can create a new type of object called a person, or a pet,
or a hobby, or anything really.
Now, why would we ever do this?
Well, because in Python, they already give us methods like
this, and that's because we are likely to use these on pretty
much any string.
It's a very common thing,
so they provide it for us.
We would essentially do the same thing.
So we could have, for example, a person.
Now, for the most part, people are born with two legs and
two arms and a head.
But people are also different.
We have different features, like different hair color, different
shoe size, things like that.
And Object Oriented Programming lets us create repeatable
and organized code without actually having to write the same
10 variables about a person over and over and over again.
And so sort of how we created a dictionary a long time ago
where we had 'person', 'name = "Kalob"', we would have
pre-defined things like arms,
I've got two arms, legs, two legs, head, one head, something like that.
And those are sort of actually terrible examples,
but I think you get the point here where I have a 'person',
and I could create another person with pretty much the exact
same attributes and then just change, like, the 'name'.
And so that's really just setting up a template so that you
can create multiple people.
You can create an army of people that all have, for instance,
a default of 2 arms, or 3 arms, or 8 arms, 5 legs, and 2 heads;
and you could copy that over and over and over again with
a single line of code.
You just have to set the rules for that template.
That's what Object Oriented Programming is.
So now a lot of people at this point in time, they think,
"Well, why would I ever want to use Object Oriented Programming
when I can just use variables and functions?"
And that is the key question here.
So functions are really nice for small pieces of code.
You know, typically, a function does just one thing.
It should actually only really do just one thing.
But functions by themselves aren't organized well enough
in code, and sometimes they need to be used together.
So essentially, what Object Oriented Programming does is
it allows us to group our functions and our variables together
so that we know that they're all supposed to work together.
And inside of our object, it sort of has its own version
of scope, is a way to think about that, at least.
And once you have an internal variable inside of one of your
objects, or one of your classes, you can access it from pretty
much any other method, or a function inside of your object.
So again, we're really just grouping things together here.
So if my 'person' dictionary here also had a function, and it
needed to be 'say_hello', or this needs to be basically some
sort of function that basically just says, 'print("Hello")',
and this gets a little bit harder with a dictionary.
With Object Oriented Programming, we can do that.
We can say, 'person.say_hello', just like 'name.upper',
and it will print out "Hello" for us, or anything else we wanted
to. So let's go ahead, and I'm going to stop talking about
the theory, and let's actually look at some of the syntax
here. So to create a new object in Python, we use the keyword
'class', and then we just give it a name.
Now, typically, in Python, variables have lowercase letters
and use underscores to separate them.
So a variable name like 'my_name = "Kalob"', lowercase,
lowercase, underscore, lowercase, lowercase, lowercase.
In an object, we tend to use a different naming convention.
Now you don't have to follow this rule, but it is a good
practice to follow this rule.
So it starts with the keyword 'class', and it just has upper case
or camel case
rather, camel case naming, like this, 'MyClassName', and then
':', and then inside of here we have functions, and these look exactly
like regular functions.
So 'def say_hello(): print("Hello")'.
Now the only difference here is because this is in a class,
every single method that you write takes 'self' as its first
parameter every single time.
So let's go ahead and execute this,
and let's, I don't know, call this 'person', I guess,
and instantiate this with 'MyClassName()'.
[no audio]
And now we can do 'type(person)', and we're going to see that
this is 'MyClassName' type.
And if I do 'person.', and then hit, 'Enter', or not 'Enter',
if I hit 'Tab', it automatically fills with the only option
that there is, which says, 'say_hello', and I can just run
this with parentheses.
Now you don't need to specify 'self' in here.
You don't need to say this. That's already in there, and Python
will ignore it by default.
It's basically just passing in the rest of the class data
into here, so we have access to it.
We'll dive into that in just a second.
But now I can say, 'person.say_hello'.
And this looks a lot like the same syntax as 'name.upper',
'name.upper', 'person.say_hello'.
Now a class can also take default parameters in here.
And this takes a function, a magic function called
'__init__()'. Because it's a function
inside of a class, or in this case, it's actually called a method,
it's going to take 'self' all the time,
we never pass in 'self',
Python does that for us.
Then we could say the default 'name' is going to be "Person",
and the default 'hobby' is going to be "Coding".
And this again is pretty much the exact same as a regular
function. Now at this point in time, we can say, 'print(name)',
'print(hobby)'. And let's run that.
And let's add this in here.
We'll just run that once more.
Now, because this was initially instantiated like this, the
default 'name' was "Person",
default 'hobby' was "Coding",
it said, "Person", and "Coding", but we could actually change this.
We could say the 'name = "Henry", and his default
'hobby = "Being adorbs"'.
He's super adorable.
And we can see that that changes in here.
That's not going to change.
But now, because we have this little variable in here, we
might actually want to access that.
So ideally we would just say 'person.name', just like a
regular attribute on a string, for instance.
But this isn't necessarily going to work yet.
And the reason for that is because, "AttributeError:
'MyClassName' object has no attribute 'name'."
So this attribute here, even though we set it when we initially
created this object, it says it doesn't exist, and that's
because of scoping.
That's why we learned about scoping.
'name' is a scoped variable, only exists in here, does not exist
anywhere else, cannot exist anywhere else.
Not yet anyways.
So what we can say is 'self.name = name',
'self.hobby = hobby'.
And now you notice how we are using 'self' here.
What we're saying is, 'MyClassName
.name =', whatever this is going to be.
So by default, it will be "Person",
but we're saying it's going to be "Henry". And we can create
a new function in here.
'def get_name(self)',
and that 'self' is really just it's attaching itself to the rest of this class.
So without it, it doesn't know about 'self'.
It doesn't know about 'self.name', or 'self.hobby'.
But we can say 'print(self.name)' now.
And as a better example, let's go ahead and run this with
'name'. Let's comment this out as if that never happened.
'name' is set as "Person".
It's printed out immediately.
And when we run 'get_name', do we actually get that 'name'?
We're going to see that this is a scoping issue here.
So let's go ahead and save this.
We'll rerun that, rerun that, that,
and in here we could say 'person.get_name', is what I called
it, right? 'get_name'.
[no audio]
Oh, and it's Python.
Now, the reason I did that, very interesting,
I probably should have used a different variable name.
But scoping again. Scoping, looked for a 'name' in here, didn't exist,
looked for a name in the object, doesn't exist,
looks for a name in the global scope, which is up here,
and that was "Python".
So let's go ahead and 'del name' from our script here.
So we're just going to delete that variable entirely,
rerun these.
[no audio]
and now we get a "NameError:", it says "'name' is not defined".
It says the variable does not exist.
And that's because in here it technically doesn't.
What we are looking for is 'self.name'.
Now that doesn't exist because we haven't set it yet.
'self' is a special keyword that refers to the object itself.
So whatever this object is called, that's what 'self' refers
to. Just like, "My name is Kalob", when I refer to 'myself', 'myself'
is "Kalob", in this case, 'self' is 'MyClassName'.
We'll, uncomment that one as well.
And let's rerun these.
And now we're going to see that 'self = 'name', and
we can access that because 'self' is always passed in automatically
in an object. 'print(self.name)' is going to be "Henry".
[no audio]
So let's rerun all these.
'get_name'. There it is.
"Henry". So that is a crash course into Object Oriented Programming.
There's a lot of different things we can do with this.
But really, all we did was we bundled a couple of functions
together, 'say_hello', and 'get_name',
and we made a couple variables accessible only inside of this class.
We can also do 'person.name' now, and we can see that it's
"Henry". 'person.hobby' is also "Being adorbs".
[no audio]
And so by grouping all of this together, we're getting the
power of a dictionary,
but we're also getting the power of functions, and scope is
actually going to start working in our favor now.
So this was a crash course into Object Oriented Programming.
By no means do you need to understand all of us.
We are going to go through a lot more examples of Object
Oriented Programming in the coming videos.
[no audio]