Card 07/ 08
Practice: Copying a Document Template
A template with a title, a list of sections and a style object, copied for each new document.
A document tool that starts every proposal from a template is a natural Prototype, and this exercise asks you to write its clone() and decide how deep each field's copy must go. The template has a title string, a sections list and a style dictionary. Each new document changes its title, adds sections, and may change a style setting, and none of that may reach the template.
- For each field, say whether the copy may share it with the template, and why.
- Write
clone()withoutcopy.deepcopy, copying only what must be copied. - Show that changing a new document leaves the template unchanged.
Show a solution
import copy
class DocumentTemplate:
def __init__(self, title: str, sections: list[str], style: dict[str, str]) -> None:
self.title = title
self.sections = sections
self.style = style
def clone(self) -> "DocumentTemplate":
duplicate = copy.copy(self)
duplicate.sections = list(self.sections)
duplicate.style = dict(self.style)
return duplicate
proposal = DocumentTemplate("Proposal", ["Summary", "Scope", "Costs"], {"font": "Inter", "accent": "teal"})
acme = proposal.clone()
acme.title = "Proposal for Acme"
acme.sections.append("Timeline")
acme.style["accent"] = "orange"
print("template:", proposal.title, proposal.sections, proposal.style)
print("acme: ", acme.title, acme.sections, acme.style)template: Proposal ['Summary', 'Scope', 'Costs'] {'font': 'Inter', 'accent': 'teal'}
acme: Proposal for Acme ['Summary', 'Scope', 'Costs', 'Timeline'] {'font': 'Inter', 'accent': 'orange'}The title can be shared: a Python string cannot change, so assigning a new title to the copy replaces the copy's reference and leaves the template's alone. The sections list and the style dictionary cannot be shared, because the document changes them in place, with append and with item assignment.
The output shows the template still has three sections and a teal accent after the Acme document added a timeline and turned orange. copy.deepcopy would also be correct here; writing the copy by hand says which fields were considered, and avoids copying anything that should stay shared if the class later gains one.
← → move through sections and cards