Intro to CS: Lectures 1-26 notes/blogs


Lecture 1 - Introduction

Date: 2025-12-19

Here are my notes and thoughts about this lecture. Topics: Introduction to Python: knowledge, machines, objects, types, variables, bindings, IDEs.

Declarative vs. imperative knowledge. The former is statements of fact while the latter is a recipe or "how to". In this course we will be dealing with mostly imperative knowledge.

Programming is writing a recipe for a computer to do something.

We are really getting back to the basics. We talk about what an algorithm is, which is the following:

  1. A sequence of simple steps
  2. Flow of control process that specifies when each step is executed
  3. A means of determining when to stop

So I already knew (1) but I guess I didn't consider (2) and (3) before, explicitly at least, so that's something new.

Computers are machines that execute algorithms. Big idea: Computers will only do what you tell them to do.

Before there were fixed program computers, meaning computers with a fixed set of algorithms. Then came stored program computers. Now computers store and execute instructions.

Key insight: programs are no different than other kinds of data. A special program called an interpreter executes each instruction in order.

This reminds me of when I took computer architecture, we were fetching instructions to execute from the registers, which were then loaded into memory IIRC. Or maybe the instructions didn't need to get loaded into memory but rather were loaded directly from the registers and then executed. Not sure, it's been awhile.

With primitives we build the syntax of a language. English for example, is made up of words as its primitives. The lecture draws parallels between English language and a programming language. Syntax validity is one example, another ex. Is static semantics.

Programs have multiple data objects. Objects have a type that defines the kinds of things programs can do to them.

This is all straightforward and I want to optimize for time, so I think I'll only note stuff that I find interesting or haven't learned before.

We review the basic primitive types such as int, boolean, float, etc. We review type casting and creating expressions. Note: Expressions are NOT stored in memory, only their result.

I guess something new I learned is that a function call is an expression because it results in a value.

Finished the video, it was all straightforward. But let's carry on and see after the course just how much of it was redundant for me.

Lecture 2 - Strings, Input/Output, Branching

This blog post might be really short as I don't feel like repeating things that I already know. Will keep watching the lecture to see if anything interesting pops up. Watching lectures on 2x speed.

Topics: Core Elements of Programs: strings, input/output, f-strings, operators, branching, indentation.

Lecture 3 - Iteration

Going over while and for loops. This is basic stuff for me. Watching video at 2x speed. Done watching, no new things learned. Onward to lecture 4.

Lecture 4 - Loops over strings, guess-and-check, and binary

This lecture explains iteration in simple programs like guess-and-check, binaries, and fractions in Python. Loops can iterate over any sequence of values including a range for numbers or a string. Guess-and-check provides a simple algorithm for solving problems. When the set of potential solutions is enumerable, exhaustive enumeration is guaranteed to work (eventually). Binary numbers help us understand how the machine works. Converting to binary will help us understand how decimal numbers are stored

Guess and check algorithms, and use of boolean flags is covered. Can't use equal sign between floats due to approximation error. Dealing with floats as transaction amounts for a fintech company I worked for, this concept was applied.

Overall it was a review lecture for me. I guess one new thing I learned was the algorithm for converting a decimal integer to a binary number. Or I probably learned it before but forgot it. It basically checked if the number was odd or even, if odd, add 1 to the left of the string, otherwise add 0, then divide number by 2 and repeat process. The finger exercise was easy.

On to the next lecture.

Lecture 5 - Floats and Approximation Methods

Topics: Simple Algorithms: approximation method, floats

One thing I observed so far is that this course is not teaching a systematic way on how to come up with algorithms. By coming up with algos, I mean the process of taking a well-defined problem, its steps, and translating it into code.

The instructor mentions that it is not expected to come up with some of these mathematical recipes/steps, like converting an integer to binary, for example. But it IS expected to translate the algo/recipe into code. The "translating" steps in between are not explicitly taught but rather seem to be implicitly assumed. That's one flaw with this course I've found so far, and also a flaw with Systematic Program Design course. In my opinion, for beginner level courses, such a technique is important.

There's another course I took awhile back that teaches this general technique for translation from problem to code. Be aware that the course I am referring to is not mentioned as part of the OSSU curriculum, although I'm thinking about starting a conversation to add it there (but its a Coursera course so might not get approved).

