A heterogeneous list

The list in the following program contains four items, of data types str, int, float, and list. This demonstrates that a list can contain a list.

We saw a triple-quoted string here. For the underscores in the 59_500_000.00 in line 15, see Floating point literals. The $ in line 20 is a plain old dollar sign for money. The ,.2f means “print the float with commas, and two digits to the right of the decimal point”.

heterogeneous.py

Name: Dr. No
Year: 1962
Box office: $59,500,000.00
Starring: Sean Connery, Ursula Andress, Joseph Wiseman, Jack Lord

Things to try

    >
  1. The list easier to read if we split it onto two lines:
    movie = ["Dr. No", 1962, 59_500_000.00,
        ["Sean Connery", "Ursula Andress", "Joseph Wiseman", "Jack Lord"]
    ]
    
    More spread out, for legibility and comments:
    movie = ["Dr. No", 1962, 59_500_000.00,
        [
            "Sean Connery",   #James Bond
            "Ursula Andress", #Honey Ryder
            "Joseph Wiseman", #Dr. No
            "Jack Lord"       #Felix Leiter
        ]
    ]
    
    Even more spread out:
    movie = [
        "Dr. No",             #title
        1962,                 #year
        59_500_000.00,        #box office
        [
            "Sean Connery",   #James Bond
            "Ursula Andress", #Honey Ryder
            "Joseph Wiseman", #Dr. No
            "Jack Lord"       #Felix Leiter
        ]
    ]
    
  2. Take the values out of the format pockets.
    #This format string contains 4 lines and 3 pockets.
    
    f = """\
    Name: {}
    Year: {}
    Box office: ${:,.2f}
    Starring:"""
    
    print(f.format(movie[0], movie[1], movie[2]))
    
    The above call to print can now be abbreviated to
    print(f.format(*movie[:3]))
    
  3. Instead of one movie, make a list of five movies. Now we have rows and columns of data.
    movies = [
        ["Dr. No",                1962,  59_500_000.00, ["Sean Connery", "Ursula Andress", "Joseph Wiseman", "Jack Lord"]],
        ["From Russia With Love", 1963,  79_000_000.00, ["Sean Connery", "Pedro Armendáriz", "Lotte Lenya", "Robert Shaw", "Bernard Lee", "Daniela Bianchi"]],
        ["Goldfinger",            1964, 125_000_000.00, ["Sean Connery", "Honor Blackman", "Gert Fröbe"]],
        ["Thunderball",           1965, 141_200_000.00, ["Sean Connery", "Claudine Auger", "Adolfo Celi", "Luciana Paluzzi", "Rik Van Nutter"]],
        ["Casino Royale",         1967,  41_700_000.00, ["Peter Sellers", "Ursula Andress", "David Niven", "Woody Allen", "Joanna Pettet", "Orson Welles", "Daliah Lavi"]]
    ]
    
    Would it be easier to read like this?
    movies = [
        ["Dr. No",                1962,  59_500_000.00,
            ["Sean Connery", "Ursula Andress", "Joseph Wiseman", "Jack Lord"]
        ],
    
        ["From Russia With Love", 1963,  79_000_000.00,
            ["Sean Connery", "Pedro Armendáriz", "Lotte Lenya", "Robert Shaw", "Bernard Lee", "Daniela Bianchi"]
        ],
    
        ["Goldfinger",            1964, 125_000_000.00,
            ["Sean Connery", "Honor Blackman", "Gert Fröbe"]
        ],
    
        ["Thunderball",           1965, 141_200_000.00,
            ["Sean Connery", "Claudine Auger", "Adolfo Celi", "Luciana Paluzzi", "Rik Van Nutter"]
        ],
    
        ["Casino Royale",         1967,  41_700_000.00,
            ["Peter Sellers", "Ursula Andress", "David Niven", "Woody Allen", "Joanna Pettet", "Orson Welles", "Daliah Lavi"]
        ]
    ]
    
    Or like this?
    movies = [
        ["Dr. No",                1962,  59_500_000.00,
            [
                "Sean Connery",
                "Ursula Andress",
                "Joseph Wiseman",
                "Jack Lord"
            ]
        ],
    
        ["From Russia With Love", 1963,  79_000_000.00,
            [
                "Sean Connery",
                "Pedro Armendáriz",
                "Lotte Lenya",
                "Robert Shaw",
                "Bernard Lee",
                "Daniela Bianchi"
            ]
        ],
    
        ["Goldfinger",            1964, 125_000_000.00,
            [
                "Sean Connery",
                "Honor Blackman",
                "Gert Fröbe"
            ]
        ],
    
        ["Thunderball",           1965, 141_200_000.00,
            [
                "Sean Connery",
                "Claudine Auger",
                "Adolfo Celi",
                "Luciana Paluzzi",
                "Rik Van Nutter"
            ]
        ],
    
        ["Casino Royale",         1967,  41_700_000.00,
            [
                "Peter Sellers",
                "Ursula Andress",
                "David Niven",
                "Woody Allen",
                "Joanna Pettet",
                "Orson Welles",
                "Daliah Lavi"
            ]
        ]
    ]
    
    Now that we have a list of movies, change the rest of the program to
    for movie in movies:
        print(f.format(movie[0], movie[1], movie[2]))
        stars = movie[3]
    
        for star in stars[:-1]: #all but the last
            print(star, end = ", ")
    
        print(stars[-1])        #the last star
        print()
    
    Name: Dr. No
    Year: 1962
    Box office: $59,500,000.00
    Starring:
    Sean Connery, Ursula Andress, Joseph Wiseman, Jack Lord
    
    Name: From Russia With Love
    Year: 1963
    Box office: $79,000,000.00
    Starring:
    Sean Connery, Pedro Armendáriz, Lotte Lenya, Robert Shaw, Bernard Lee, Daniela Bianchi
    
    Name: Goldfinger
    Year: 1964
    Box office: $125,000,000.00
    Starring:
    Sean Connery, Honor Blackman, Gert Fröbe
    
    Name: Thunderball
    Year: 1965
    Box office: $141,200,000.00
    Starring:
    Sean Connery, Claudine Auger, Adolfo Celi, Luciana Paluzzi, Rik Van Nutter
    
    Name: Casino Royale
    Year: 1967
    Box office: $41,700,000.00
    Starring:
    Peter Sellers, Ursula Andress, David Niven, Woody Allen, Joanna Pettet, Orson Welles, Daliah Lavi
    
  4. Print the box office total too.
    total = 0.00
    
    for movie in movies:
        total += movie[2]   #means total = total + movie[2]
        print(f.format(movie[0], movie[1], movie[2]))
        stars = movie[3]
    
        for star in stars[:-1]:
            print(star, end = ", ")
    
        print(stars[-1])
        print()
    
    print(f"Total box office: ${total:,.2f}")
    
    Total box office: $446,400,000.00
    
    You could also compute the total like this:
    print(f"${sum([movie[2] for movie in movies]):,.2f}")
    
  5. """
    ZodiacSign.py
    
    Find your zodiac sign.  Select your birth month and day from tkinter menus.
    """
    
    import sys
    import datetime
    import tkinter
    
    monthNames = [
        None,
        "January",
        "February",
        "March",
        "April",
        "May",
        "June",
        "July",
        "August",
        "September",
        "October",
        "November",
        "December"
    ]
    
    signs = [
         [ 1, 19, "Capricorn"],
         [ 2, 18, "Aquarius"],
         [ 3, 20, "Pisces"],
         [ 4, 19, "Aries"],
         [ 5, 20, "Taurus"],
         [ 6, 20, "Gemini"],
         [ 7, 22, "Cancer"],
         [ 8, 22, "Leo"],
         [ 9, 22, "Virgo"],
         [10, 22, "Libra"],
         [11, 21, "Scorpio"],
         [12, 21, "Sagittarius"],
         [12, 31, "Capricorn"]
    ]
    
    root = tkinter.Tk()
    root.title("Find your Zodiac Sign.")
    
    #Labels:
    
    monthLabel = tkinter.Label(text = "What is your birth month?", anchor = "w", padx = 5)
    monthLabel.grid(row = 0, column = 0)
    
    dayLabel = tkinter.Label(text = "What is your birth day?", anchor = "w", padx = 5)
    dayLabel.grid(row = 1, column = 0, sticky = "ew")   #east west
    
    signLabel = tkinter.Label(anchor = "w", padx = 5)
    signLabel.grid(row = 2, column = 1, sticky = "ew")
    
    #Variables:
    
    month = tkinter.StringVar(root)
    month.set(monthNames[1])   #default value
    
    day = tkinter.IntVar(root)
    day.set(1)   #default value
    
    #Menus:
    
    def erase(monthName):
        signLabel["text"] = ""
    
    monthMenu = tkinter.OptionMenu(root, month, *monthNames[1:], command = erase)
    monthMenu.grid(row = 0, column = 1, sticky = "ew")
    
    dayMenu = tkinter.OptionMenu(root, day, *range(1, 32), command = erase)
    dayMenu.grid(row = 1, column = 1, sticky = "ew")
    
    #Button:
    
    def buttonPressed():
        monthName = month.get()
        monthNumber = monthNames.index(monthName)
        year = 2000   #Pick a year that has  february 29.
        birthday = datetime.datetime(year, monthNumber, day.get())
    
        for sign in signs:
            if birthday <= datetime.datetime(year, sign[0], sign[1]):
                break
    
        signLabel["text"] = sign[2]
    
    button = tkinter.Button(root, text = "Press this button.",
        anchor = "w", padx = 5, command = buttonPressed)
    button.grid(row = 2, column = 0, sticky = "we")
    
    tkinter.mainloop()
    
    Remove monthNames and replace it by calendar.month_name. (You’ll have to import calendar.) calendar.month_name is almost the same as a list, but at one point you’ll have to turn it into a list explicitly:
        monthNumber = list(calendar.month_name).index(monthName)