You create a Python class using the class keyword, and the process is the concrete act that turns the abstract idea of object-oriented programming into code you can run. Up to this point in the learning path, you have used classes every day without defining your own. Every string you have sliced, every list you have appended to, and every dictionary you have looped over is an object created from a class that someone at the Python project wrote. The step you are about to take is writing your own class for the first time, using the same class keyword and the same method syntax that the built-in types rely on. The syntax is small enough to learn in a single sitting, but the design decisions you make when writing a class, what to name it, what attributes it should hold, and what its initialization method should expect, shape how every other part of your program will interact with the objects that class produces.
A Python class definition begins with the class keyword, followed by the name you choose for the class, followed by a colon. By convention, class names in Python use PascalCase, sometimes called CapWords, where each word in the name starts with a capital letter and there are no underscores between words. The name BankAccount follows this convention; bank_account does not. Inside the class body, which is indented one level below the class line, you define methods that look exactly like functions except for two differences: every method must accept a special first parameter that refers to the object itself, and methods are called on objects using dot notation rather than as standalone function calls. The simplest possible class looks almost empty, and understanding why you would write one begins with a problem that a standalone function cannot solve cleanly.
If you have worked through the section on Python functions, you know that a function receives input through parameters and sends output through a return value. That model works perfectly when a function needs to process data and produce a result in a single step. But consider a program that tracks multiple bank accounts. Each account has an owner name and a balance, and you need to deposit and withdraw money from specific accounts without mixing them up. A procedural approach might store account data in parallel lists, one for names and one for balances, and write functions that take an index to identify which account to modify. That approach works for two accounts but becomes fragile when accounts are created dynamically, passed between functions, or stored in data structures. A class bundles the name and balance into a single object that can be passed around as one unit, and the methods that modify the balance travel with the object automatically.
The anatomy of a class definition
Every Python class, from the simplest beginner example to the most complex library class, follows the same structural pattern. The class keyword starts the definition, the class name identifies it, the colon marks the beginning of the class body, and everything indented underneath belongs to that class. Methods defined inside the class body are functions that operate on instances of the class, and the special first parameter of every method connects each method call to the specific object it should modify. Attributes are variables that belong to the class or to individual objects, and they are accessed through dot notation on the object itself.
Here is a complete class that represents a book in a library catalog. It stores a title and an author, and it provides a method that returns a formatted description string:
class Book:
def __init__(self, title, author):
self.title = title
self.author = author
def describe(self):
return f"{self.title} by {self.author}"The first method, written with the special name init, is what Python calls automatically when you create a new Book object. Its name is pronounced "dunder init," short for double underscore init, and it serves as the constructor: the function that builds and initializes a new instance. The parameter named self represents the object being created, and title and author are the values you want each Book to remember. Inside the method body, the assignment self.title = title stores the provided title string on the object so it persists for as long as the object exists. The second method, describe, takes only self as a parameter because it does not need any additional input beyond the object's own stored attributes. It builds a formatted string from the title and author attributes and returns it.
The describe method is an ordinary function in every respect except that it lives inside a class and receives the object reference automatically. You could write the same logic as a standalone function that accepts a book object as an explicit parameter, but placing it inside the class signals to anyone reading your code that describing a book is an operation that belongs to the Book concept itself. This organizational clarity is one of the main reasons developers choose to write classes even when a function would technically work. For a broader introduction to why classes matter in Python, the article on object-oriented programming explained covers the motivation and conceptual foundation in detail.
Understanding the constructor and the self parameter
The initialization method is the most important method in any Python class because it controls what information every object must have from the moment it is created. When you call the class name with arguments, as in Book("Dune", "Frank Herbert"), Python does several things in sequence. First, it allocates memory for a new Book object. Then it calls the initialization method on that new object, passing "Dune" as the title argument and "Frank Herbert" as the author argument. The self parameter inside the method refers to the newly allocated object, and the assignments inside the method body attach the provided values to that object. Finally, Python returns the fully initialized object, and you can assign it to a variable or use it directly.
The self parameter is not a Python keyword in the technical sense, which means you could name it anything you want. The following code would work exactly the same if you replaced every occurrence of self with a different name like this or instance:
class Book:
def __init__(this, title, author):
this.title = title
this.author = authorBut every Python developer, every code editor, every linter, and every style guide expects the name self, and deviating from that convention makes your code confusing to read without providing any benefit. Treat self as a mandatory convention even though the language does not enforce it.
When you define the initialization method, you decide which arguments are required to create an object and which ones are optional. A Book must have a title and an author, so both are required parameters with no default value. If you tried to call Book() with no arguments, Python would raise a TypeError telling you that two positional arguments are missing. You can make parameters optional by providing default values, just like with regular functions, and a later article on Python object initialization best practices covers patterns for optional attributes, validation inside the constructor, and alternative constructor designs.
Creating objects from your class
Once a class is defined, creating objects from it uses a syntax you have already seen hundreds of times in this learning path. Calling the class name as if it were a function, with parentheses and any required arguments, constructs a new object and returns it. This is the same pattern you use when you call list() to create a list or int() to convert a string to an integer. Your own classes work identically because Python's type system treats user-defined classes and built-in types uniformly.
Here is how you create two Book objects and call their describe methods:
book_one = Book("Dune", "Frank Herbert")
book_two = Book("Neuromancer", "William Gibson")
print(book_one.describe())
print(book_two.describe())The first line creates a Book object with the title "Dune" and the author "Frank Herbert" and stores it in the variable book_one. The second line creates a second Book object with different data and stores it in book_two. The two objects are completely independent: changing the title on one would not affect the other, and calling describe on each uses its own stored attributes. This independence is the defining feature of objects and the reason classes are useful: one definition produces as many independent instances as you need.
The output of this program confirms that each object maintains its own state. The first describe call prints "Dune by Frank Herbert" and the second prints "Neuromancer by William Gibson". If you later add a third Book or modify one of the existing ones, the others remain untouched because each object is a self-contained bundle of data.
Choosing good class and attribute names
Naming is one of the most underrated skills in programming, and it matters even more in object-oriented code because class names and attribute names become part of the vocabulary your entire program uses. A good class name is a singular noun that describes what one instance of the class represents. Book, Customer, Invoice, and Sensor are good class names because you can say "this variable holds a Book" and the sentence makes sense. BookManager, DataProcessor, and UtilityFunctions are weaker names because they describe actions or collections rather than individual things, and they often indicate that the class is trying to do too many unrelated jobs.
Attribute names should be short but descriptive and should read naturally after the object name and a dot. If you have an object called flight, then flight.departure_time reads like English, while flight.dt requires the reader to remember an abbreviation. Method names should use verbs or verb phrases because methods perform actions. Names like deposit, withdraw, describe, and calculate_total tell you what the method does. The Python community follows these conventions consistently, which means code written by different people in different companies still reads with a familiar rhythm.
The next article in this section, on creating and using Python objects, takes the Book class you defined here and explores how objects interact with the rest of your program: passing objects as arguments to functions, storing objects in collections, and building programs where objects collaborate rather than just holding data in isolation. Before moving on, try writing your own simple class that models something you find interesting. A class with two or three attributes and one method is enough to build the muscle memory for the class keyword, the initialization method, and the parameter that connects every method to its object.
Rune AI
Key Insights
- A Python class is defined with the class keyword followed by a name in PascalCase and a colon, with all methods indented inside the class body.
- The init method is Python's constructor, called automatically when a new object is created, and its job is to set initial attribute values.
- Every method inside a class must have self as its first parameter, which gives the method access to the specific object it was called on.
- You create an object by calling the class name as if it were a function, passing any arguments that init expects after the self parameter.
- The class body can also contain class attributes defined outside any method, which are shared across all instances of the class.
Frequently Asked Questions
What does the __init__ method do in a Python class?
Why does every method in a class need a self parameter?
Can I create a Python class without an __init__ method?
Conclusion
Creating a Python class is a small syntactic step from writing a function, but it opens up an entirely new way to organize your code. The class keyword, the init method, and the self parameter are the three building blocks you will use in every class you write, and mastering them now makes every subsequent OOP topic easier to understand and apply.
More in this topic
Python OOP Design Best Practices
Learn the best practices for designing Python classes, from the SOLID principles adapted for Python to practical guidelines for writing maintainable object-oriented code.
Object-Oriented Programming in Python Explained
Learn what object-oriented programming means in Python, why classes and objects matter, and how OOP helps you organize larger programs into manageable, reusable pieces.
Read and Write Large Files in Python
Learn how to read and write large files in Python without running out of memory, using chunked reading, line-by-line iteration, and buffered writes.