>> One of the great things about Python is its flexibility,
that you can really do any type of
development that you might want with Python.
So for example, you can do functional programming,
you can do procedural programming,
which we've really actually already seen quite a bit of,
but we can also do object-oriented programming.
Now sticking with the tradition of all the videos that we've done,
I'm not going to spend really any time talking
about the concepts of classes and objects and things like that.
But rather, I'm going to focus in on the syntax and
how you can implement this inside of your code.
That being said, at a real quick high level,
a class allows you to define a data structure that's
going to have some level of behavior and well, store data.
You create classes to give yourself
some nice reusable components to be able
to group data and operations together,
and really just make your life easier when it
comes to development in certain scenarios.
Now just to define a couple of real quick terms,
this is terminology that's always helped
me when I'm trying to understand classes,
maybe this will help you as well.
Now here we go. That a class is a noun,
that this is basically what it is that I'm trying to describe,
what it is that I'm talking about.
My properties or my fields are adjectives.
These are the different things that are true about the class.
Then last but not least are the methods,
and those are the verbs,
those are the actions,
those are the different things that
this is going to be able to do,
the different things that it's going to be able to perform for me.
Now to create a class in Python,
syntax looks a little bit like that.
So we say class,
as you might expect, and
then whatever name it is that we want to give it.
In Python convention is to use PascalCasing.
For those of you not familiar with PascalCasing,
let me to do, there we go.
Perfect, and make that a little bit bigger.
So this is PascalCasing where what we've got is a capital letter,
and then every word thereafter
is also going to have a capital letter.
So that's convention in Python.
So create your class and then you can
add whatever it is that you might want to that class.
Now what you're going to notice is we're
starting off with a constructor right here.
Now a constructor in a class is where
I'm going to be able to now create a new instance of this.
This is how I'm now going to start to set everything up.
I'm constructing it.
The syntax in Python to set up
a constructor is that two underscores,
init, and then two underscores afterwards.
Now what you're going to notice from here,
I'm now going to set this up like I would on normal function.
The only real difference between a constructor
and a normal function is when this is going to get called.
This is going to get called when we look to
create a brand new instance of presenter.
So just like a normal function in Python,
you're going to notice that the first parameter is self,
or this if you will in other programming languages.
That's going to give me access to
the current instance of the object.
After that, we then go ahead and set up
whatever additional parameters it is that we might want.
In my case with my presenter,
what I'm saying is,
is I want to be able to set the name.
So I've added that in as parameter.
Now you have to give me a name if you're going to
set this up as an instance of the object.
The next thing that I want you to notice is right here
where I say self.name.
So you're going to notice that I'm
using self and I'm just tagging on,
I'm just appending on name right there.
This is a little feature that's part of duck typing,
where what I want to be able to do is give it something else.
So I'm just giving it something else.
I'm just simply saying self dot.
So I'm actually defining how I
want this object to look on the fly.
This is actually now going to
become what would be commonly called the field.
Some people might call this a property,
but a property typically involves a little bit of code execution.
We'll see that in just a couple of moments here.
But now I have name that's available
on the instance of this presenter object.
I'm also going to highlight the fact that we can
add in any methods that we might want.
You're going to notice that I'm going to set up self,
and then I can now read all of my properties here.
So that's how we can go in and set up our class.
So we have our constructor.
We can add on any methods that we might want.
If we want to create a field,
then we just simply create it almost on the fly,
if you will, inside of the constructor.
When it comes time to use it,
you'll notice that we call the constructor much in
the same way that we would just call a function,
that there is no keyword new or anything like that,
it's simply presenter equals presenter, pass in the name.
You'll notice that name field,
we're able to update that on the fly.
So I'm able to just go ahead and say, name equals Christopher.
Then last but not least,
I'm able to then have it do this, say_hello.
If I ran this code,
it would then say "Hello, Christopher."
Now one of the things that we have to be
aware of when it comes to a field is the fact
that anybody is going to be able to access
that and anybody is going to be able to update that.
So what happens if we want to be able to exert
some level of control over how somebody is able to use our class?
Well, let's start this conversation by talking a little bit about
accessibility in Python when it comes to our classes.
At the end of it all, everything is public.
So if you add on a method,
you add on a field,
whatever it is, it's going to be public.
There is no protected,
there is no private,
anything like that inside of Python.
What there is, is a couple of conventions.
If you start something with a single underscore,
so let's say I said underscore name for example,
what that means is you should avoid using
that property or avoid using that method,
unless you know exactly what it is that you're doing.
So what I'm saying when I create a class and
I put in a field or a method with a single underscore,
is I'm saying yeah, I know that some people are going to use that,
I want to avoid changing it.
But there is no guaranteed to
the user that it's not going to change at a later time,
and what I'm trying to tell the user is, "Hey,
you probably don't want this,
unless you really know what's going on on
the internals of the class that I have created."
The double underscore means do not use.
This is about as close as you could get to say
protected or private inside of Python.
That the double underscore is going to indicate,
hey, don't use this.
When you go in and you use something like
the intellisense that's available inside a Visual Studio code,
what you're going to notice is that anything with
a double underscore will
automatically wind up down at the very bottom.
It's trying to hide that.
It's really just trying to say don't use that.
I would also say that if you're going to
be using something from a library,
and you see underscores or
double underscores, follow that convention.
Don't use those items unless you know
exactly what it is that you're doing and
you're willing to accept the risk
that whatever is there might change,
that it might break your code.
The other thing that we can do
to control a little bit better accessibility here,
that we can limit what it is that somebody is able
to do to our class is by setting up a property.
What a property is going to give to us is field style access,
but actually using methods behind the scenes.
So what you'll notice is I've now
updated my little presenter here.
My constructor looks basically the
exact same where I'm saying self.name.
But now I'm doing something very different.
Now, name is going to be set up as a property.
The way that you set up a property in
Python is by creating the getter side.
So if I said x equals presenter.name,
it's going to give me this value back.
Then I set the setter side,
which is where if I would say presenter.name equals some value.
So this right here, this little getter,
that would be called if somebody said x equals,
and let's say I had a presenter called presenter.name.
That's when that's going to execute.
So inside of here,
I can now return back whatever value it is that I might want.
In my case, it's hard-coded to be now underscore,
underscore name, trying to indicate to
the outside world, don't use this.
Now you can also, if you want,
calculate a value on the fly,
that's totally just fine.
So maybe I'm storing parts of a value,
and now I'm going to perform some function on it,
now I'm going to give that back to you, totally cool.
So it doesn't have to just be a field that you're returning here.
On the setter side,
this is going to be called if somebody said presenter.name equals,
and it'll say Christopher, just like that.
So now what will happen is,
is the value, this little Christopher right out here,
that will now become part of the name.
So this gives me an opportunity to run some validation.
So if I want to make sure maybe that it's not
an empty string or that it's not null or something like that,
I can go ahead and check that out there to go
ahead and throw an exception as needed.
If it all works, then I could go ahead and
set that value into the field.
To close all of this off,
we can see this in action by saying,
presenter equals presenter Chris, setting the name,
and then printing out that value.
Now what I want you to notice is the fact that my
presenter.name equals Christopher, me reading presenter.name.
To the outside world,
that looks just like a field.
But behind the scenes,
we're actually calling a function.
I think the best way to figure
all of this out is to actually see it. So let's go see it.