The factory design pattern in Python means letting a function (or class method) decide which class to create, so your code asks for an object by name, not by class. In Python, a dictionary of classes is often all you need:
METHODS = {"ground": Ground, "express": Express}
def make_shipping(method):
return METHODS[method]()
Each pattern below ran on Python 3.12.5, using shipping, notifications, orders and payments as examples.
I’ll show a simple factory, a self-registering factory with a decorator, factory methods with @classmethod, abstract base classes that enforce the interface, and when a factory is overkill.
A simple factory in Python
The caller passes a name, and make_shipping() returns the right object. Every class has the same cost() method, so the caller doesn’t care which one it got:
class Ground:
def cost(self, pounds):
return 5.99 + 0.50 * pounds
class Express:
def cost(self, pounds):
return 12.99 + 1.25 * pounds
class Overnight:
def cost(self, pounds):
return 24.99 + 2.00 * pounds
METHODS = {"ground": Ground, "express": Express, "overnight": Overnight}
def make_shipping(method):
"""The factory: callers ask by name and never import the classes."""
try:
return METHODS[method.lower()]()
except KeyError:
raise ValueError(f"unknown shipping method {method!r}; choose from {sorted(METHODS)}") from None
for name in ["ground", "Express", "overnight"]:
shipper = make_shipping(name)
print(f"{name:<9} {type(shipper).__name__:<9} 4 lb -> ${shipper.cost(4):.2f}")
try:
make_shipping("drone")
except ValueError as err:
print("ValueError:", err)
Output:
ground Ground 4 lb -> $7.99
Express Express 4 lb -> $17.99
overnight Overnight 4 lb -> $32.99
ValueError: unknown shipping method 'drone'; choose from ['express', 'ground', 'overnight']

Adding a new shipping option means adding one class and one dictionary entry. No if/elif chain anywhere else needs to change.
A self-registering factory with a decorator
For plugin-style code, let each class register itself. A small decorator adds the class to the factory’s dictionary when it’s defined:
NOTIFIERS = {}
def register(name):
def decorator(cls):
NOTIFIERS[name] = cls # each class adds itself to the factory
return cls
return decorator
@register("email")
class EmailNotifier:
def send(self, to, msg):
return f"email to {to}: {msg}"
@register("sms")
class SmsNotifier:
def send(self, to, msg):
return f"text to {to}: {msg[:20]}"
def create_notifier(kind):
return NOTIFIERS[kind]()
print("registered:", list(NOTIFIERS))
print(create_notifier("email").send("ava@example.com", "Your order shipped"))
print(create_notifier("sms").send("512-555-0147", "Your order shipped today, track it online"))
Output:
registered: ['email', 'sms']
email to ava@example.com: Your order shipped
text to 512-555-0147: Your order shipped t

Decorators like this one are covered in Python class decorators.
Factory methods with @classmethod
A factory method is a class method that builds an instance from some other format. Python uses this all over the standard library, such as dict.fromkeys() and date.fromisoformat():
from datetime import date
class Order:
def __init__(self, order_id, total, placed):
self.order_id, self.total, self.placed = order_id, total, placed
@classmethod
def from_csv(cls, line): # factory method: build from a CSV row
order_id, total, placed = line.split(",")
return cls(int(order_id), float(total), date.fromisoformat(placed))
@classmethod
def from_dict(cls, data): # factory method: build from JSON-style data
return cls(data["id"], data["total"], date.fromisoformat(data["date"]))
def __repr__(self):
return f"Order({self.order_id}, ${self.total:.2f}, {self.placed})"
print(Order.from_csv("1042,59.99,2026-11-10"))
print(Order.from_dict({"id": 1043, "total": 120.0, "date": "2026-11-11"}))
Output:
Order(1042, $59.99, 2026-11-10)
Order(1043, $120.00, 2026-11-11)

Returning cls(...) rather than Order(...) means subclasses get the factory methods for free. More in the Python classmethod guide.
How do you enforce the interface in a factory?
If every product must have the same methods, define an abstract base class. Python then refuses to create a subclass that forgot to implement them:
from abc import ABC, abstractmethod
class PaymentMethod(ABC):
@abstractmethod
def charge(self, amount): ...
class Card(PaymentMethod):
def charge(self, amount):
return f"charged ${amount:.2f} to card"
class BankTransfer(PaymentMethod):
def charge(self, amount):
return f"scheduled ${amount:.2f} bank transfer"
class Broken(PaymentMethod): # forgot to implement charge()
pass
def payment_factory(kind) -> PaymentMethod:
return {"card": Card, "bank": BankTransfer, "broken": Broken}[kind]()
print(payment_factory("card").charge(49.99))
print(payment_factory("bank").charge(1250.00))
try:
payment_factory("broken")
except TypeError as err:
print("TypeError:", err)
Output:
charged $49.99 to card
scheduled $1250.00 bank transfer
TypeError: Can't instantiate abstract class Broken without an implementation for abstract method 'charge'

Broken didn’t implement charge(), so creating it fails right away instead of later in production.See abstract base classes in Python for the details of abc.
When to use the factory pattern (and when not to)
| Use a factory when | Skip it when |
|---|---|
| The class to create depends on data (a config value, user choice, file type) | There’s only one class |
| You keep adding new types | The types never change |
| Callers shouldn’t import every concrete class | A direct constructor call is clearer |
| You need several ways to build one class | One __init__ covers it |
In Python I keep factories small: a dict, a function, or a classmethod. The heavy class hierarchies you see in Java-style examples are rarely needed.
More Python object-oriented guides:
Frequently asked questions
What is the factory design pattern in Python?
It’s a way to create objects without naming their class directly: a function or method picks the right class and returns an instance.
What’s the simplest factory in Python?
A dictionary that maps names to classes, plus a function that looks up the name and calls the class.
What’s the difference between a factory function and a factory method?
A factory function stands alone and can return different classes. A factory method is a @classmethod that builds instances of its own class from other data.
How do I handle an unknown type in a factory?
Catch the KeyError and raise a ValueError that lists the valid choices.
Do I need abstract base classes for a factory?
No, but they help: Python raises TypeError if a product class forgets a required method.
Where are abstract base classes documented?
See abc in the Python docs.

Bijay Kumar is a 13-time Microsoft MVP with more than 18 years in software development, and the founder of Python Guides and TSinfo Technologies. He started out building .NET and SharePoint solutions at HP, TCS and KPIT before moving into Python, machine learning and AI, and he also builds web apps with TypeScript and React. He writes the tutorials here himself, and every example is run before publishing so you see the real output. More about Bijay · Microsoft MVP profile · LinkedIn