import json
# Why the import is nesscary
# Without import json, the name json isn't defined, and you'll get a NameError the
# moment you call json.dump , etc.
#Modular design Python keeps functionality organized in modules
from data classes import dataclass, asdict
from typing import List, Optional
#-- Data Label --
@dataclass
class Actor:
name: str
medium: str
role: str
start_year: int
end_year Optional[int] = None #None if ongoing or single year
#-- Seed Data -- Well known Superman Portrayals
def seed_actors() -> List[Actor]:
return [
Actor(" Kirk Alyn", "Serial", "Superman", 1948, 1950),
Actor( "George Reeves", "TV", "Superman", 1952, 1958),
Actor(" Chrisopher Reeve", "Film", "Superman", 1978, 1987),
Actor("Dean Cain", "TV", "Superman", 1993, 1997),
Actor("Tom Welling", "TV", "Clark Kent", 2001, 2011),
Actor("Brandon Routh", "Film", "Superman", 2006, 2006),
Actor("Henry Cavill", "Film", "Superman", 2013, 2022),
Actor("Tyler Hoechlin", "TV", "Superman", 2016, None),
]
#Core functions
def add_actor (actors: List[Actor], actor: Actor) -> None:
"""Append a new to the list"""
actors.append(actor)
def list_all(actors: List[Actor]) -> None:
print("\nAll Superman Actors:")
for idx, a in enumerate(actors):
span = f"{a.start_year}-{a.end_year or 'present'}"
print(f" {idx:>2}: {a.name} ({a.medium}, {a.role}, {span})")
def filter_by_medium(actors: List[Actor], medium: str) -> List[Actor]:
return[a for a in actors if a.medium.lower() == medium.lower()]
def filter_by_year_range(actors: List[Actor], start: int, end: int) -> [Actor]:
"""Return actors active in any part of [start, end]."""
result = []
for a in actors:
a_end = a.end_year or 9999
if not (a_end < start or a.start_year > end):
result.append(a)
return result
def find_by_name(actors: List[Actor], name_query: str) -> List[Actor]:
nq = name_query.lower()
return[a for a in actors if nq in a.name.lower()]
#-- pop() helpers ---
def pop_last_actor(actors: List[Actor]) -> Optional[Actor]:
""" Removes and returns the last actor, returns none if the list is empty"""
if not actors:
return None
return actors.pop() #Same as actors.pop(-1)
def pop_actor_at(actors: List[Actor], index: int) -> Tuple[bool, Optional[Actor],
Optional[str]]:
try:
removed = actors.pop(index)
return True, removed, None
except IndexError:
return False, None, f"Index {index} is out of range (0... {len(actors) -1})."
# -- Persistence(optional) ----
def save_to_json(actors: List[Actor],path: str) -> None:
payload = [asdict(a) for a in actors]
with open(path, "w", encoding= "utf-8") as f:
json.dump(payload, f, indent=2, ensure_ascii=False)
def load_from_json(path: str) -> List[Actor]:
with open(path, "r", encoding="utf-8") as f:
raw = json.load(f)
return [Actor(**item) for item in raw]
#Demo / CLI
def main():
actors - seed_actors()
# Show initial list
list_all(actors)
#Ex: Append a new actor
print("\nAppending a new actor entry...")
new_actor = Actor(
name= "David Cornswet",
medium="Film",
role="Superman"
start_year=2025, #Adjust if needed
end_year=None
)
add_actor(actors, new_actor)
list_all(actors)
#pop() - remove the last actor
print("\nPopping the last actor...")
removed = pop_last_actor(actors)
if removed:
print(f"Removed: {removed.name}")
else:
print("No actor to remove (list is empty).")
list_all(actors)
#pop() - remove at a specific index
print("\nPopping actor at index 2....")
To embed this project on your website, copy the following code and paste it into your website's HTML: