You're storing a point (x, y) that shouldn't change. A list could be accidentally modified. A tuple is immutable - once created, it's fixed. Perfect for coordinates, RGB colors, and returning multiple values from functions.

Store coordinates

Create a tuple for a point in 2D space.

coordinates.py
Replay: real traced execution (multi-file project)
def main():
    # Coordinates as tuples (x, y)
    origin = (0, 0)
    home = (10, 25)
    office = (50, 30)
    store = (35, 15)

    print("=== Location Coordinates ===")
    print(f"Home: {home}")
    print(f"Office: {office}")
    print(f"Store: {store}")

    # Access individual values
    home_x = home[0]
    home_y = home[1]
    print(f"\nHome is at x={home_x}, y={home_y}")

    # 3D coordinates
    point_3d = (10, 20, 30)
    print(f"\n3D Point: {point_3d}")
    x, y, z = point_3d
    print(f"x={x}, y={y}, z={z}")

    # Calculate distance from origin
    import math
    def distance_from_origin(point):
        return math.sqrt(point[0]**2 + point[1]**2)

    print("\n=== Distance from Origin ===")
    locations = [("Home", home), ("Office", office), ("Store", store)]
    for name, coord in locations:
        dist = distance_from_origin(coord)
        print(f"{name}: {dist:.2f} units")

main()
  1. main()

    36main()37#@help tuple
  2. origin ← (0, 0), home ← (10, 25), office ← (50, 30), store ← (35, 15)

    1#@var=default,3d2def main():3    # Coordinates as tuples (x, y)  #?tuple4    origin→ (0, 0) = (0, 0)5    home→ (10, 25) = (10, 25)6    office→ (50, 30) = (50, 30)7    store→ (35, 15) = (35, 15)8    9    print("=== Location Coordinates ===")10    print(f"Home: {home(10, 25)}")11    print(f"Office: {office(50, 30)}")12    print(f"Store: {store(35, 15)}")13    14    # Access individual values15    home_x→ 10 = home[0]10  #?access16    home_y→ 25 = home[1]2517    print(f"\nHome is at x={home_x10}, y={home_y25}")18    19    # 3D coordinates  #@var=_,!20    point_3d→ (10, 20, 30) = (10, 20, 30)  #@var=_,!21    print(f"\n3D Point: {point_3d(10, 20, 30)}")  #@var=_,!22    x→ 10, y→ 20, z→ 30 = point_3d(10, 20, 30)  #@var=_,!23    print(f"x={x10}, y={y20}, z={z30}")  #@var=_,!24    25    # Calculate distance from origin26    import math27    def distance_from_origin(point):28        return math.sqrt(point[0]**2 + point[1]**2)29    30    print("\n=== Distance from Origin ===")31    locations→ [('Home', (10, 25)), ('Office', (50, 30)), ('Store', (35, 15))] = [("Home", home(10, 25)), ("Office", office(50, 30)), ("Store", store(35, 15))]32    for name, coord in locations:
    output=== Location Coordinates ===
    Home: (10, 25)
    Office: (50, 30)
    Store: (35, 15)
    
    Home is at x=10, y=25
    
    3D Point: (10, 20, 30)
    x=10, y=20, z=30
    
    === Distance from Origin ===
  3. for name, coord in locations:

    pass 1 of 3
    31locations = [("Home", home), ("Office", office), ("Store", store)]32for nameHome, coord(10, 25) in locations[('Home', (10, 25)), ('Office', (50, 30)), ('Store', (35, 15))]:33    dist = distance_from_origin(coord(10, 25))34    print(f"{name}: {dist:.2f} units")
    All 3 passes — pass 1 is the card above
    passnamecoord
    1Home(10, 25)
    2Office(50, 30)
    3Store(35, 15)
  4. def distance_from_origin(point):

    pass 1 of 3
    26import math27def distance_from_origin(point(10, 25)):28    return math<module 'math' from '/usr/local/lib/python3.12/lib-dynload/math.cpython-312-x86_64-linux-gnu.so'>.sqrt(point[0]10**2 + point[1]25**2)
    All 3 passes — pass 1 is the card above
    passpointpoint[0]point[1]
    1(10, 25)1025
    2(50, 30)5030
    3(35, 15)3515
  5. dist ← 26.92582403567252

    32for name, coord in locations:33    dist→ 26.92582403567252 = distance_from_origin(coord(10, 25))34    print(f"{nameHome}: {dist26.92582403567252:.2f} units")
    outputHome: 26.93 units
  6. dist ← 58.309518948453004

    32for name, coord in locations:33    dist→ 58.309518948453004 = distance_from_origin(coord(50, 30))34    print(f"{nameOffice}: {dist58.309518948453004:.2f} units")
    outputOffice: 58.31 units
  7. dist ← 38.07886552931954

    32for name, coord in locations:33    dist→ 38.07886552931954 = distance_from_origin(coord(35, 15))34    print(f"{nameStore}: {dist38.07886552931954:.2f} units")
    outputStore: 38.08 units
  8. main()

    36main()37#@help tuple

