← Back

Prototype Design Pattern in Python: Creating Objects by Cloning

Posted on Tue 26 May 2026 in Python

Sometimes creating an object from scratch is expensive or unnecessarily complicated.

Imagine an application that creates highly configured objects containing:

  • Name
  • Configuration
  • Permissions
  • Metadata
  • Nested objects
  • Templates
  • Formatting

If you repeatedly need objects with almost identical configurations, constructing each one from scratch can be inefficient and repetitive.

The Prototype Design Pattern provides another approach: create one configured object and clone it whenever you need a similar object.

Refactoring.Guru describes Prototype as a creational pattern that allows existing objects to be copied without making the code dependent on their concrete classes.

What Is the Prototype Pattern?

The basic idea is:

Existing Object
      |
      | clone()
      |
      +----> New Object
      |
      +----> New Object
      |
      +----> New Object

The original object acts as a prototype.

Instead of:

new_object = ComplexObject(...)

we can do:

new_object = existing_object.clone()

Python Example

Python provides the copy module, which makes cloning particularly convenient.

import copy

class Project:

    def __init__(self, name, settings):
        self.name = name
        self.settings = settings

    def clone(self):
        return copy.deepcopy(self)

Create a prototype:

prototype = Project(
    "Default Project",
    {
        "theme": "dark",
        "language": "English",
        "notifications": True
    }
)

Now clone it:

project1 = prototype.clone()
project2 = prototype.clone()

Each project is a separate object:

print(project1 is prototype)

Output:

False

But the cloned objects contain the same initial configuration.

Why Clone Instead of Constructing?

Imagine a report object contains dozens of settings:

report = Report(
    title="Monthly Report",
    theme="professional",
    header=True,
    footer=True,
    charts=True,
    pagination=True,
    language="English",
    ...
)

If we repeatedly create similar reports, we have to repeat the configuration.

With Prototype:

template = Report(...)

Then:

report1 = template.clone()
report2 = template.clone()
report3 = template.clone()

This can make object creation simpler.

Shallow Copy vs Deep Copy

This is particularly important in Python.

Shallow Copy — copy.copy(object) creates a new outer object, but nested mutable objects may still be shared.

Deep Copy — copy.deepcopy(object) recursively copies nested objects as well.

Example:

import copy

original = {
    "name": "Project",
    "settings": {
        "theme": "dark"
    }
}

clone = copy.deepcopy(original)

Now the nested dictionary is also independently copied.

A More Practical Example

Suppose a game needs many enemy objects. Each enemy has:

  • Health
  • Speed
  • Weapon
  • Armor
  • Position
  • AI Configuration

Creating every enemy from scratch may involve a large amount of configuration.

Instead, create prototypes:

Enemy Prototype
    |
    +---- Soldier
    |
    +---- Sniper
    |
    +---- Tank

Then:

soldier = soldier_prototype.clone()
sniper = sniper_prototype.clone()
tank = tank_prototype.clone()

The game can then modify individual properties such as position or health.

Prototype Registry

For applications with many frequently used prototypes, a registry can be useful.

Conceptually:

prototypes = {
    "soldier": soldier_prototype,
    "sniper": sniper_prototype,
    "tank": tank_prototype
}

Then:

enemy = prototypes["soldier"].clone()

Refactoring.Guru describes a prototype registry as a collection of pre-built objects that can be accessed and copied when needed.

Prototype vs Factory Method

These patterns solve different creation problems.

Factory Method creates an object based on a class or factory decision:

Factory
   |
   +----> Object Type A
   +----> Object Type B

Prototype starts with an existing configured object:

Existing Object
      |
      +---- clone()
      +---- clone()
      +---- clone()

A simple way to remember the difference: Factory creates. Prototype copies.

Advantages

Faster or Simpler Construction — Useful when creating an object from scratch requires significant setup.

Avoids Repetitive Configuration — Create the configuration once and reuse it through cloning.

Reduces Dependency on Concrete Classes — The client can clone an existing object without needing to know its exact concrete class.

Useful for Many Similar Objects — Particularly helpful when many objects share most of their configuration.

Potential Problems

Deep copying can be expensive for very large object graphs.

Some objects also contain resources that should not simply be copied, such as:

  • Database connections
  • File handles
  • Network connections
  • Thread locks
  • External resources

Therefore, cloning behavior should be designed carefully.

When Should You Use Prototype?

Consider Prototype when:

  • Objects are expensive or complex to initialize
  • Many objects share similar configurations
  • You want to avoid repeating setup code
  • The exact concrete class may not be known by the client
  • Pre-configured templates can be reused

Conclusion

The Prototype pattern focuses on creating new objects from existing objects.

The central idea is: configure an object once, then clone it whenever you need another object with a similar configuration.

Python's copy and deepcopy utilities make this pattern especially practical, although developers must understand how nested and resource-based objects behave during copying.