How to Create an Object in Python

What you’ll build or solve

You’ll create objects in Python using classes, constructors, and methods.

When this approach works best

Creating an object works best when you:

  • Group related data and behavior together, like a User with email and display_name().
  • Track state that changes over time, like a Timer that can start, stop, and report elapsed time.
  • Create many similar things, like Product objects built from rows in a file or API response.

Avoid this approach when a simple dictionary is enough and you do not need behavior. For a small one-off structure, a dict can stay clearer.

Prerequisites

  • Python installed
  • You know what a function is
  • You know what a dictionary is

Step-by-step instructions

1) Define a class and instantiate it

Define a class, then call it like a function to create an instance.

class User:
    pass

u1 = User()
u2 = User()

print(type(u1))
print(u1 is u2)

What to look for:

User() constructs a new object each time you call it. In Python, every value, including strings, numbers, and lists, is already an object.


2) Use __init__ to set attributes

Use __init__ to set up the object’s attributes right when you create it.

class User:
    def __init__(self, email):
        self.email = email
        self.is_active = True

u = User("mina@example.com")
print(u.email, u.is_active)

What to look for:

self refers to the current instance. Assigning self.email = ... creates an attribute on that object.


3) Add methods that use the object’s data

Methods let your object do useful work with its own state.

class User:
    def __init__(self, email):
        self.email = email

    def display_name(self):
        return self.email.split("@")[0]

u = User("lea@example.com")
print(u.display_name())

Option A: Update internal state from a method

class Counter:
    def __init__(self, start=0):
        self.value = start

    def inc(self):
        self.value += 1

c = Counter(10)
c.inc()
c.inc()
print(c.value)

What to look for:

Call methods on an instance, like u.display_name(), not on the class itself.


Examples you can copy

Example 1: Create multiple objects from a list of dictionaries

class Task:
    def __init__(self, title, done=False):
        self.title = title
        self.done = done

rows = [
    {"title": "buy milk", "done": True},
    {"title": "send email", "done": False},
    {"title": "workout", "done": False},
]

tasks = [Task(row["title"], row["done"]) for row in rows]

print(tasks[0].title, tasks[0].done)
print(len(tasks))

Example 2: Validate inputs during object creation

class Discount:
    def __init__(self, percent):
        if not (0 <= percent <= 100):
            raise ValueError("percent must be between 0 and 100")
        self.percent = percent

d = Discount(15)
print(d.percent)

Example 3: Use a class method as an alternate constructor

This pattern helps when you want to create an object from a different input shape.

class User:
    def __init__(self, email):
        self.email = email

    @classmethod
    def from_username(cls, username, domain="example.com"):
        return cls(f"{username}@{domain}")

u = User.from_username("mila", domain="mimo.org")
print(u.email)

Example 4: Store computed values on the object

class Rectangle:
    def __init__(self, width, height):
        self.width = width
        self.height = height
        self.area = width * height

r = Rectangle(3, 5)
print(r.area)

Example 5: Build objects from an API-like response

class Product:
    def __init__(self, name, price):
        self.name = name
        self.price = price

response_items = [
    {"name": "Notebook", "price": 12},
    {"name": "Pen", "price": 2},
]

products = [Product(item["name"], item["price"]) for item in response_items]
print(products[0].name, products[0].price)

Example 6: Use @dataclass for data-focused objects with less boilerplate

This is handy when you mostly store data and want a shorter class definition.

from dataclasses import dataclass

@dataclass
class Product:
    name: str
    price: int

p = Product("Notebook", 12)
print(p)
print(p.name, p.price)

Common mistakes and how to fix them

Mistake 1: Forgetting to use self when setting attributes

What you might do

class User:
    def __init__(self, email):
        email = email  # does nothing useful

Why it breaks

You assign to a local variable, not to the object. The instance never gets an email attribute.

Fix

class User:
    def __init__(self, email):
        self.email = email

u = User("mina@example.com")
print(u.email)

Mistake 2: Using a mutable default value in __init__

What you might do

class Bag:
    def __init__(self, items=[]):
        self.items = items

Why it breaks

That list is shared across instances. Changes leak between objects.

Fix

class Bag:
    def __init__(self, items=None):
        self.items = [] if items is None else list(items)

a = Bag()
b = Bag()
a.items.append("key")

print(a.items)
print(b.items)

Mistake 3: Treating a class like an instance

What you might do

class User:
    def __init__(self, email):
        self.email = email

print(User.email)

Why it breaks

email exists on instances, not on the class itself.

Fix

u = User("ivan@example.com")
print(u.email)

Troubleshooting

If you see TypeError: __init__() missing ..., you called User() without the required arguments. Pass the values your constructor expects.

If you see AttributeError: 'User' object has no attribute 'email', you never set self.email in __init__, or you misspelled the attribute name.

If you see TypeError: 'User' object is not callable, you tried to call an instance like u(). Call the class to create objects, like User().

If your objects share list data by accident, check for mutable defaults like [] or {} in __init__ and switch to None.

If the @dataclass example errors, confirm you are on Python 3.7+ and that fields with defaults come after fields without defaults.


Quick recap

  • Define a class, then create an instance with ClassName().
  • Use __init__ to set attributes on self.
  • Add methods to act on the object’s data and state.
  • Avoid mutable default arguments like items=[].
  • Use @dataclass when you want a shorter data-focused class.