If you struggle with translating a problem and its solution into code like on problem set 1 of this course, and if you're curious about that general technique, here is a 1-page PDF describing the technique, maybe you can apply it when doing the problem sets for this course.

If you're curious about which course(s) I'm referring to, it's part of the Coursera Java programming and software engineering fundamentals specialization (first few courses). Not trying to steer anyone away from this course, but the courses from the specialization linked use and teach that technique which I found to be extremely useful when I was a beginner, and seem to not be taught in this MIT course (so far, but I'm only on lecture 6, so I can't fully judge this course just yet until after I complete it).

I could turn out to be proved wrong, if later in the course such a technique is taught.

Curious what others think about this.

Anyway, now I start watching this lecture. Never use == to test floats. What gets printed is not always what's in memory. Need to be careful in designing algorithms that use floats.

This brings us to an approximation method. Find an answer that is "good enough". We increment by some small amount and we stop when we are close enough (exact is not possible).

Lecture 6 - Bisection search

Topics: Simple Algorithms: bisection search, Newton-Raphson

This is basically binary search. Straightforward algorithm and review for me.

I learned something new. Or something I probably learned before but forgot about. The square root of a number between 0 and 1 is going to be greater than itself.

Compared different algorithms for finding square root.

Lecture 7 - Decomposition, Abstraction, Functions

Topics: Functions: decomposition, abstraction, specifications

Big idea: Apply abstraction (black box) and decomposition (split into self-contained parts) to programming.

Already know about functions, decomposition, and abstraction, so this lecture is review to me.

The instructor is now teaching how to come up with code for say a quiz. They say not to write code right away, to do an example by hand, and come up with steps that we think a computer can interpret. So I was wrong about my initial assumption that the course does not teach such a technique. It does.

Lecture 8 - Functions as Objects

Topics: Functions: environments, scope, functions as objects

This is also review for me. Another thing I noticed about this course is that a lot of math examples are used. Math and CS/Programming go hand in hand so I'm not surprised by this. Also, this is MIT, so students are expected to be familiar with basic math, of course.

Going over frames/scoping. This is great knowledge for a beginner to learn.

One of the scoping examples bit me during an interview, namely the case where a function can reference variables from its parent scope.

A function is an object and can be passed in as an argument to another function and can also be a return value.

In Python all primitive types are objects, including boolean, float, int, etc.

Lecture 9 - Lambda functions, Tuples, and Lists

Topics: Tuples and lists

Lambda creates a procedure/function object, but does not bind a name to it. I've come across lambda functions throughout my experience so I am familiar with them. Another name for them is anonymous functions.

Going over tuples, and variable number of arguments.

Lecture 10 - Lists, Mutability

Topics: List Operations, Mutability: mutation, aliasing, tricky examples with loops over L

Lists are mutable. Strings are not. We covered the append function on lists. Convert string to list using list(s), and convert list to string using join. This is all review for me.

Functions with side effects can mutate inputs. We go over some tricky loop examples which I think was a good review for me.

Lecture 11 - Aliasing, Cloning

Topics: Aliasing and cloning

Going over some operations on lists, including .clear(), .pop(), del() and .remove().

Iterating over a list as you are mutating the list can lead to unpredictable behavior. Takeaway here is to be careful when mutating a list while iterating over it. Consider using a copy.

= sign on mutable object creates an alias, not a clone.

Big idea: When you pass a list as a parameter to a function, you are making an alias.

Shallow copy vs. deep copy.

Lecture 12 - List comprehension, functions as objects, testing, debugging

Date: 2026-01-01 10:00 Category: Intro to CS using Python Tags: computer-science,python

Topics: More Functions as Objects, Keyword Arguments, Default Arguments, Debugging: glass box/black box testing, examples

List comprehensions are review for me. Default parameters are also review.

Functions can return another function. Why bother returning functions?

  • Code can be rewritten without returning function objects
  • Good software design
    • Embracing ideas of decomposition, abstraction
    • Another tool to structure code
  • Interrupting execution
    • Example of control flow
    • A way to achieve partial execution and use result somewhere else before finishing the full evaluation

