OOP

Object-Oriented Programming (OOP) Introduction

  • Discussion Session:

    • Inquiry about prior experience with object-oriented design in software.

    • Key terms: "object-oriented" and their implications for programming.

  • Goal of the Lab:

    • Explore top-down design of a simple class in Python.

    • Focus: Translating intuition and world knowledge into Python code.

    • Emphasis on designing objects (classes) by reasoning about:

      • Attributes: class properties.

      • Methods: class behaviors.

Programming Paradigms

  • Contrasting Paradigms:

    • Procedural Programming:

      • Sequential execution of instructions (e.g., C programming language).

    • Functional Programming:

      • Functions as central elements; state changes are avoided (e.g., Haskell).

    • Object-Oriented Programming:

      • Data and functions are encapsulated in objects (e.g., Java).

    • Blurred Distinctions:

      • Python supports both functions and classes; everything in Python is treated as an object.

Reasons for Learning OOP

  • Intuitive:

    • Models real-world concepts and relationships naturally.

  • Modular:

    • Breaks down complex systems into manageable pieces.

  • Extensible:

    • Allows for writing complex code derived from simpler concepts.

    • Facilitates generic code application across multiple settings.

  • Organized:

    • Promotes clean, reusable code which is practical in real-world applications.

Understanding Objects in OOP

  • Objects:

    • Defined as collections of attributes with associated behaviors.

    • Object-oriented design focuses on writing code that models these objects.

  • Familiar Python Objects:

    • Basic objects include strings, lists, and dictionaries.

    • Example Definitions:

      • name = "Alexander Hamilton"

      • titles = ["American military officer", "statesman", "Founding Father"]

      • dates = {"birth": "January 11, 1755", "death": "July 12, 1804"}

Instantiating Classes in Python

  • Class Instances:

    • A class serves as a blueprint for creating class instances.

    • Key Rules about Objects in Python:

      • Everything in Python is an object.

      • Every object is an instance of at least one class.

    • Class Keyword:

      • Used to create a type of object.

      • Object vs Class:

        • A class is an abstract specification of a type; an object is a concrete realization.

    • Objects possess states defined by their attributes (also known as properties or instance variables).

    • Behaviors that act on objects are referred to as methods.

Designing a Document Class for NLP

  • Example Scenario:

    • Development of a Document class for representing documents in a text processing pipeline.

    • Consideration of creating a Corpus class to manage multiple Document instances.

  • Design Process:

    • Initial meetings for mapping ideas to software products using Unified Markup Language (UML) diagrams to illustrate interactions.

    • Simplified focus on understanding concept-to-code mapping.

Document Class Implementation

  • Basic Implementation of Document Class:
    python class Document: """ Represents a single Document with contents. """ def __init__(self, contents=""): """ Creates a Document containing contents. """ self.contents = contents

  • Creating Instances: python doc1 = Document() doc2 = Document() print(id(doc1)) print(id(doc2))

    • Verification of instance uniqueness: id(doc1) == id(doc2) returns False.

  • Instance with Content: python doc3 = Document("hello!") print(doc3) print(doc3.contents)

    • Output:

      • <__main__.Document object at 0x7feb85084a10>

      • hello!

  • Key Components Observed:

    • The use of the self argument in the constructor __init__.

    • Creation of distinct instances with associated attributes.

Class Instantiation in Python: Detailed Mechanism

  • Two-Step Process for Class Instantiation:

    • The special method __new__ is invoked to create an instance (Constructor).

    • The special method __init__ is subsequently utilized to initialize instance attributes.

  • Note:

    • Custom __init__ methods are common; modification of __new__ is rare.

Enhanced Document Class

  • Adding Functionality to Document Class:
    python class Document: """ Represents a single Document in the Corpus. """ def __init__(self, contents="", tags="", id=None): """ Creates a Document with contents and optional tags. """ self.contents = contents self.tags = tags def match(self, filter): """ Determine if the document matches filter text. """ return filter in self.contents or filter in self.tags

Important Consideration for List Initialization

  • Initialization of Mutable Defaults:

    • Correct Approach:

      • Use None as the default to avoid shared mutable list instances, which can cause unintentional side effects.

    • Incorrect Approach:python class Document: def __init__(self, contents, tags=[], id=None):

      • Both instances reference the same list, which may lead to errors.

  • Example that Illustrates the Misuse of Mutable Defaults: python d1 = Document("hello", ["world news"]) d2 = Document("goodbye") print(id(d1.tags)) print(id(d2.tags))

    • Reflects the unintended consequences of using mutable defaults.

Adding More Dunder Methods for Document Class

  • Enhancement with String Representation:
    python class Document: def __str__(self): return f'{self.contents[:30]}... ' def __repr__(self): return f'{self.__class__.__name__}({self.contents[:30]}..., {self.tags})'

  • Implementation Example:
    python doc = Document("Das Ethiopian Cuisine: Upscale, white-tablecloth Ethiopian standby") print(doc) print(repr(doc))

  • Expected Output:

    • Das Ethiopian Cuisine: Upscale...

    • Document(Das Ethiopian Cuisine: Upscale..., )

Introducing the Corpus Class

  • Corpus Overview:
    python class Corpus: """ Represents a collection of Documents. """ def __init__(self): self.docs = [] ...

  • Functionality:

    • Initialize with an empty list of Documents.

    • Methods for creating, finding, and modifying documents within the collection.

  • Example Usage:
    python corpus = Corpus() corpus.create_document(123, "my document")

Review of Previous Data Structures

  • Review of Data Structures:

    • Familiar data structures: tuple, list, str.

    • Example of using a tuple to represent RGB pixel intensities:

      • pixel = (R, G, B).

  • NamedTuple for Enhanced Data Representation:
    python from typing import NamedTuple class Pixel(NamedTuple): red: int green: int blue: int

  • Example and Usage of NamedTuple:
    python p = Pixel(250, 0, 125) print(p.red) # Outputs: 250

  • Comparison to Lists:

    • Tuples: Immutable, more efficient but less flexible.

    • Lists: Mutable dynamic arrays used for manipulation post-creation.

Data Classes in Python

  • Introduction to Data Classes:

    • Defined using @dataclass, providing automatic method implementations.

    • Example data class for Email:
      python import dataclasses @dataclasses.dataclass class Email: subject: str body: str

  • Example of Usage: python doc = Email("This is the subject", "This is the body") print(doc)

    • Output format demonstrates automatically provided string representation.

Data Class Flexibility Compared to NamedTuple

  • Flexibility of Data Classes:
    python @dataclasses.dataclass class Email: subject: str = "Empty Subject" body: str = "Empty Body" recipients: list[str] = field(default_factory=list)

  • Explanation:

    • Default values can be set; fields can utilize various options.

    • Useful methods and behaviors present in data classes compared to NamedTuple.

  • Type Annotations:

    • Helpful but not enforced during runtime.

Conclusion: The Role of OOP in Software Design

  • OOP Clarification:

    • Focused on crafting customized data structures beyond what's available in built-in structures.

    • Importance of ongoing development and iterative design processes evident in software projects.