text
for p in soup.find_all("p"): # loop through every paragraph
print(p.string)
```
---
template: modules
## Built-in vs. add-on, side by side
These two slides together show the typical web-input workflow: **fetch, then parse**.
--
- **`urllib.request`** is **built-in** — it ships with Python, just `import` it
--
- **`BeautifulSoup`** (`bs4`) is an **add-on** — it must be installed first (e.g. with `pip`) before you can import it
--
Together they turn a live web page into usable input for your program.
---
name: program-structure
# Program Structure
---
template: program-structure
## Putting it all together
The concepts above combine into a clean, conventional way to structure a program:
--
- write the program's logic as **small functions**, each doing one job
- have a **`main()`** function that runs the program by **calling those other functions**
- use the **[`__name__` guard](#name-guard)** to call `main()` only when the file is run directly
---
template: program-structure
## A well-structured program
```python
def get_name():
return input("What's your name? ")
def build_greeting(name):
return "Hello, " + name + "!"
def main():
name = get_name() # call a helper function
greeting = build_greeting(name) # call another helper function
print(greeting)
if __name__ == "__main__":
main()
```
--
`main()` orchestrates the program; the helper functions do the detailed work.
---
template: program-structure
## Splitting work across files
Helper functions are often defined in **other files**, which act as [modules](#modules)
you `import` — keeping each file focused and its functions reusable.
```python
# greetings.py — a module of reusable functions
def build_greeting(name):
return "Hello, " + name + "!"
```
```python
# main.py — the program that uses the module
import greetings
def main():
print(greetings.build_greeting("Watson"))
if __name__ == "__main__":
main()
```
---
template: program-structure
## Why structure programs this way?
- **Readable** — `main()` reads like a high-level summary of what the program does
--
- **Reusable** — functions (and whole modules) can be imported and reused elsewhere
--
- **Testable** — small functions with return values are easy to test individually
--
- **Safe to import** — the `__name__` guard means importing a file loads its
functions without accidentally running the whole program
---
class: center, middle
# Good luck on the exam!
Review the linked Notes for full details and examples.