Tuples use parentheses: (x, y). Access by index like lists.

tuple Immutable sequence: `(1, 2, 3)`. Cannot be modified after creation.

Represent RGB colors

Store color components as a fixed triplet.

rgb_color.py
Replay: real traced execution (multi-file project)
def main():
    # RGB colors as tuples (red, green, blue)
    # Each value: 0-255
    red = (255, 0, 0)
    green = (0, 255, 0)
    blue = (0, 0, 255)
    white = (255, 255, 255)
    black = (0, 0, 0)
    orange = (255, 165, 0)

    print("=== RGB Color Palette ===")
    colors = {
        "Red": red,
        "Green": green,
        "Blue": blue,
        "White": white,
        "Black": black,
        "Orange": orange
    }

    for name, rgb in colors.items():
        print(f"{name}: RGB{rgb}")

    # Color mixing (additive)
    print("\n=== Color Analysis ===")
    target_color = orange
    r, g, b = target_color

    print(f"Orange = RGB{target_color}")
    print(f"  Red component:   {r}")
    print(f"  Green component: {g}")
    print(f"  Blue component:  {b}")

    # Brightness (simple average)
    brightness = (r + g + b) / 3
    print(f"  Brightness: {brightness:.1f}/255")

    # RGBA with alpha channel
    transparent_red = (255, 0, 0, 128)
    r, g, b, a = transparent_red
    print(f"\nRGBA with alpha: {transparent_red}")
    print(f"  Opacity: {a/255*100:.0f}%")

