Object-Oriented Programming in Python

Gregory M. Kapfhammer

September 8, 2025

What are the main goals of object-oriented programming?

  • Write code that reflects thought and the world
  • Enable code reuse and sharing among programmers
  • Encourage the creation of well-designed software
  • Ensure that software is easy to maintain and extend

What is a class? What is an object?

  • A class is a blueprint for creating objects
  • An object is an instantiation of a class
  • A class defines the attributes and methods of an object
    • Attributes are the data that an object holds
    • Methods are the behaviors that an object can perform

Brainstorm an example of a class and an object that might exist in a program you use! After identifying the attributes and the methods, reflect on the benefits of object-oriented design.

Type Inference in Python

mylist = []
print(type(mylist))
print(isinstance(mylist, list))
print(isinstance(mylist, str))
<class 'list'>
True
False
  • Key insights about this source code:
    • mylist = [] creates an empty list
    • type(mylist) returns the type of the list
    • isinstance returns True or False for provided type
    • isinstance(mylist, list) checks if mylist is a list
    • Same approach works for other data types!

Existing types available in Python

def example_function():
  return 0
print(type(example_function))
<class 'function'>

def generator_example(n):
  for i in range(n):
    yield i
print(type(generator_example))
print(type(generator_example(5)))
<class 'function'>
<class 'generator'>
  • type shows that functions and generators have their own types
  • What are the similarities and differences for these two types?
  • How do return and yield influence a function’s behavior?

Explore use of the type function

  • Key Task: Add other types, including those that contain different types!

What if we don’t create objects?

u = (3,4)
v = (3,6)
def add(a, b):
  return (a[0] + b[0], a[1] + b[1])
def subtract(a,b):
  return (a[0] - b[0], a[1] - b[1])
def dot(a, b):
  return (a[0] * b[0] + a[1] * b[1])
def norm(a):
  return (a[0] * a[0] + a[1] * a[1]) ** 0.5
def isvertical(a):
  return a[0] == 0
print(norm(u))
print(add(u,v))
print(u + v)
print(isvertical(subtract(v, u)))
5.0
(6, 10)
(3, 4, 3, 6)
True

Explore tuple for encoding state

  • Key Questions: What are the strengths and weaknesses of this approach to representing vectors? How could this approach lead to program defects?

An object-oriented alternative

class Vector:
  def __init__(self, x, y):
    try:
      self.x = float(x)
      self.y = float(y)
    except ValueError:
      self.x = 0.0
      self.y = 0.0
  def norm(self):
    return (self.x ** 2 + self.y ** 2) ** 0.5
  def __add__(self, other):
    newx = self.x + other.x
    newy = self.y + other.y
    return Vector(newx, newy)
  def __str__(self):
    return "({:.2f}, {:.2f})".format(self.x, self.y)
u = Vector(3,4)
v = Vector(3,6)
print(u + v)
(6.00, 10.00)

Explore an object-oriented approach

  • Key Questions: After trying different instances of Vector, what is the state and behavior? What are the strengths and weaknesses of this approach to representing vectors? How could this approach lead to program defects?

What are the principles of object-oriented programming?

  • Abstraction: Hide implementation details
  • Inheritance: Create new classes from existing classes
  • Encapsulation: Group related data and methods together
  • Polymorphism: Allow objects to take on multiple forms

Encapsulation with Triangle

class Triangle:
    def __init__(self, points):
        self._sides = 3
        self._points = list(points)
        if len(self._points) != 3:
            raise ValueError("Wrong number of points.")

    def sides(self):
        return 3

    def __str__(self):
        return "I’m a triangle."
  • What state does a Triangle object have?
  • How can we access the state of a Triangle object?
  • What are the benefits and limitations of encapsulation?

Encapsulation with Square

class Square:
    def __init__(self, points):
        self._sides = 4
        self._points = list(points)
        if len(self._points) != 4:
            raise ValueError("Wrong number of points.")

    def sides(self):
        return 4

    def __str__(self):
        return "I’m so square."
  • What state does a Square object have?
  • How can we access the state of a Square object?
  • Wait, what is the purpose of __init__ and __str__?

Wait, what is the relationship between a Square and a Triangle?

class Polygon:
    def __init__(self, sides, points):
        self._sides = sides
        self._points = list(points)
        if len(self._points) != self._sides:
            raise ValueError("Wrong number of points.")

    def sides(self):
        return self._sides
  • The Polygon class is a superclass of Triangle and Square
  • The Triangle and Square classes are subclasses of Polygon
  • The Polygon class is a generalization of Triangle and Square

