A small program
The file runs from the top
A Python file is executed from the first line to the last. def main stores a function. The function runs when the last lines call it, which they do when you run this file as a program.
def main() -> None:
print("The python holds still.")
if __name__ == "__main__":
main()
What to notice. __name__ is "__main__" when this file is the program you started. The same file can later be imported, and then those last lines skip the call. The programs on this page are Python 3.
Try itAn f-string fills a placeholder
print writes a line. An f before the opening quote makes braces into placeholders. The name inside the braces is filled in when the line runs.
coils = 12
print(f"Coils: {coils}")
What to notice. The braces are not printed. {coils} is replaced by the value 12. Without the f, the braces would be ordinary characters.
Try itA project is a directory
A small program can be one file. A project is a directory around it. pyproject.toml names the project. hello.py holds the program you run.
# serpens-field/
# ├── pyproject.toml
# └── hello.py
print("python hello.py")
What to notice. pyproject.toml is the manifest. hello.py is the script. Comments with # are not executed.
This site does not run Python. Try it opens the program that would live in hello.py. On your own machine, python hello.py runs that file.
Try itSyntax
A name can be rebound
A name refers to an object. Writing the name again points it at a new object. There is no separate mark that allows the change. The old object stays as it was.
bolts = 4
coats = 1
coats += 1
print(f"{bolts} bolts, {coats} coats")
What to notice. coats += 1 is coats = coats + 1. The name coats moves from 1 to 2. bolts still refers to 4.
Try itA few types, and a hint
int is a whole number. bool is True or False. str is text, written with quotes. A colon and a type after a name is an annotation. The program runs without checking it.
piers: int = 2
awake: bool = True
mark: str = "S"
name: str = "Serpens"
print(piers, awake, mark, name)
What to notice. The four values are an int, a bool, and two strings. Python has no separate one-character type. The annotations are for a reader, and for a type checker you run on purpose.
Try itreturn hands a value back
def names a function. The parameters sit in the parentheses. The arrow and a type are an annotation for the returned value. return is what actually hands that value back. A function with no return hands back None.
def span(piers: int) -> int:
return piers * 6
print(span(2))
What to notice. return piers * 6 leaves the function with 12. The annotation -> int describes that number. It is not the return itself.
Try itif and for
if runs an indented block when the condition is true. for walks a sequence. range(1, 3) yields 1 and then 2. The end value is not included.
length = 3
if length > 2:
print("coil")
for segment in range(1, 3):
print(f"segment {segment}")
What to notice. The block is the indent, not braces. The condition has no parentheses. range(1, 3) stops before 3. range(1, 3) is two steps.
Try itData
A class bundles data and methods
class starts a new type. __init__ runs when you call the type, and self is the new object. A method's first parameter is that object. snake.label() passes snake in as self.
class Snake:
def __init__(self, meters: int) -> None:
self.meters = meters
def label(self) -> str:
return f"{self.meters}m"
snake = Snake(12)
print(snake.label())
What to notice. self.meters stores 12 on the object. label reads that attribute and builds the text 12m.
Try itmatch picks a case
match compares a value with a series of cases. The first case that fits runs. A value that fits none of them falls through. The language does not require a case for every possible string.
def report(coat: str) -> str:
match coat:
case "sound":
return "sound"
case "shed":
return "shed"
return "other"
print(report("shed"))
What to notice. case "shed" matches the argument, so report returns shed. return "other" runs only when no case matched.
Try itA list can grow. A str is replaced.
A list is an ordered collection. append adds an item to that same list. A str cannot grow in place. title += "s" points the name at a new string.
names = ["north", "south"]
names.append("center")
title = "span"
title += "s"
print(len(names), title)
What to notice. append changes the list object. += on a string rebinds the name. len counts the items in the list, which is now three.
Try itThe Python idea
Assignment adds a name
moved = name does not copy the characters and does not take the object away from name. Both names refer to the same object. is is true when two names refer to one object.
name = "Serpens"
moved = name
print(f"{moved} {name is moved}")
What to notice. After the assignment, name and moved are two ways to reach one string. The first name still works.
Try itA function can change the object you passed
The parameter scales is another name for the list in the caller. append changes that list. When the function returns, the caller sees the new item, because there was only one list.
def add_scale(scales: list[int]) -> None:
scales.append(1)
scales = [1, 2]
add_scale(scales)
print(len(scales))
What to notice. The call does not copy the list. len is 3 because append changed the object the caller still names.
Try itNone and an exception
int(text) builds an integer from digits. A string that is not an integer raises ValueError. try runs the conversion. except runs when that error is raised, and this function returns None to say there was no number.
def meters_from(text: str) -> int | None:
try:
return int(text)
except ValueError:
return None
print(meters_from("12"))
What to notice. "12" converts to the integer 12, so the except block does not run. None is a real object. It is how this function reports that the text was not a number.
Try it