Lecture Notes
Introduction to Programming and Algorithm Design (COP-1000)

Classes and functions

This chapter discusses two ways to write functions that use objects as parameters: pure functions and modifier functions.


  • Another example of a user-defined type:

    >>> class Time:
  • Instantiate a Time object t1, and give it some attributes:
    >>> t1 = Time()
    >>> t1.hours = 11
    >>> t1.minutes = 59
    >>> t1.seconds = 30
  • See example program time1.py

Pure functions

  • A pure function is one that
    • does not modify any of the objects passed as parameters
    • has no side effects, like displaying a value or getting user input
  • Pure functions usually return an object
  • See example program time2.py
    • addTime() is a pure function
    • Time object is returned to caller
    • Unfortunately, addTime() does not work correctly
  • See example program time3.py
    • addTime() now works correctly


  • Functions that make changes to an object passed as a parameter are called modifiers
  • See example program time4.py
    • increment() modifies caller's object
    • nothing needs to be returned
  • See example program time5.py
    • increment() is now a pure function makes copy of caller's object, modifies copy, then returns it
  • Programs written with only pure functions are faster to develop are less error-prone than programs written with modifiers
  • Modifier functions are often faster in execution than the pure function counterparts
  • Rule of thumb: Write programs with pure functions, unless there is a compelling reason to use a modifier function
  • Writing programs with mainly pure functions is called functional programming style

Prototype development versus planning

  • In prototype development, a working model of a function is written, then tested and corrected as problems are found (like addTime(), above)
  • Prototype development is common and often used for small programs because they can be quickly written and demonstrated, even if they do not successfully handle every case; code resulting from prototype development is often unnecessarily complicated
  • Alternatively, planned development means thinking the problem through before you write the code, to see if you can find a more comprehensive or general solution, rather than handle each case individually
  • Planned development means writing algorithms
  • Here is a better implementation of the functionality for a Time class: time6.py
    • Two new (pure) functions provided:
      • convert a Time object to seconds
      • convert seconds to Time object
    • Note what happens to increment()!


  • By thinking the problem through, we came up with a more general solution, that required converting between base 60 (Time) and base 10 (seconds)
  • But by solving the bigger problem, we provided a facility through which functionality can be more easily extended; consider these functions:

    def addTime(t1, t2):
        return makeTime(convertToSecs(t1) + convertToSecs(t2))

    def after(t1, t2):
        return convertToSecs(t1) > convertToSecs(t2)
  • Both these functions are now much easier to write, test, and demonstrate to be correct

Pilot System

  • In his classic book "The Mythical Man-Month", Fred Brooks makes several sage observations about software engineering, many of them contrary to conventional wisdom at the time
  • One observation is that the first attempt at a design is often a "pilot system" that serves primarily as a learning device for the engineer
  • Here is the Wikipedia description: 

When designing a new kind of system, a team will design a throw-away system (whether it intends to or not). This system acts as a "pilot plant" that reveals techniques that will subsequently cause a complete redesign of the system. This second, smarter system should be the one delivered to the customer, since delivery of the pilot system would cause nothing but agony to the customer, and possibly ruin the system's reputation and maybe even the company's.

 Updated: 12.13.2010