What a class is and why you need one

A class in Python is a container that holds related data and the actions you can perform on that data. Instead of writing the same code over and over for similar things, you write it once in a class and reuse it. For example, if you are building a program that tracks books, you could create a Book class that stores the title, author, and page count for any book — then create as many individual books as you need without rewriting that structure each time.

Classes let you organize code in a way that mirrors how you think about the real world. A Dog class might have a name and a breed, and actions like bark() or sit(). Every dog you create from that class will have those same properties and actions, but with different values. This is much cleaner than storing dog names in one list, breeds in another list, and barking instructions scattered across your code.

The technical term for a single dog created from the Dog class is an instance or object. The class is the blueprint; the instance is the actual thing you use in your program.

Key Takeaways

  • A class starts with the word class, followed by a name you choose, a colon, and then the code indented underneath.
  • The __init__ method is a special function that runs automatically when you create a new instance and sets up its starting values.
  • Methods are functions that live inside a class and always receive self as their first parameter, which refers to the specific instance being used.
  • You create an instance by typing the class name followed by parentheses, like my_dog = Dog("Buddy", "Golden Retriever").
  • Access an instance's data or run its methods using a dot, like my_dog.name or my_dog.bark().

The basic structure of a class

Every class in Python follows the same basic shape. You start with the word class, then the name you want to give it (usually starting with a capital letter), then a colon. Everything indented underneath belongs to that class.

Here is the simplest possible class:

class Dog:     pass

The word pass is a placeholder that means "do nothing." This class does not do anything yet, but it is valid Python. You can create instances from it, though they will be empty.

A more useful class has an __init__ method (pronounced "dunder init"). This is a special method that Python runs automatically the moment you create a new instance. It is where you set up the starting values for that instance.

class Dog:     def __init__(self, name, breed):         self.name = name         self.breed = breed

The self parameter is required in every method inside a class. It refers to the specific instance you are working with. When you write self.name = name, you are saying "store the name that was passed in as an attribute of this instance." You do not type self when you create the instance — Python adds it automatically.

Adding methods to a class

A method is a function that lives inside a class. It works like a regular function, but it always has self as its first parameter. Methods let you define actions that an instance can perform.

class Dog:     def __init__(self, name, breed):         self.name = name         self.breed = breed     def bark(self):         print(self.name + " says woof!")

The bark method uses self.name to access the name stored in that specific instance. When you call the method, you do not pass self — Python handles that for you.

Methods can also take additional parameters beyond self. For example, a sit method might take a duration:

    def sit(self, duration):         print(self.name + " is sitting for " + str(duration) + " seconds")

When you call this method, you pass only the parameters after self: my_dog.sit(30). Python automatically passes the instance as self in the background.

Creating and using instances

Once you have written a class, you create an instance by typing the class name followed by parentheses. Any values you pass in the parentheses go to the __init__ method.

my_dog = Dog("Buddy", "Golden Retriever")

This line creates a new Dog instance, passes "Buddy" and "Golden Retriever" to __init__, and stores the result in the variable my_dog. Now my_dog is a real object with a name and a breed.

You access the data stored in an instance using a dot:

print(my_dog.name)    # prints "Buddy" print(my_dog.breed)    # prints "Golden Retriever"

You call methods the same way:

my_dog.bark()    # prints "Buddy says woof!" my_dog.sit(30)    # prints "Buddy is sitting for 30 seconds"

You can create as many instances as you need, and each one is separate. Changes to one instance do not affect the others.

my_dog = Dog("Buddy", "Golden Retriever") your_dog = Dog("Max", "Labrador") my_dog.bark()    # prints "Buddy says woof!" your_dog.bark()    # prints "Max says woof!"

A complete example from start to finish

Here is a full class definition for a Book that stores a title, author, and page count, plus a method to print a summary:

class Book:     def __init__(self, title, author, pages):         self.title = title         self.author = author         self.pages = pages     def summary(self):         print(self.title + " by " + self.author + " has " + str(self.pages) + " pages") book1 = Book("1984", "George Orwell", 328) book1.summary()    # prints "1984 by George Orwell has 328 pages"

Notice that every method has self as the first parameter, even though you never type it when calling the method. The indentation matters — everything inside the class must be indented, and everything inside a method must be indented further.

When you run book1.summary(), Python automatically passes book1 as self, so the method can access self.title, self.author, and self.pages for that specific book.

Common mistakes to avoid

The most common mistake is forgetting self as the first parameter in a method. Every method must have it, even if the method does not use it. Python will give you an error if you leave it out.

Another frequent error is forgetting to indent the code inside the class or inside a method. Python uses indentation to know what belongs where. If your code is not indented correctly, Python will not understand the structure of your class.

A third mistake is trying to access instance data without creating an instance first. You cannot write print(Dog.name) — you have to create a Dog instance first, like my_dog = Dog("Buddy", "Golden Retriever"), and then write print(my_dog.name).

Finally, remember that when you create an instance, you pass values to __init__, not to the class name itself. The parentheses after the class name are where those values go: Dog("Buddy", "Golden Retriever"), not Dog by itself.

Frequently Asked Questions

Do I have to use __init__?

No, but you almost always should. __init__ is where you set up the starting values for each instance. Without it, instances would have no data. You can write a class with just methods and no __init__, but that is rare and usually not useful.

What is the difference between a class and an instance?

A class is the blueprint or template. An instance is an actual object created from that blueprint. The Dog class is the design; my_dog and your_dog are two separate instances created from that design. Each instance has its own data, but they all follow the same structure.

Can I change an instance's data after I create it?

Yes. You can assign a new value to any attribute using a dot: my_dog.name = "Buddy Jr.". This changes the name stored in that specific instance without affecting any other instances or the class itself.

Can a method return a value instead of printing?

Yes. Instead of print(), use return. For example, def get_info(self): return self.name + " is a " + self.breed. Then you can store the result: info = my_dog.get_info(). This is often better than printing because it lets the rest of your program use the value.

What happens if I create two instances with the same values?

They are still separate objects. Changing one does not affect the other. dog1 = Dog("Buddy", "Golden") and dog2 = Dog("Buddy", "Golden") look the same but are two different instances in memory. Python treats them as completely separate.