Going over testing and debugging.

Testing

Break up code into modules that can be tested and debugged individually. Document constraints on modules. What do you expect input/output to be? Document assumptions behind code design.

When are you ready to test?

  • Ensure code runs
    • Remove syntax errors
    • Remove static semantic errors
    • Python interpreter can usually find these for you
  • Have a set of expected results
    • An input set
    • For each input, the expected output

Classes of tests

  • Unit testing
    • Validate each piece of program
    • Testing each function separately
  • Regression testing
    • Add test for bugs as you find them
    • Catch reintroduced errors that were previously fixed
  • Integration testing
    • Does overall program work?
    • Tend to rush to do this

These testing concepts definitely come up in the real world on the job, so this is a good review for me.

Testing approaches

  • Intuition about natural boundaries to the problem
    • Mathematical functions usually make this easy
    • Can you come up with some natural partitions?
  • If no natural partitions, might do random testing
    • Probability that code is correct increases with more tests
    • Better options below
  • Black box testing
    • Explore paths through specification
    • Designed without looking at the code
    • Can be done by someone other than the implementer to avoid some implementer biases
    • Testing can be reused if implementation changes
    • Paths through specification
      • Build test cases in different natural space partitions
      • Also consider boundary conditions (empty lists, singleton list, large numbers, small numbers)
  • Glass box testing
    • Explore paths through code
    • Use code directly to guide design of test cases
    • Called path-complete if every potential path through code is tested at least once
    • What are some drawbacks to this type of testing?
      • Can go through loops arbitrarily many times
      • Missing paths
    • Guidelines
      • Branches
        • Exercise all parts of a conditional
      • For loops
        • Loop not entered
        • Body of loop executed exactly once
        • Body of loop executed more than once
      • While loops
        • Same as for loops, cases that catch all ways to exit loop
    • Path complete test suite could still miss a bug
      • Should still test boundary cases

Debugging

  • Once you have discovered that your code does not run properly, you want to:
    • Isolate the bug(s)
    • Eradicate the bug(s)
    • Retest until code runs correctly for all cases
    • Steep learning curve
  • Goal is to have a bug free program
  • Tools
    • Built in to IDLE and Anaconda
    • Python tutor
    • Print statement
    • Use your brain, be systematic in your hunt

Error messages - Easy

Logic errors - hard

  • think before writing new code
  • draw picture, take a break
  • explain the code to
    • Someone else
    • A rubber ducky

Debugging steps

  • Study program code
    • Don't ask what is wrong
    • Ask how did I get the unexpected result
    • Is it part of a family
  • Scientific Method
    • Study available data
    • Form hypothesis
    • Repeatable experiments
    • Pick simplest input to test with

Print statements are a good way to test hypothesis

Lecture 13 - Exceptions, Assertions

Topics: Exceptions, assertions

Introduced to the try/except code blocks, with some examples.

Also introduced to assertions, as a way to program defensively. I sort of forgot about assertions so this is good review. I will look to use them in my future code. They are good for enforcing invariants.

Overall this lecture was review for me.

Lecture 14 - Dictionaries

Topics: Dictionaries: keys, values, mutability, iteration over a dict, examples

This is review for me, I am familiar with dictionaries. I guess one new thing I learned is that dictionary keys must be immutable or technically hash-able objects. Although in practice this is obvious.

Lecture 15 - Recursion

Topics: Recursion: iteration vs. recursion, inductive reasoning

Recursion is review for me. I like the example she gave with the student asking professor, TA, and LA to regrade.

Big idea: "Earlier" function calls are waiting on results before completing. Went over some more examples of recursion.

When to use recursion?

  • Multiplication of two numbers did not need a recursive function, did not even need an iterative function
  • Factorial was a little more intuitive to implement with recursion
  • MOST problems do not need recursion to solve them
    • If iteration is more intuitive for you then solve them using loops
  • SOME problems yield far simpler code using recursion
    • Searching file system for a specific file
    • Evaluating mathematical expressions that use parens for order of ops

Lecture 16 - Recursion on Non-Numerics

Topics: Recursion: Fibonacci, Fibonacci with a dict, recursion on non-numerics, recursion on lists, Towers of Hanoi (extra)

