main.pyCourse

Python

A value and its type, then a class, then a shared list versus a copy, a method that uses self, and Decimal for money.

A cup label is three values
  1. namestrlatte
  2. centsint450
  3. readyboolTrue

6 lessons, in orderFree to read

Syllabus

Basics

The types, explained, then an object you can name and call.

  1. Every Python value has a type. name is a str, cents is an int, and ready is a bool. The program prints latte $4.50 ready, then str int bool.

    name = "latte"
    cents = 450
    ready = True
    status = "ready" if ready else "sold out"
    print(f"{name} ${cents // 100}.{cents % 100:02d} {status}")
    print(type(name).__name__, type(cents).__name__, type(ready).__name__)
    latte $4.50 ready
    str int bool
    
  2. A class groups fields and a method. Item stores a drink and a price in cents. label prints latte $4.50.

    Builds on lesson 1.

    class Item:
        def __init__(self, name, cents):
            self.name = name
            self.cents = cents
    
        def label(self):
            return f"{self.name} ${self.cents // 100}.{self.cents % 100:02d}"
    
    latte = Item("latte", 450)
    print(latte.label())
    latte $4.50
    

Practice

A rule that prevents a bug, then a program that uses the object.

  1. Assigning a list to a second name does not copy it. list() does. The program adds a muffin to the ticket and prints ['latte'] ['latte', 'muffin'].

    Builds on lessons 1 through 2.

    kitchen = ["latte"]
    ticket = list(kitchen)
    ticket.append("muffin")
    print(kitchen, ticket)
    ['latte'] ['latte', 'muffin']
    
  2. A method changes the object through self. A bill starts at 0 cents, add puts a latte on it, and the program prints 450.

    Builds on lessons 1 through 3.

    class Bill:
        def __init__(self):
            self.cents = 0
    
        def add(self, cents):
            self.cents = self.cents + cents
    
    bill = Bill()
    bill.add(450)
    print(bill.cents)
    450
    

Further

One more idea, then a program that puts the pieces together.

  1. A price is a Decimal made from a string, not a float. Three americanos at 4.10 print 12.30, and the total equals Decimal("12.30").

    Builds on lessons 1 through 4.

    from decimal import Decimal
    
    price = Decimal("4.10")
    total = price * 3
    print(total)
    print(total == Decimal("12.30"))
    12.30
    True
    
  2. A function can call label on any object that has label. Item has that method. show prints latte $4.50.

    Builds on lessons 1 through 5.

    class Item:
        def __init__(self, name, cents):
            self.name = name
            self.cents = cents
    
        def label(self):
            return f"{self.name} ${self.cents // 100}.{self.cents % 100:02d}"
    
    def show(obj):
        print(obj.label())
    
    show(Item("latte", 450))
    latte $4.50
    

Readings

Shorter pieces in the same language. Any order is fine once the lessons feel familiar.

  1. Mutable defaults: evaluated once 2 min

    GoByte Skills #9: A default argument is evaluated when def runs, not on each call, and stored on the function. So a list default is one list that every call shares. Why, the None fix, and why += is the same bug in disguise.

  2. The GIL: threads for waiting, processes for work 2 min

    GoByte Skills #8: The GIL lets one thread run Python bytecode at a time. Four threads on CPU work finish no faster than one. Four processes really run in parallel. Measured, plus why the __main__ guard is not style.

  3. Generators: a function you can pause 2 min

    GoByte Skills #7: Calling a generator function runs none of its body. Each next() resumes a frozen frame up to the next yield, so a billion values cost one frame of memory. Plus the one pass trap that fails silently.