main()
  1. main()

    45main()46#@help rgb
  2. red ← (255, 0, 0), green ← (0, 255, 0), blue ← (0, 0, 255), white ← (255, 255, 255)

    1#@var=default,alpha2def main():3    # RGB colors as tuples (red, green, blue)  #?rgb4    # Each value: 0-2555    red→ (255, 0, 0) = (255, 0, 0)6    green→ (0, 255, 0) = (0, 255, 0)7    blue→ (0, 0, 255) = (0, 0, 255)8    white→ (255, 255, 255) = (255, 255, 255)9    black→ (0, 0, 0) = (0, 0, 0)10    orange→ (255, 165, 0) = (255, 165, 0)11    12    print("=== RGB Color Palette ===")13    colors→ {'Red': (255, 0, 0), 'Green': (0, 255, 0), 'Blue': (0, 0, 255), 'White': (255, 255, 255), 'Black': (0, 0, 0), 'Orange': (255, 165, 0)} = {14        "Red": red(255, 0, 0),15        "Green": green(0, 255, 0),16        "Blue": blue(0, 0, 255),17        "White": white(255, 255, 255),18        "Black": black(0, 0, 0),19        "Orange": orange(255, 165, 0)20    }
    output=== RGB Color Palette ===
  3. for name, rgb in colors.items():

    pass 1 of 6
    22for nameRed, rgb(255, 0, 0) in colors{'Red': (255, 0, 0), 'Green': (0, 255, 0), 'Blue': (0, 0, 255), 'White': (255, 255, 255), 'Black': (0, 0, 0), 'Orange': (255, 165, 0)}.items():23    print(f"{nameRed}: RGB{rgb(255, 0, 0)}")
    outputRed: RGB(255, 0, 0)
    All 6 passes — pass 1 is the card above
    passnamergb
    1Red(255, 0, 0)
    2Green(0, 255, 0)
    3Blue(0, 0, 255)
    4White(255, 255, 255)
    5Black(0, 0, 0)
    6Orange(255, 165, 0)
  4. target_color ← (255, 165, 0), r ← 255, g ← 165, b ← 0, brightness ← 140.0

    25# Color mixing (additive)26print("\n=== Color Analysis ===")27target_color→ (255, 165, 0) = orange(255, 165, 0)28r→ 255, g→ 165, b→ 0 = target_color(255, 165, 0)  #?unpack2930print(f"Orange = RGB{target_color(255, 165, 0)}")31print(f"  Red component:   {r255}")32print(f"  Green component: {g165}")33print(f"  Blue component:  {b0}")3435# Brightness (simple average)36brightness→ 140.0 = (r255 + g165 + b0) / 337print(f"  Brightness: {brightness140.0:.1f}/255")3839# RGBA with alpha channel  #@var=_,!40transparent_red→ (255, 0, 0, 128) = (255, 0, 0, 128)  #@var=_,!41r→ 255, g→ 0, b→ 0, a→ 128 = transparent_red(255, 0, 0, 128)  #@var=_,!42print(f"\nRGBA with alpha: {transparent_red(255, 0, 0, 128)}")  #@var=_,!43print(f"  Opacity: {a128/255*100:.0f}%")  #@var=_,!
    output
    === Color Analysis ===
    Orange = RGB(255, 165, 0)
      Red component:   255
      Green component: 165
      Blue component:  0
      Brightness: 140.0/255
    
    RGBA with alpha: (255, 0, 0, 128)
      Opacity: 50%
  5. main()

    45main()46#@help rgb

(red, green, blue) with values 0-255. Immutability prevents accidental changes.

Unpack tuple values

Assign tuple elements to individual variables.

unpacking.py
Replay: real traced execution (multi-file project)
def main():
    # Basic tuple unpacking
    coordinates = (100, 250)
    x, y = coordinates

    print("=== Basic Unpacking ===")
    print(f"Tuple: {coordinates}")
    print(f"x = {x}, y = {y}")

    # Unpacking in loop
    print("\n=== Unpacking in Loops ===")
    points = [(0, 0), (10, 20), (30, 40), (50, 60)]

    for x, y in points:
        distance = (x**2 + y**2) ** 0.5
        print(f"Point ({x}, {y}) is {distance:.2f} from origin")

    # Swap variables using unpacking
    print("\n=== Variable Swap ===")
    a, b = 5, 10
    print(f"Before: a={a}, b={b}")
    a, b = b, a
    print(f"After:  a={a}, b={b}")

    # Extended unpacking with * (Python 3+)
    numbers = (1, 2, 3, 4, 5, 6, 7)
    first, *middle, last = numbers
    print("\n=== Extended Unpacking ===")
    print(f"Numbers: {numbers}")
    print(f"First: {first}")
    print(f"Middle: {middle}")
    print(f"Last: {last}")

    # Ignore values with _
    print("\n=== Ignoring Values ===")
    data = ("John", "Doe", 30, "Engineer", "NYC")
    first_name, last_name, _, job, _ = data
    print(f"{first_name} {last_name} works as {job}")

