When you start modeling “things” in code—a student, an order, a sensor reading—it helps to keep the data and the actions that touch that data in one place. That is exactly what a Python class gives you. The official tutorial describes it as bundling data together with the functions that know how to work on that data: attributes remember state, methods describe behavior. This page stays small on purpose: you will walk through one Student example, see how objects are created, meet __init__ and self, compare instance data with shared class data, peek at inheritance and __str__, and pick up a few pitfalls beginners hit—without turning the guide into a full object-oriented textbook.
Tested on: Python 3.13.3; kernel 6.14.0-37-generic.
What is a class in Python?
You can picture a class as a blueprint. The class block spells out what every instance will know (its attributes) and what it can do (its methods). When you call the class like a function, Python builds a fresh object wired to that blueprint. You already use classes every day—list, str, and dict are built-in types written the same way—so your own classes are just custom names for the ideas in your program.
Simple Python class example
Here is a complete little class you can run as-is. Read it slowly: everything later in the article expands on one of these lines.
class Student:
def __init__(self, name, grade):
self.name = name
self.grade = grade
def show_info(self):
return f"{self.name} is in grade {self.grade}"
student1 = Student("Amit", 8)
print(student1.show_info())Run it and you should see Amit is in grade 8. In plain language:
class Studentintroduces the blueprint.student1 = Student("Amit", 8)asks Python to build one student object and fill in the starting fields.__init__is the special setup routine that runs right after that object is born; it copies the arguments onto the instance.selfis how each method talks back to “this particular student” while the code runs.show_infois just a function living on the class, except it always receives the instance asself, so it can readself.nameandself.grade.
Create an object from a class
Every time you call Student(...), Python allocates another object. They might look similar in text, but they are not the same box in memory—compare them with is and you will see.
class Student:
def __init__(self, name, grade):
self.name = name
self.grade = grade
a = Student("Amit", 8)
b = Student("Priya", 9)
print(a is b) # False: two different objectsAdd attributes using __init__
__init__ is not a constructor in the C++ sense, but it is the hook you almost always use to attach starting data. Whatever you assign to self.something becomes an attribute other methods (or outside code) can read later. For parameters, defaults, validation, and inheritance ordering around __init__, see the Python constructor guide.
class Box:
def __init__(self, label, weight_kg):
self.label = label
self.weight_kg = weight_kg
b = Box("books", 12.5)
print(b.label, b.weight_kg)What is self in a Python class?
You will see self in nearly every instance method. It is only a name, but everyone agrees on it: it means “the object I should operate on right now.” When you write student1.show_info(), Python quietly passes student1 as the first argument, so inside show_info the name self refers to that same student. If you leave self out of the definition while still calling the method on an instance, Python raises a TypeError—because it still has that extra object to hand you.
class Counter:
def __init__(self):
self.count = 0
def bump(self):
self.count += 1
c = Counter()
c.bump()
print(c.count) # 1Add methods to a class
Methods are just functions nested inside the class body, with the small rule that the first parameter receives the instance. They can return values, update attributes, or call sister methods through self.
class Student:
def __init__(self, name, grade):
self.name = name
self.grade = grade
def passed(self, passing_grade: int = 5) -> bool:
return self.grade >= passing_grade
s = Student("Lee", 6)
print(s.passed())Instance attributes vs class attributes
Anything you stick on self belongs to one object. Names you assign directly on the class (above the methods) are shared by every instance until an object defines its own attribute with the same name.
class Student:
school = "Riverside" # class attribute (shared)
def __init__(self, name):
self.name = name # instance attribute (per object)
s1 = Student("Amit")
s2 = Student("Priya")
print(s1.school, s2.school)
Student.school = "Central"
print(s1.school, s2.school)Watch out for mutable class attributes (like a list defined on the class): every instance would see the same list unless you create a fresh list per instance inside __init__.
Create multiple objects from the same class
That is the payoff of the blueprint idea—you write the class once, then stamp out as many independent objects as you need.
class Student:
def __init__(self, name, grade):
self.name = name
self.grade = grade
students = [Student("Amit", 8), Student("Priya", 9), Student("Kim", 7)]
print([s.name for s in students])Modify object attributes
Unless you hide fields on purpose (not covered here), you can change attributes after construction. That is normal when state evolves—think of updating a score, a status flag, or a cached value.
class Student:
def __init__(self, name, grade):
self.name = name
self.grade = grade
s = Student("Amit", 8)
s.grade = 9
print(s.grade)Add a default value in a class
Optional fields work the same way as optional function arguments: give __init__ a default, and callers can skip that piece.
class Student:
def __init__(self, name, grade=0):
self.name = name
self.grade = grade
s = Student("Amit")
print(s.name, s.grade) # Amit 0Python class with inheritance
Sometimes one class is a specialized version of another. Put the parent name in parentheses, and use super().__init__(...) when you still want the parent’s setup logic to run before you add your own fields. The Python super() article walks through MRO and cooperative super() calls in more depth.
class Person:
def __init__(self, name):
self.name = name
class Student(Person):
def __init__(self, name, grade):
super().__init__(name)
self.grade = grade
s = Student("Amit", 8)
print(s.name, s.grade)Python class with __str__
Ever printed an object and seen something like <__main__.Student object at 0x...>? Defining __str__ lets you choose a readable sentence instead. It does not change behavior elsewhere—it only affects print, str(), and places that stringify objects for you.
class Student:
def __init__(self, name, grade):
self.name = name
self.grade = grade
def __str__(self):
return f"Student({self.name!r}, grade={self.grade})"
print(Student("Amit", 8))Common mistakes with Python classes
- Forgetting
selfin an instance method signature, then wondering why Python complains about too many arguments. - Calling a method meant for instances on the class itself without passing an instance—or mixing up
@classmethodand@staticmethodpatterns not shown here. - Putting a mutable value (like
items = []) on the class body and expecting each object to get its own list; everyone shares that single list until you rebuild it per instance in__init__. - Naming classes in all lowercase; PEP 8 suggests
CapWordsso readers instantly seeStudentas a type. - Letting one class grow until it handles unrelated concerns; if
__init__needs ten unrelated parameters, it may be time to split responsibilities.
Python class quick reference table
| Need | Syntax |
|---|---|
| Create class | class Student: |
| Create object | student1 = Student(...) |
| Constructor | def __init__(self, ...): |
| Instance attribute | self.name = name |
| Instance method | def show_info(self): |
| Class attribute | school = "ABC School" (in class body) |
| Inheritance | class Child(Parent): |
Readable print output |
def __str__(self): |
Summary
You have now seen the whole loop: define a class, stash data on self inside __init__, let methods read that data through self, optionally share values on the class itself, and use inheritance plus __str__ when the story grows. Each call to the class mints another object, and you are free to tweak attributes as the program runs. When you are ready to dig into how names bind more broadly, the Python type of variable guide pairs well with this page, and the official class tutorial remains the best next stop.
References
- Classes (Python tutorial)
- Data model: objects, values, types (Python language reference)

