Ludium
Sign In
Introduction to Computer Science using Python
Computation & Python Basics
01Algorithms as Recipes02The Six Operations Behind Every Program03Primitives, Syntax, and Semantics04Objects, Types, and Type Casting05Expressions, Operators, and Types06Assignment vs. EqualityProblem set0/10Practice∞
01Objects, Names, and Assignment02String Concatenation, Repetition, and len()03String Indexing and Slicing04String Immutability and the print() Function05User Input, Type Conversion, and f-strings06Comparisons, Booleans, and Logical Operators07Conditionals: if, elif, and elseProblem set0/10Practice∞
Control Flow & Iteration
01Conditional Branching: if, elif, and else02Iteration and the While Loop03While Loops, Counters, and Infinite Loops04While Loop Variables and Running Products05The for Loop and range()06The Accumulator Pattern and range()Problem set0/10MIT problem set0/2Practice∞
01The break Statement: Exiting a Loop Early02Looping Over Strings and the in Operator03Guess-and-Check: Exhaustive Enumeration04for Loops, Boolean Flags, and Cube Roots05Nested Loops and Brute-Force Search06Floats, Binary, and Floating-Point ErrorProblem set0/10Practice∞
Numbers & Algorithms
01Converting Integers to Binary (and Negatives)02Why 0.1 Can't Be Stored: Fractions in Binary03How Floats Are Stored, and Why You Never Use ==04Successive Approximation and the Loop That Never EndsProblem set0/10Practice∞
01Why Approximation Search Hits a Wall02Halving the Search Space at Every Step03Coding Bisection Search for Square Roots04Fixing Bisection Search for Numbers Below One05Newton-Raphson: Sliding Down the Tangent LineProblem set0/10MIT problem set0/1Practice∞
Functions & Abstraction
01Abstraction and Decomposition: Why Your Phone Is a Black Box02What a Function Really Is: The Specification and Its Four Parts03Writing Your First Function: From a Sentence to is_even04How a Function Call Becomes Its Value: Parameters vs. Arguments05Return vs. Print: The Mysterious None, and Functions in Real Code06Building sum_odds: Plan on Paper, Then Catch the Off-by-One BugProblem set0/10Practice∞
Scope & Higher-Order Functions
01return vs. print, and the Hidden None That Reveals a Bug02Turning Bisection Square Root Into a Reusable Function03Environments and Scope: The Rule Behind UnboundLocalError04A Function Is an Object: Naming, Passing, and Tracing Calls05Higher-Order Functions: Building apply(criteria, n)Problem set0/10Practice∞
Lambdas & Sequences
01Writing Anonymous Functions With Lambda02Tracing Nested Calls with the Environment Model03Tuples: An Ordered, Mixed-Type Sequence04Why Tuples Are Immutable: Nesting and Iteration05Tuple Unpacking: One-Line Swaps and Many Returns06The Star (*args), Lists, and Pythonic LoopsProblem set0/10MIT problem set0/3Practice∞
Mutating Lists
01Lists Mutate, Tuples Don't: The Name vs the Object02append: Growing a List and the None Trap03Dot Notation: Building and Filtering Lists04split and join: Converting Between Strings and Lists05sort vs. sorted: Mutate in Place or Return a New List06Writing Functions That Mutate a List In Place07Appending While Looping, and extend vs append08Reassignment vs Mutation, Proven with id()Problem set0/10MIT problem set0/1Practice∞
Aliases & Copies
01Cloning with L[:]: Mutating a List In Place02del, pop, and remove: Three Ways to Delete03The Loop That Skips: Removing While Iterating04Aliases vs Clones: Why L2 = L1 Is Not a Copy05Shallow vs Deep Copy: copy.copy and copy.deepcopyProblem set0/10Practice∞
Comprehensions, Testing & Debugging
01List Comprehensions: Your Build-a-List Loop in One Line02Reading Any Comprehension: Iterable, Expression, Condition03Default Parameters: Defaults Last, Keywords at the Call Site04Returning a Function Object: return g, Not return g()05Catching a Returned Function: Two Names, One Object06Unit, Regression, and Integration Testing07Black Box vs Glass Box: Where Test Cases Come From08Debugging by Bisection: Print Statements as EvidenceProblem set0/10Practice∞
Exceptions & Assertions
01try and except: Catching an Exception Instead of Crashing02Named Exception Handlers, else, finally, and raise03raise ValueError and assert: Enforcing Your Docstring04One Empty List, Four Designs: Crash, None, Default, AssertProblem set0/10Practice∞
Dictionaries
01Why Lists Fail at Lookup: Parallel Lists and Nested Search02Dictionaries: Custom Keys, Curly Braces, and KeyError03Mutating a Dictionary: Add, Overwrite, del, and in04keys(), values(), items(): Three Windows Into a Dictionary05Hashing and Immutable Keys: Why a List Can't Be a Key06Case Study: Building a Word Frequency Dictionary07Ranking Words by Deleting Them: The Cost of MutationProblem set0/10MIT problem set0/8Practice∞
Recursion
01Multiplying With Only Addition: From Loops to a Smaller Copy02Writing mult_recur: Base Case, Recursive Step, and the Call Stack03Divide and Conquer: The Regrade Chain and Writing power_recur04Recursive Factorial Acted Out: Environments and When to RecurseProblem set0/10Practice∞
01fib_recur: Two Recursive Calls and an Exploding Call Tree02Memoization: One Dictionary Cuts 11 Million Calls to 6503Counting Basketball Scores: Three Base Cases, Three Branches04Recursion on Lists: Peel One Element, Trust the Rest05Debugging a Recursive Search: Print, Fix, and Return Types06Nested Lists: Flatten, Search, and Why Loops Fall Short07Reversing a List Recursively: The Brackets That Make It Legal08deep_rev: One Type Test Reverses Every LayerProblem set0/10MIT problem set0/3Practice∞
Classes & Objects
01Class vs Instance: The Blueprint Behind Every Object02Choosing Data and Behavior: Elevators, Employees, and Stacks03class Coordinate(object): Implementing a Type vs Using It04The __init__ Constructor: Why Every Method Starts With self05Creating Instances: Coordinate(3, 4), Dot Notation, and Memory06Methods and the Dot Operator: distance, and How self Gets BoundProblem set0/10MIT problem set0/3Practice∞
Composition & Dunder Methods
01Data Attributes vs Parameter Names: What self Guarantees02Returning a Value vs Mutating the Object: Writing to_origin03Composition and ValueError: A Circle Made of Coordinate Objects04Before the Dot Becomes self: Writing a SimpleFraction Class05Every Operator Is a Method: Meet Python's Dunder Names06The __str__ Method: You Decide What print Shows07Overloading * and float() for a Fraction Class08Inside reduce: a Nested gcd and the Branch That Returns an intProblem set0/10Practice∞
Inheritance
01Data and Procedural Attributes: Building the Animal Class02Getters, Setters and __str__: Why the Method Outlives the Attribute03Attribute Abuse From Outside, and a Dictionary of Animal Objects04make_animals: Walking Two Lists in Step to Build a List of Objects05Hierarchies and Subclasses: The Three Moves a Subclass Can Make06class Cat(Animal): Inheriting __init__ and the Chain Python Climbs07Overriding __init__: Person Calls Animal.__init__ By Name08Student, a Subclass of a Subclass, and the Rabbit Class Variable09__add__ and __eq__ on Rabbits: Operator Overloading With Shared IDsProblem set0/10MIT problem set0/5Practice∞
An Object-Oriented Case Study
01Designing a Workout Class: __init__ Makes Five Attributes From Three02Two State Dictionaries: __dict__ on the Class and on the Object03A Getter That Estimates: Class Variables, None, and datetime04parser.parse and Where a Class Variable Actually Lives05class RunWorkout(Workout): Inheritance and super().__init__06One __str__ in the Parent, Three Kinds of Workout Printing07A Subclass Where Its Parent Goes, and Positional Argument Order08Overriding get_calories: How Python Picks Which Method Runs09__eq__ With super(), and the Last Word on Building ClassesProblem set0/10MIT problem set0/4Practice∞
Program Efficiency
01Correct Isn't Fast: time.time() and Three Functions Built to Be Measured02Timing Nine Input Sizes, and Four Reasons the Seconds Measure the Machine03One Unit per Operation: Costing Three Functions by Hand, Then in Code04Ten Times the Input, a Hundred Times the Work: Reading Operation CountsProblem set0/10Practice∞
01A Finer Clock: time.perf_counter and a Runtime That Never Moves02Which Parameter Costs Time? compound, sum_of, and One Linear Shape03Brute Force, Bisection, or in: Timing Three Searches to 100 Million04A Loop Inside a Loop: the diameter Function and Quadratic Growth05Counting Operations: Exact Formulas and a Program That Counts Itself06Order of Growth: What to Measure, Which Input, and the Worst Case07Big O: An Upper Bound That Only Has to Hold Past the Crossover08Big Theta: Bounded From Both Sides, Keep Only the Dominant Term09Reading Theta Off the Loops: Two Laws and Six Complexity ClassesProblem set0/10Practice∞