main()
  1. main()

    41main()42#@help unpack
  2. coordinates ← (100, 250), x ← 100, y ← 250, points ← [(0, 0), (10, 20), (30, 40), (50, 60)]

    1#@var=default,extended2def main():3    # Basic tuple unpacking  #?unpack4    coordinates→ (100, 250) = (100, 250)5    x→ 100, y→ 250 = coordinates(100, 250)6    7    print("=== Basic Unpacking ===")8    print(f"Tuple: {coordinates(100, 250)}")9    print(f"x = {x100}, y = {y250}")10    11    # Unpacking in loop12    print("\n=== Unpacking in Loops ===")13    points→ [(0, 0), (10, 20), (30, 40), (50, 60)] = [(0, 0), (10, 20), (30, 40), (50, 60)]
    output=== Basic Unpacking ===
    Tuple: (100, 250)
    x = 100, y = 250
    
    === Unpacking in Loops ===
  3. distance ← 0.0

    pass 1 of 4
    15for x0, y0 in points[(0, 0), (10, 20), (30, 40), (50, 60)]:  #?loopunpack16    distance→ 0.0 = (x0**2 + y0**2) ** 0.517    print(f"Point ({x0}, {y0}) is {distance0.0:.2f} from origin")
    outputPoint (0, 0) is 0.00 from origin
    All 4 passes — pass 1 is the card above
    passxydistance
    1000.0
    2102022.360679774997898
    3304050.0
    4506078.10249675906654
  4. a ← 5, b ← 10, numbers ← (1, 2, 3, 4, 5, 6, 7), first ← 1, middle ← [2, 3, 4, 5, 6]

    19# Swap variables using unpacking20print("\n=== Variable Swap ===")21a→ 5, b→ 10 = 5, 1022print(f"Before: a={a5}, b={b10}")23a→ 10, b→ 5 = b, a  #?swap24print(f"After:  a={a10}, b={b5}")2526# Extended unpacking with * (Python 3+)  #?star27numbers→ (1, 2, 3, 4, 5, 6, 7) = (1, 2, 3, 4, 5, 6, 7)28first→ 1, *middle→ [2, 3, 4, 5, 6], last→ 7 = numbers(1, 2, 3, 4, 5, 6, 7)  #@var=_,!29print("\n=== Extended Unpacking ===")  #@var=_,!30print(f"Numbers: {numbers(1, 2, 3, 4, 5, 6, 7)}")  #@var=_,!31print(f"First: {first1}")  #@var=_,!32print(f"Middle: {middle[2, 3, 4, 5, 6]}")  #@var=_,!33print(f"Last: {last7}")  #@var=_,!3435# Ignore values with _36print("\n=== Ignoring Values ===")37data→ ('John', 'Doe', 30, 'Engineer', 'NYC') = ("John", "Doe", 30, "Engineer", "NYC")38first_name→ John, last_name→ Doe, _→ NYC, job→ Engineer, _ = data('John', 'Doe', 30, 'Engineer', 'NYC')  #?ignore39print(f"{first_nameJohn} {last_nameDoe} works as {jobEngineer}")
    output
    === Variable Swap ===
    Before: a=5, b=10
    After:  a=10, b=5
    
    === Extended Unpacking ===
    Numbers: (1, 2, 3, 4, 5, 6, 7)
    First: 1
    Middle: [2, 3, 4, 5, 6]
    Last: 7
    
    === Ignoring Values ===
    John Doe works as Engineer
  5. main()

    41main()42#@help unpack

x, y = point extracts values. Number of variables must match tuple length.

unpacking Extract values: `a, b, c = tuple`. Also works with `*rest` for variable length.

Return multiple values

Functions can return tuples for multiple return values.