We start by reviewing fibonacci and tracing through the function call graph. Recursion in general is review for me, I still think this lecture is good for me to digest.

After doing another recursion example of basketball scores, we apply the idea of recursion to lists. The first example is sum all elements in a list.

The idea is similar to how we would sum elements in a list in the Systematic Program Design course. The instructor states that we need to trust that the recursive calls do the right thing. The instructor from SPD says the same thing ! Trust the natural recursion.

Why use recursion? Some problems are very difficult to solve with iteration.

Intuition for when to use recursion:

  • In the list examples so far, we knew how many levels we needed to iterate
    • Either look at elements directly or one level down
  • But lists can have elements that are lists, which can in turn have elements that are lists, which can in turn have elements that are lists, etc.
  • How can we use iteration to do these checks? It's hard

Problems that are naturally recursive:

  • A file system
  • Order of operations in a calculator

I like the example they gave of reverse a list of elements, all sub-elements get reversed too, leaving the code here for reference:

def deep_rev(L):
    if L == []:
        Return []
    elif type(L[0]) != list:
        Return deep_rev(L[1:]) + [L[0]]
    else:
        Return deep_rev(L[1:]) + [deep_rev(L[0])]

I also like the finger exercise for flattening an arbitrarily-nested list, so I will include code here for reference:

def flatten(L):
    result = []
    for i in L:
        if type(i) == list:
            result.extend(flatten(i))
        else:
            result.append(i)
    return result

Lecture 17 - Python Classes

Topics: Object Oriented Programming: data abstraction, class def, class instances, methods

More review for me. I don't mind reviewing though. We start by defining an object, along with examples.

Advantages of OOP

  • Bundle data into packages together with procedures that work on them through well-defined interfaces
  • Divide and conquer development
    • Implement and test behavior of each class separately
    • Increased modularity reduces complexity
  • Classes make it easy to reuse code
    • Many python modules define new classes
    • Each class has a separate environment (no collision on function names)
    • Inheritance allows subclasses to redefine or extend a selected subset of a superclass' behavior

The Power of OOP

  • Bundle together objects that share
    • Common attributes and
    • Procedures that operate on those attributes
  • Use abstraction to make a distinction between how to implement an object vs. how to use an object
  • Build layers of object abstractions that inherit behaviors from other classes of objects
  • Create our own classes of objects on top of python's basic classes

Lecture 18 - More Python Class Methods

Topics: Object Oriented Programming: dunder methods, examples

We start with a review of classes and methods from last lecture.

Class vs. instance of a class.

All review for me, of course, but I like to observe how they teach it.

Dunder methods review.

Why OOP and bundling the data in this way?

  • Code is organized and modular
  • Code is easy to maintain
  • It's easy to build upon objects to make more complex objects
  • Decomposition and abstraction at work with python classes
    • Bundling data and behaviors means you can use objects consistently
    • Dunder methods are abstracted by common operations, but they're just methods behind the scenes

Lecture 19 - Inheritance

Topics: Inheritance: hierarchies, subclasses, using inherited methods, examples

We start with reviewing the basics of a class and objects. Getter and setter methods. Data attributes, code style, some examples.

Going over hierarchies and implementing in code, which is just using sub-classes. Overriding parent methods. Class variables are shared between all instances of a class.

Most of this was review for me.

Lecture 20 - Fitness Tracker OOP Example

Topics: Inheritance: more examples

Reinforcing same concept as previous lectures but with a more involved example. I learned something new. You can get the class state by doing something like this: SimpleWorkout.__dict__.keys() You can do the same on an instance variable.

Most of this was review for me, again. I have no problem with that :)

Object Oriented Design: More Art than Science

  • OOP is a powerful tool for modularizing your code and grouping state and functions together
  • BUT
  • It is possible to overdo it (aka over-engineering)
    • New OOP programmers often create elaborate class hierarchies
    • Not necessarily a good idea
    • Think about the users of your code
      • Will your decomposition make sense to them?
    • Because the function that is invoked is implicit in the class hierarchy, it can sometimes be difficult to reason about control flow

Intro to CS: Lecture 21 - Timing Programs, Counting Operations