Student, a Subclass of a Subclass, and the Rabbit Class Variable

How can the single line `Person.__init__(self, name, age)` set up the entire person part of a student, and what kind of variable hands every rabbit a unique ID?


Finger exercises

Short drills on what this video just taught. Write the code, run the checks, and reveal the answer only if you are stuck.

0 / 5 passed
  1. Write Student, whose parent is Person. Creating one takes three things — a name, an age, and a major that is None when it is not supplied — so Student cannot reuse the two-parameter initializer it inherits and has to write its own. Build the whole person part of a student with a single call to the parent's initializer, made by class name, then add the one data attribute a student has that a person does not: major.

    Then create a student named 'alice', aged 20, majoring in "CS", and assign it to student.

    Given code — runs before yours
    class Animal(object):
        """ An animal with an age and a name """
    
        def __init__(self, age):
            self.age = age
            self.name = None
    
        def get_age(self):
            return self.age
    
        def get_name(self):
            return self.name
    
        def set_age(self, newage):
            self.age = newage
    
        def set_name(self, newname=""):
            self.name = newname
    
        def __str__(self):
            return "animal:" + str(self.name) + ":" + str(self.age)
    
    class Person(Animal):
        """ An animal with a name from the start and a list of friends """
    
        def __init__(self, name, age):
            Animal.__init__(self, age)
            self.set_name(name)
            self.friends = []
    
        def get_friends(self):
            return self.friends
    
        def add_friend(self, fname):
            if fname not in self.friends:
                self.friends.append(fname)
    
        def speak(self):
            print("hello")
    
        def __str__(self):
            return "person:" + str(self.name) + ":" + str(self.age)
    1
    2
    3
    4
    5
    6
    7
    # A student is a person, plus one thing of its own.
    class Student(Person):
        ...  # your code here — the initializer
    
    student = ...  # your code here
    
    Python runs in your browser
    ⌘/Ctrl + Enter runs
    ?
    Student is a subclass of Person that writes its own __init__
    ?
    is a Student carrying the name and age it was built with
    ?
    stores the major as a data attribute of its own
    ?
    the person part came from one call to the parent
    ?
    the major falls back to its default when it is left out
←Previous Overriding __init__: Person Calls Animal.__init__ By NameNext __add__ and __eq__ on Rabbits: Operator Overloading With Shared IDs →

Your summary note

    1. 1

      A subclass built through two levels of parents

      Write class Student(Person) taking name, age and major=None, and record that the single line Person.__init__(self, name, age) builds the age, the name and the friends list, leaving self.major as the addition.

    2. 2

      The randomized speak override

      Record Student.speak drawing random.random() from the random library and branching on four quarters between 0 and 1, with __str__ overridden again to print student:name:age:major.

    3. 3

      Class variables as a shared resource

      Rank plain variables, instance variables and class variables, write tag = 1 directly in the class body outside any method, and state that one instance's change is visible to every other instance.

    4. 4

      The Rabbit.tag counter trace

      Write self.rid = Rabbit.tag followed by Rabbit.tag += 1 at the end of __init__, then trace Rabbit(8), Rabbit(6) and Rabbit(10) to rids 1, 2 and 3 with tag left at 4.

    Attempt 1 of 2