return_multiple.py
Replay: real traced execution (multi-file project)
def main():
    # Functions can return multiple values via tuple

    def get_min_max(numbers):
        """Return both minimum and maximum in one call."""
        return min(numbers), max(numbers)  # Returns a tuple!

    scores = [85, 92, 78, 95, 88, 73, 91]

    print("=== Student Scores ===")
    print(f"Scores: {scores}")

    # Receive both values
    lowest, highest = get_min_max(scores)
    print(f"Lowest: {lowest}")
    print(f"Highest: {highest}")

    # Extended version with more statistics
    def get_stats(numbers):
        """Return comprehensive statistics."""
        total = sum(numbers)
        count = len(numbers)
        average = total / count
        minimum = min(numbers)
        maximum = max(numbers)
        return minimum, maximum, average, total, count

    low, high, avg, total, n = get_stats(scores)
    print(f"\n=== Detailed Statistics ===")
    print(f"Count: {n}")
    print(f"Sum: {total}")
    print(f"Average: {avg:.2f}")
    print(f"Range: {low} to {high}")

    # Divmod - built-in that returns tuple
    print("\n=== Built-in divmod() ===")
    total_minutes = 137
    hours, minutes = divmod(total_minutes, 60)
    print(f"{total_minutes} minutes = {hours}h {minutes}m")

    # Can also keep as tuple
    print("\n=== Keeping as Tuple ===")
    result = get_min_max(scores)  # Don't unpack
    print(f"Result tuple: {result}")
    print(f"Type: {type(result)}")

main()
  1. main()

    48main()49#@help return
  2. scores ← [85, 92, 78, 95, 88, 73, 91]

    1#@var=default,stats2def main():3    # Functions can return multiple values via tuple  #?return4    5    def get_min_max(numbers):6        """Return both minimum and maximum in one call."""7        return min(numbers), max(numbers)  # Returns a tuple!8    9    scores→ [85, 92, 78, 95, 88, 73, 91] = [85, 92, 78, 95, 88, 73, 91]10    11    print("=== Student Scores ===")12    print(f"Scores: {scores[85, 92, 78, 95, 88, 73, 91]}")13    14    # Receive both values15    lowest, highest = get_min_max(scores[85, 92, 78, 95, 88, 73, 91])  #?receive16    print(f"Lowest: {lowest}")
    output=== Student Scores ===
    Scores: [85, 92, 78, 95, 88, 73, 91]
  3. def get_min_max(numbers):

    pass 1 of 2
    5def get_min_max(numbers[85, 92, 78, 95, 88, 73, 91]):6    """Return both minimum and maximum in one call."""7    return min(numbers[85, 92, 78, 95, 88, 73, 91]), max(numbers)  # Returns a tuple!
  4. lowest ← 73, highest ← 95

    14# Receive both values15lowest→ 73, highest→ 95 = get_min_max(scores[85, 92, 78, 95, 88, 73, 91])  #?receive16print(f"Lowest: {lowest73}")17print(f"Highest: {highest95}")1819# Extended version with more statistics  #@var=_,!20def get_stats(numbers):  #@var=_,!21    """Return comprehensive statistics."""  #@var=_,!22    total = sum(numbers)  #@var=_,!23    count = len(numbers)  #@var=_,!24    average = total / count  #@var=_,!25    minimum = min(numbers)  #@var=_,!26    maximum = max(numbers)  #@var=_,!27    return minimum, maximum, average, total, count  #@var=_,!2829low, high, avg, total, n = get_stats(scores[85, 92, 78, 95, 88, 73, 91])  #@var=_,!30print(f"\n=== Detailed Statistics ===")  #@var=_,!
    outputLowest: 73
    Highest: 95
  5. total ← 602, count ← 7, average ← 86.0, minimum ← 73, maximum ← 95

    19# Extended version with more statistics  #@var=_,!20def get_stats(numbers[85, 92, 78, 95, 88, 73, 91]):  #@var=_,!21    """Return comprehensive statistics."""  #@var=_,!22    total→ 602 = sum(numbers[85, 92, 78, 95, 88, 73, 91])  #@var=_,!23    count→ 7 = len(numbers[85, 92, 78, 95, 88, 73, 91])  #@var=_,!24    average→ 86.0 = total602 / count7  #@var=_,!25    minimum→ 73 = min(numbers[85, 92, 78, 95, 88, 73, 91])  #@var=_,!26    maximum→ 95 = max(numbers[85, 92, 78, 95, 88, 73, 91])  #@var=_,!27    return minimum73, maximum95, average86.0, total602, count7  #@var=_,!
  6. low ← 73, high ← 95, avg ← 86.0, total ← 602, n ← 7, total_minutes ← 137

    29low→ 73, high→ 95, avg→ 86.0, total→ 602, n→ 7 = get_stats(scores[85, 92, 78, 95, 88, 73, 91])  #@var=_,!30print(f"\n=== Detailed Statistics ===")  #@var=_,!31print(f"Count: {n7}")  #@var=_,!32print(f"Sum: {total602}")  #@var=_,!33print(f"Average: {avg86.0:.2f}")  #@var=_,!34print(f"Range: {low73} to {high95}")  #@var=_,!3536# Divmod - built-in that returns tuple37print("\n=== Built-in divmod() ===")38total_minutes→ 137 = 13739hours→ 2, minutes→ 17 = divmod(total_minutes137, 60)  #?divmod40print(f"{total_minutes137} minutes = {hours2}h {minutes17}m")4142# Can also keep as tuple43print("\n=== Keeping as Tuple ===")44result = get_min_max(scores[85, 92, 78, 95, 88, 73, 91])  # Don't unpack45print(f"Result tuple: {result}")
    output
    === Detailed Statistics ===
    Count: 7
    Sum: 602
    Average: 86.00
    Range: 73 to 95
    
    === Built-in divmod() ===
    137 minutes = 2h 17m
    
    === Keeping as Tuple ===
  7. def get_min_max(numbers):

    pass 2 of 2
    5def get_min_max(numbers[85, 92, 78, 95, 88, 73, 91]):6    """Return both minimum and maximum in one call."""7    return min(numbers[85, 92, 78, 95, 88, 73, 91]), max(numbers)  # Returns a tuple!
  8. result ← (73, 95)

    43print("\n=== Keeping as Tuple ===")44result→ (73, 95) = get_min_max(scores[85, 92, 78, 95, 88, 73, 91])  # Don't unpack45print(f"Result tuple: {result(73, 95)}")46print(f"Type: {type(result(73, 95))}")
    outputResult tuple: (73, 95)
    Type: <class 'tuple'>
  9. main()

    48main()49#@help return

