Objects can be one of the most difficult programming concepts to understand. Once it clicks, however, it really clicks. I recommend you read and pay close attention to the textbook, and utilize your resources until you understand objects and classes, as your upcoming evaluation will rely heavily on your understanding of these concepts.
Before you begin, please read the Python documentation 9.2. Python Scopes and Namespaces. This stuff messes a lot of people up during major labs!
Let’s get started.
Classes are like a blueprint. They describe the traits and actions of something. Let’s look at a real life example, using a car.
To generalize our example, we will define a car as a vehicle with four wheels and an engine. We know, however, that some cars are different. Some are different colours, or seat more passengers. Our class describes the object in general. For example:
The class definition of colour simply states:
The car has a colour.
And for our number of passengers:
The car seats some number of passengers.
Objects are created using the “class” blueprints. So, let’s say we want to build a blue car that seats 5 people. We can then fill in the blanks from our class design to create the object defined as having the colour blue, and room for 5 passengers. We’ll call this car something different than the class name. This is because we want it to be identifiable. We’ll call it MyCar.
To stick with the terms you’ll be required to know, here’s a formal definition of what we just described. Read it slowly and make sure you understand it!
“MyCar” is an object. This object is an instance of the class “Car”. The class defines two attributes, colour, and number of passengers. Both of which can be defined specifically for each instance of “Car”.
Here’s the basic Python syntax for defining a class:
# Simple class definition class ClassName: <statement 1> . . . <statement N>
There are a few different types of statements that we will use to create our class. I’m going to try to cover all the “types” of statements, but there are many different applications for these, which I will leave up to you.
In our car example, we decided that every car needs a colour. This colour can (though it does not have to be) be unique for each instance of “Car”. When we initialize an object with certain data, that is called an Attribute.
An Attribute is a piece of data that describes the object. Since our class definition just gives us a blueprint for the object, we need to define attributes to describe the specific instance of the class in a bit more detail.
Attributes are usually defined when we create the object. This is done using Python’s special initialization function
__init__. (TWO underscores before and after the word “init”)
The init function is called once when the object is first created and takes a few arguments. One is “self”, which always comes first, and we will discuss later. The other two are the parameters that we will be using to specify colour and the number of passengers that the car holds.
When we save attributes, we want to assign them to “self”. This is because of the way that Python handles objects. We can think of it as the actual object running the code. Therefore, when we give it a colour, it has to think:
“Hey, this is MY colour, I’ll save it for my self.
class Car: def __init__(self, colour, numOfPassengers): # This is my colour self.colour = colour # This is my numOfPassengers self.numOfPassengers = numOfPassengers
Accessors (Get Methods)
Once we’ve stored attributes, we will often need to get them back from the object. In the Vector example you’ve seen in lab, you need to be able to get the x and y coordinates to really make use of the class. Therefore, you will need to create a method that returns the values you’ll need to work with. We’ll apply this to our Car example, noting that we might need to check the colour of the car, or the number of passengers it seats.
class Car: def __init__(self, colour, numOfPassengers): # This is my colour self.colour = colour # This is my numOfPassengers self.numOfPassengers = numOfPassengers # GET methods def getColour(self): return self.colour def getNumOfPassengers(self): return self.numOfPassengers
Now how do we use these functions? The syntax for Objects and their methods is extremely important. Please make sure you understand this!
In general, the syntax for an object’s instance is:
This calls Method from Object’s Class description, and passes it the arguments if necessary.
self is always passed first, and this is done automatically. Do not pass it in, Python will handle that.
Depending on your object class, you will often need it to perform more actions. This can be done by defining additional functions in the same way as we did above. These functions can do anything! They’re just like normal functions, but must still take in
self in order to operate correctly. The syntax for all functions you will define in an object is:
class Object: def myFunction(self, arg1, arg2... argN): # Do something
self is determined when you call the function as follows:
myObject = Object() myObject.myFunction(arg1, arg2... argN) #[-self-][-method--][-arguments--------]
So if our function does anything to
self, it is actually performing this action on the instance
anObject. I’ve decided to go a bit more in depth about the
self concept. It continues below. All you need to know is how to define object functions, and how to call them properly using Python syntax.
The “Self” Concept
No, this isn’t philosophy class. The concept of
self in object oriented programming is possibly one of the most important concepts to understand. I’m going to do my best to describe it using a few methods and metaphors. Please let me know if it is unclear. Read this next part several times if you need to.
Self is a concept used in Python to describe the “current object”. When you call an object’s method:
You can think of it as instructing
myObject to perform the action
myMethod using the variables
argument2. When Python goes to look at the code for myMethod, it goes straight to the Class definition (the blueprint). If we didn’t pass
self, Python doesn’t know which object we’re talking about. When we use
self, the identity of myObject is passed, so when Python checks the code for myMethod, it can see myMethod is utilizing some attribute of
self, and in turn, is utilizing some attribute of
myObject. An example from the lab follows:
class Vector: def __init__(self, x, y): self.x= x self.y= y
Let’s start here.
Python passes in
self so that it is in our scope. Otherwise, we would get an error saying it isn’t defined. When we use the statement
self.x = x, we are saying “the value of x specific to this object is set equal to the parameter passed in”. This is basically a way of saving information inside our objects.
class Vector: def __init__(self, x, y): self.x= x self.y= y def getX(self): return self.x def getY(self): return self.y
Here, we add two functions to get our
y values. Python automatically passes the parameter
self based on how the function was called. For example:
# Returns the x value from vector 1 # In this case, self is the "vector1" object vector1.getX() # Returns the x value from vector 2 # self is the "vector2" object vector2.getX()
This helps Python determine which value of
x we’re returning. Remember that
self doesn’t come out of nowhere. It is determined outside the class when you’re actually working with the methods of an instance of that class.
If we just told Python to
getX(), there is no way for Python to know what we want. This will return an error, and this is exactly why we require the specific syntax for calling methods of objects:
Hopefully this clears things up. Your textbook’s chapter on this content is really well done, and I recommend reading it (I know it’s dry, but it’s worth it, I promise!) if you’re still struggling with this understanding. Next major lab will absolutely require you to understand these concepts, so make sure you know them!