Connecting Triangle and Square to the Polygon Superclass

class Triangle(Polygon):
    def __init__(self, points):
        Polygon.__init__(self, 3, points)

    def __str__(self):
        return "I’m a triangle."

class Square(Polygon):
    def __init__(self, points):
        Polygon.__init__(self, 4, points)

    def __str__(self):
        return "I’m so square."
  • Forms an “is-a” relationship between:
    • Triangle and Polygon and also Square and Polygon

Using composition in Python

class MyLimitedList:
    def __init__(self):
        self._L = []

    def append(self, item):
        self._L.append(item)

    def __getitem__(self, index):
        return self._L[index]
  • The MyLimitedList class “has-a” list inside of it called _L
  • Composition is a way to build complex objects from simpler ones
  • The MyLimitedList class is a “is-a” of list
  • Let’s fully connect this to document engineering!
  • How can we use objects to represent documents?

Document connection

  • A Document can maintain state and exhibit behavior:
    • State:
      • Store its title, author, and content
      • Maintain metadata like keywords and categories
    • Behavior:
      • Count its own words automatically
      • Generate summaries by itself
  • A document engineering “pipeline” can have these features:
    • Contain a list of documents and process and search them
    • Generate reports and summaries of the list of documents

Defining a Document class

from typing import Dict
from datetime import datetime

class Document:
    """A base class representing a document in our document engineering system."""
    
    def __init__(self, title: str, author: str, content: str = ""):
        """Initialize a document with basic properties."""
        self.title = title
        self.author = author
        self.content = content
        self.created_date = datetime.now()
        self.word_count = len(content.split()) if content else 0
        self.metadata: Dict[str, str] = {}
    
    def add_metadata(self, key: str, value: str) -> None:
        """Add metadata to the document."""
        self.metadata[key] = value
    
    def get_summary(self) -> str:
        """Generate a summary of the document."""
        return f"'{self.title}' by {self.author} ({self.word_count} words)"
    
    def __str__(self) -> str:
        """String representation of the document."""
        return self.get_summary()

Exploring the Document class

  • Insight: Document offers the state and behaviors of a document!

Inheritance builds on a class

Like a family tree of classes

  • Parent class: basic Document
  • Child class: specialized TechnicalDocument
  • Child inherits everything from parent
  • Child can add its own special features

Why inheritance? One reason: Code reuse!

  • Don’t rewrite the same code
  • Build on what’s already working
  • Add only what’s new and different

Inheritance example

Insight: TechnicalDocument builds on Document by adding a new property called level! What else could we add to this subclass?

Composition with DocumentSection

Key insight: Generator is made of smaller parts that work together!

Object-orientation for documents

  • Abstraction: Hide complexity
    • Document classes hide file operations
    • Users work with simple document objects
  • Inheritance: Build on existing code
    • Child classes inherit parent features
    • Add only what’s new and different
  • Encapsulation: Protect object’s state
    • Private data stays safe inside classes
    • Public methods control access
  • Polymorphism: Same action, different results
    • One method name, many behaviors
    • Code stays simple, results vary

Objects empower prosegrammers!

  • Objects makes document engineering easier
    • Classes organize document tools
    • Inheritance reuses existing code
    • Polymorphism handles different document types
    • Composition builds flexible systems
  • Start simple, build complex systems
    • Begin with basic document classes
    • Add features as you need them
    • Combine simple parts into powerful tools

Overall document engineering setup

Tips for effective document engineering setup

  • Devote time outside class to installing and configuring tools

  • Confirm that most tools work during the this week’s lab session

  • Create and render test documents with the provided examples

  • Complete the first document engineering project on time

  • Contribute to collaborative documentation projects

  • Prepare for first document engineering skill check

  • Get ready for an exciting journey into document engineering!

  • If you are having trouble, publicly ask for help on Discord!

  • If you would like to use a token, please contact the course instructor!

Reminder of course goals

  • Document Creation:
    • Design and implement document generation workflows
    • Test all aspects of documents to ensure quality and accuracy
    • Create frameworks for automated document production
  • Document Analysis:
    • Collect and analyze data about document usage and quality
    • Visualize insights to improve documentation strategies
  • Communicate results and best practices for document engineering
  • Check syllabus for details about Document Engineering course!