return x, y implicitly creates a tuple. Caller can unpack or use as tuple.

Named tuples for clarity

Use named tuples for self-documenting fields.

named_tuple.py
Replay: real traced execution (multi-file project)
from collections import namedtuple

def main():
    # Regular tuple - position-based access
    person_tuple = ("Alice", 30, "Engineer")
    print("=== Regular Tuple ===")
    print(f"Data: {person_tuple}")
    print(f"Name: {person_tuple[0]}")  # What is [0]? Hard to remember!
    print(f"Age: {person_tuple[1]}")

    # Named tuple - name-based access!
    Person = namedtuple('Person', ['name', 'age', 'job'])

    alice = Person("Alice", 30, "Engineer")
    bob = Person(name="Bob", age=25, job="Designer")

    print("\n=== Named Tuple ===")
    print(f"Alice: {alice}")
    print(f"Name: {alice.name}")  # Much clearer!
    print(f"Age: {alice.age}")
    print(f"Job: {alice.job}")

    # Still works with index too
    print(f"Index access still works: {alice[0]}")

    # Unpacking works
    name, age, job = bob
    print(f"\nUnpacked Bob: {name}, {age}, {job}")

    # Named tuple for coordinates
    Point = namedtuple('Point', ['x', 'y'])

    print("\n=== Points as Named Tuples ===")
    origin = Point(0, 0)
    destination = Point(100, 50)

    dx = destination.x - origin.x
    dy = destination.y - origin.y
    distance = (dx**2 + dy**2) ** 0.5

    print(f"From: {origin}")
    print(f"To: {destination}")
    print(f"Distance: {distance:.2f}")

    # Create from existing tuple
    data = (200, 300)
    point = Point._make(data)
    print(f"\nCreated from tuple: {point}")

    # Convert to dictionary
    print(f"As dict: {point._asdict()}")

