Python Classes and Objects

In the last lesson you learned Introduction to OOP. There we talked about thinking in objects instead of loose variables and functions. Now we get to the part where you actually build one. So the big question is this. How do you create your own kind of thing in Python, like a Dog or a User or a BankAccount? That is what classes and objects are for.

πŸ€” Why Classes and Objects?

Say you are building an app that has many dogs in it. Each dog has a name. Each dog can bark. Without a way to group this, you end up with loose variables floating around. You get dog1_name, dog2_name, dog1_sound, and so on. It gets messy fast. And nothing ties a dog’s name to its bark.

A class fixes this. It lets you design one β€œshape” for a dog. Then you create as many dogs as you want from that one design. Each one carries its own name and knows how to bark.

πŸ—οΈ Blueprint vs Real Thing

Here is the idea in plain words.

  • A class is a blueprint. It describes what something looks like and what it can do. It is not a real thing yet.
  • An object is a real thing made from that blueprint. We also call an object an instance.

Think of a house. The architect draws one blueprint. From that single blueprint, the builder puts up many real houses on the street. Each house is real. You can live in it. And they were all made from the same drawing.

The blueprint is the class. Each real house is an object.

So you write the class once. Then you create many objects from it. Each object lives on its own.

πŸ› οΈ Defining a Class

You create a class with the class keyword. By habit, class names start with a capital letter, like Dog or User. Inside the class you put methods. A method is just a function that belongs to the class.

Here is the smallest useful Dog class. It has one method called bark.

class Dog:
def bark(self):
print("Woof!")

Let’s read it line by line.

  • class Dog: starts the blueprint and names it Dog.
  • def bark(self): defines a method, which is a function that lives inside the class.
  • print("Woof!") is what that method does when you call it.

Right now nothing happens. We have only drawn the blueprint. No real dog exists yet. To get a real dog, we have to make an object.

πŸ• Creating Objects from the Class

To create an object, you write the class name followed by parentheses, like calling a function. This gives you back one real object. We store it in a variable.

This creates one dog and makes it bark.

class Dog:
def bark(self):
print("Woof!")
my_dog = Dog()
my_dog.bark()

Running this prints:

Output

Woof!

Here is what each new line does.

  • my_dog = Dog() creates a real Dog object and stores it in my_dog. This is the instance.
  • my_dog.bark() calls the bark method on that object using a dot.

The dot is how you reach into an object and use what it can do. You read my_dog.bark() as β€œask my_dog to bark”.

The real value shows up when you make more than one. Each call to Dog() gives you a separate object.

This creates two dogs from the same blueprint.

class Dog:
def bark(self):
print("Woof!")
rex = Dog()
buddy = Dog()
rex.bark()
buddy.bark()

It prints:

Output

Woof!
Woof!

rex and buddy are two different objects. They came from the same Dog class. But they are separate things in memory. That is the whole point of a blueprint. You write it once and create many.

πŸ™‹ What Is self?

You probably noticed self sitting in def bark(self):. This confuses a lot of people, so let me say it plainly.

self is the object itself. When you call rex.bark(), Python quietly passes rex into the method as self. So inside the method, self means β€œthe exact object this was called on”.

You do not pass it yourself. Look closely. You write rex.bark() with empty parentheses, yet the method header says bark(self). Python fills in self for you, automatically.

self becomes useful when each object holds its own data. Here each dog has a name. And bark uses self to read that name.

class Dog:
def bark(self):
print(f"{self.name} says Woof!")
rex = Dog()
rex.name = "Rex"
buddy = Dog()
buddy.name = "Buddy"
rex.bark()
buddy.bark()

This prints:

Output

Rex says Woof!
Buddy says Woof!

See what happened there.

  • rex.name = "Rex" stores a name on the rex object.
  • buddy.name = "Buddy" stores a different name on the buddy object.
  • Inside bark, self.name reads the name of whichever object you called it on.

So when you run rex.bark(), self is rex, and self.name is "Rex". When you run buddy.bark(), self is buddy. Same method, different object, different result.

Tip

Setting names from outside like rex.name = "Rex" works, but it is not the clean way. In the next lesson you will learn the constructor, which gives each object its data the moment it is created.

πŸ“‹ Class vs Object at a Glance

This table lines up the two ideas side by side.

Class Object (Instance)
The blueprint A real thing made from it
Written once Created many times
class Dog: rex = Dog()
Describes what a dog can do Has its own name and barks on its own

⚠️ Common Mistakes

A few things tend to cause problems early on.

  • Forgetting the parentheses when creating an object. Dog is the blueprint. Dog() is a real object.
# ❌ Avoid: this points at the class itself, not an object
my_dog = Dog
# βœ… Good: the parentheses actually build an object
my_dog = Dog()
  • Leaving out self in a method. Every method that works on the object needs self as its first parameter.
# ❌ Avoid: no self, so the method cannot reach the object's data
class Dog:
def bark():
print("Woof!")
# βœ… Good: self is there, so bark can use the object
class Dog:
def bark(self):
print("Woof!")
  • Calling a method without the parentheses. rex.bark just refers to the method. rex.bark() actually runs it.

βœ… Best Practices

Keep these habits and your classes stay easy to read.

  • Name classes with a capital first letter: Dog, User, BankAccount. This is the common style and other developers expect it.
  • Give classes and methods clear, real-world names. bark and Dog tell the reader exactly what they are.
  • Always make self the first parameter of a method, even before you fully understand it. It needs to be there.
  • Keep one class focused on one kind of thing. A Dog class should describe a dog, not also handle the whole app.

🧩 What You’ve Learned

A quick recap of what you can now do.

  • βœ… A class is a blueprint, and an object (instance) is a real thing made from it.
  • βœ… You define a class with the class keyword and put methods inside it.
  • βœ… You create an object by calling the class name with parentheses, like Dog().
  • βœ… You call a method on an object with a dot, like rex.bark().
  • βœ… self is the object itself, and Python passes it in for you automatically.

Check Your Knowledge

Test what you learned. Pick an answer for each question, then click Check.

  1. 1

    What is the difference between a class and an object?

    Why: A class describes the shape; an object (instance) is an actual thing built from that class.

  2. 2

    How do you create an object from a class named Dog?

    Why: You call the class name with parentheses, so Dog() builds and returns a new object.

  3. 3

    What does self refer to inside a method?

    Why: self is the exact object the method runs on, and Python passes it in automatically.

  4. 4

    When you call rex.bark(), how does self get its value?

    Why: Writing rex.bark() tells Python to pass rex in as self for you, so the parentheses stay empty.

πŸš€ What’s Next?

You can make objects now, but setting each one’s data by hand quickly becomes tedious. Next you will learn how to give an object its data the moment it is born.

Constructors

Share & Connect