Creating a Class
Class syntax
If you want to define a new type of object, that isn't a list, dictionary, or anything built-in, you can create your own. When you create a class you will need to provide python with the following information:
- A name for your class.
- What the data that each object stores should be.
- All the behavior we want the objects to be able to do. In other words, define methods for objects of your class.
To define a class in Python we follow this pattern:
class MyClass:
#<-> Note the indentation of all our code below
def __init__(self, param_1, param_2...):
self.data_1 = param_1
self.data_2 = param_2 * 7
self.data_3 = "some_default_value"
def method_1(self):
# We can define a behavior in this method
def method_2(self, param_1):
# We can define a different behavior in this method.
Let's break this down:
class
is a keyword that should be followed by the name of the class. Note that everything related to our class is indented under theclass MyClass:
statement__init__
is a special method, often called the constructor. This is the method that defines what we need to create a new object of our class We will dig a lot deeper into the__init__
method soon.self
is a keyword that you will see in all methods of our class. When you use theself
variable within a method, you get to access the data of the object the method was called upon. This is a very crucial concept we will cover more in examples below.
Let's build our first class.
Our first class
Let's say we are writing a program that draws points on the screen. To represent where to draw each point, we need to have the x coordinate and the y coordinate. The x coordinate will be the number of pixels from the left side of the screen, and the y coordinate will be the number of pixels from the bottom of the screen.
Ideally, if my_point
was a point object, I'd want it to know it's x and y coordinate. If I were to represent my_point
, it would be convenient if I could type print(my_point.x)
and see the x-coordinate of my point.
Let's do just that:
class Point:
def __init__(self, initial_x, initial_y):
self.x = initial_x
self.y = initial_y
With these few lines of code, it's now possible for us to define points:
Let's dig deeper into what is going on here: We call x and y the attributes of Point objects. These represent the data stored in each object and they can be accessed and manipulated directly. For example we can modify my_point's x coordinate:
my_point.x = 11
print(my_point.x) # prints 11
These attributes were defined and set up inside our Constructor, the __init__
method. The line self.x = initial_x
is telling python two different things:
- The object we are creating should have an attribute called
x
- The value of that attribute should be the parameter
initial_x
Similarly, we do the same for the y-coordinate of the point.
It is up to you what the attributes of your objects should be, and how you will initialize them. This is part of the fun of programming in this style: Figuring out what you need to solve the problem at hand.
You may be wondering, where is our constructor method called? It is not obvious at a first glance, but the constructor is used in this line:
my_point = Point(4, 7)
. Using the name of your class, followed by all the parameters defined in __init__
besides self
, is how you create an object of a custon class.
Check your understanding:
What do you think would happen if you were to execute this line of code:
Make a prediction about what will be printed, then test it out yourself.
Solution:
We will get an error! more specifically, an _AttributeError_, as the Point class does not have an attribute called _z_ defined in its constructor.Our first methods
The main thing we want to do with these points is move them around the screen, so let's build new behavior, new methods to achieve that.
class Point:
def __init__(self, initial_x, initial_y):
self.x = initial_x
self.y = initial_y
def move_right(self):
self.x += 1
def move_left(self):
self.x -= 1
def move_up(self):
self.y += 1
def move_down(self):
self.y -= 1
Now on top of storing data, our objects have behaviour. Here's what it would look like to use the Point
class now:
start.move_up()
calls the move_up
method defined in the class. It is like calling a function, it's just that this is a function attached to the object.
Understanding self
:
This section is not about self awareness, but about clarifying the use of the keyword self
Note that in our definition of the move_right
method, self
looks like a parameter, however we called the method as start.move_right()
without providing any parameters. Here self
refers to the object we called the method upon. When we execute start.move_right()
, self
is effectively start
. If we call my_point.move_right()
, self
is effectively my_point
.
That's why we don't need to provide the parameter between parentheses, python knows what object to use in place of self
by looking at the object before the '.'
How does it work in our Constructor though? Well there is no object yet, so inside our __init__
method, self
refers to the object we are busy creating
Slides: Point
class explanation
Click through the slides to see an explanation for each line of the Point class
What's next?
In the next section, we will go over some common bugs and errors you may encounter with your classes, before building another example class.