Topics: Complexity: measuring efficiency, timing programs, counting operations

Efficiency is important.

  • Separate time and space efficiency of a program
  • Tradeoff between them: can use a bit more memory to store values for quicker lookup later
    • Think fibonacci recursive vs. fibonacci with memoization
  • Challenges in understanding efficiency
    • A program can be implemented in many different ways
    • You can solve a problem using only a handful of different algorithms
  • Want to separate choice of implementation from choice of more abstract algorithm

Introduced to python's time module, which will help time programs.

Timing programs is inconsistent. So we count operations as an attempt to get a more consistent evaluation.

Lecture 22 - Big Oh and Theta

Topics: Complexity: Big-Oh notation, Big-Theta notation, complexity relations and classes, calc-complexity

Getting introduced to the python time.perf_counter() function. This is new to me. I guess its a more accurate version of time.time(). We compare the runtime of a few different functions. The plots of input size vs. runtime turn out to be linear, logarithmic, and quadratic.

Timing is a critical tool to assess the performance of programs. But we will see another complementary tool (asymptotic complexity) that has other advantages. A.k.a. Big Oh notation. Express runtime as an order-of instead of exact growth. Focus on the largest factors in runtime.

Lecture 23 - Complexity Classes Examples

Topics: String and List Examples, Analyzing Complexity, Search: indirection, linear search, bisection search

This lecture we are looking at more code and analyzing their complexities. Be careful what the inputs are and whether or not they contribute to the complexity.

Went over a bunch of examples, it was a good practice/review at analyzing a piece of code's time complexity.

Side note: I'm surprised they didn't go over the set data structure in Python in this course so far.

Lecture 24 - Sorting Algorithms

Topics: Sort: bogo, bubble, selection, merge sort

Linear search vs. Binary search on a sorted list.

Going through examples.

Lecture 25 - Plotting

Topics: Visualization Library

Plots help us visualize data. I sped through the video because it didn't seem useful to me. I don't see myself using the plot library anytime soon. And if I do, I'll just read the documentation and examples on stack overflow or something to get what I need, as-needed.

Lecture 26 (Final Lecture) - List Access, Hashing, Simulations, and Wrap-Up

Topics: Extras: lists in memory, hashing, simulations, wrap-up

Looking at lists, and how they're actually implemented in memory. Looking at dictionaries, and how they are implemented in memory using hash tables.

Going over simulations.

Simulations

Topic useful for many domains

  • Computationally describe the world using randomness
  • One very important topic relative to many fields of study
    • Risk modeling and analysis
    • Reduce complex models

Idea:

  • Observe an event and want to calculate something about it
  • Using computation, design an experiment of that event
  • Repeat the experiment k many times (make a simulation)
  • Keep track of the outcome of your event
  • After k repetitions, report the value of interest

Wrap Up - What did we learn

  • Python syntax
  • Flow of control
    • Loops, branching, exceptions
  • Data structures
    • Tuples, lists, dictionaries
  • Organization, decomposition, abstraction
    • Functions
    • Classes
  • Algorithms
    • Binary/bisection
  • Computational complexity
    • Big theta notation
    • Searching and sorting

My experience was that I was a "natural" mostly because I already have a lot of experience with programming.

What's next

  • 6100B - overview of interesting topics in CS and data science (Python)
    • Optimization problems
    • Simulations
    • Experimental data
    • Machine learning
  • 6.101 - fundamentals of programming (Python)
    • Implementing efficient algorithms
    • Debugging
    • Problem sets are hardcore, lot of debugging
    • Sets data structure will be covered here
  • 6.102 - software construction (typescript)
    • Writing code that is safe from bugs, easy to understand, ready for change
  • Other classes (ML, Algorithms, etc.)

I can't find these courses on MIT OCW, and since I'm not an MIT student, I can't take these courses. It's fine. I'm following the curriculum for OSSU so I have a next course to take.

The instructor states: It's easy to forget without practice ! She recommends to practice at least once a week. It doesn't need to be a lot, just 30 min once a week is fine.

I liked the problem sets, I feel like they were great practice for me.

That's a wrap for this class ! Next up, I'm going to write a review of this course and maybe upload a YouTube video about it.