main()
  1. main()

    53main()54#@help regular
  2. person_tuple ← ('Alice', 30, 'Engineer'), Person ← <class '__main__.Person'>

    3def main():4    # Regular tuple - position-based access  #?regular5    person_tuple→ ('Alice', 30, 'Engineer') = ("Alice", 30, "Engineer")6    print("=== Regular Tuple ===")7    print(f"Data: {person_tuple('Alice', 30, 'Engineer')}")8    print(f"Name: {person_tuple[0]Alice}")  # What is [0]? Hard to remember!9    print(f"Age: {person_tuple[1]30}")10    11    # Named tuple - name-based access!  #?named12    Person→ <class '__main__.Person'> = namedtuple('Person', ['name', 'age', 'job'])13    14    alice→ Person(name='Alice', age=30, job='Engineer') = Person("Alice", 30, "Engineer")15    bob→ Person(name='Bob', age=25, job='Designer') = Person(name="Bob", age=25, job="Designer")16    17    print("\n=== Named Tuple ===")18    print(f"Alice: {alicePerson(name='Alice', age=30, job='Engineer')}")19    print(f"Name: {alice.nameAlice}")  # Much clearer!20    print(f"Age: {alice.age30}")21    print(f"Job: {alice.jobEngineer}")22    23    # Still works with index too24    print(f"Index access still works: {alice[0]Alice}")25    26    # Unpacking works27    name→ Bob, age→ 25, job→ Designer = bobPerson(name='Bob', age=25, job='Designer')28    print(f"\nUnpacked Bob: {nameBob}, {age25}, {jobDesigner}")29    30    # Named tuple for coordinates31    Point→ <class '__main__.Point'> = namedtuple('Point', ['x', 'y'])32    33    print("\n=== Points as Named Tuples ===")34    origin→ Point(x=0, y=0) = Point(0, 0)35    destination→ Point(x=100, y=50) = Point(100, 50)36    37    dx→ 100 = destination.x100 - origin.x038    dy→ 50 = destination.y50 - origin.y039    distance→ 111.80339887498948 = (dx100**2 + dy50**2) ** 0.540    41    print(f"From: {originPoint(x=0, y=0)}")42    print(f"To: {destinationPoint(x=100, y=50)}")43    print(f"Distance: {distance111.80339887498948:.2f}")44    45    # Create from existing tuple46    data→ (200, 300) = (200, 300)47    point→ Point(x=200, y=300) = Point<class '__main__.Point'>._make(data(200, 300))  #?make48    print(f"\nCreated from tuple: {pointPoint(x=200, y=300)}")49    50    # Convert to dictionary51    print(f"As dict: {pointPoint(x=200, y=300)._asdict()}")
    output=== Regular Tuple ===
    Data: ('Alice', 30, 'Engineer')
    Name: Alice
    Age: 30
    
    === Named Tuple ===
    Alice: Person(name='Alice', age=30, job='Engineer')
    Name: Alice
    Age: 30
    Job: Engineer
    Index access still works: Alice
    
    Unpacked Bob: Bob, 25, Designer
    
    === Points as Named Tuples ===
    From: Point(x=0, y=0)
    To: Point(x=100, y=50)
    Distance: 111.80
    
    Created from tuple: Point(x=200, y=300)
    As dict: {'x': 200, 'y': 300}
  3. main()

    53main()54#@help regular

namedtuple gives names to positions: point.x instead of point[0].

namedtuple Tuple with named fields: `Point = namedtuple('Point', ['x', 'y'])`.

Exercise: tuple_vs_list.py

Explore when to choose tuple vs list