PDA·02 · Chapter 2
Python Basics, IPython & Jupyter
Chapter 2 — the interpreter, notebooks, and the core of the language
The book's crash course in the Python you need before NumPy and pandas: how to run code, why notebooks, how names and objects really work, the basic types, and control flow. If you've done Python Crash Course, sessions 2.3 and 2.4 are where the new ideas are.
The Python Interpreter
Concept
- Python is an interpreted language: the interpreter runs your program one statement at a time.
- Type
pythonin a terminal for the standard prompt (>>>); typeexit()or press Ctrl-D (Ctrl-Z then Enter on Windows) to leave. - Run a whole file with
python hello_world.py. Inside IPython,%run hello_world.pydoes the same and keeps its variables afterwards so you can inspect them. - Data analysts mostly live in IPython or Jupyter rather than the plain prompt — they add history, completion and rich output.
Key Terms
- Interpreter
- the program that reads and runs Python code
- >>>
- the standard Python prompt
- %run
- IPython command that runs a script in the current session
Worked example
# hello_world.py
print("Hello world") $ python hello_world.py
Hello world Exercise
Write hello_world.py, run it from a terminal, then run it again with %run inside IPython and check the variables it made still exist.
Open the plain python prompt and IPython side by side. Type the same three lines in each and list two things IPython does better.
IPython and Jupyter Basics
Concept
- IPython prints the result of the last expression in a cell automatically, numbered
Out[n]to matchIn[n]— noprint()needed. - A Jupyter notebook is a document of cells; the kernel behind it keeps every variable alive between cells until you restart it.
- Tab completion: type part of a name, or
obj., and press Tab to see matching variables, methods and even file paths. - Introspection:
obj?shows the type, value and docstring;func??also shows the source code.np.*load*?searches names with wildcards. - Cells run in the order you run them, not the order they appear — the numbers in
In[n]tell you the real history. Restart and run all before trusting a notebook.
Key Terms
- Kernel
- the Python process behind a notebook that keeps its state
- Out[n]
- the auto-displayed value of cell n's last expression
- obj? / obj??
- show docs / show docs and source
- Magic command
- an IPython command starting with %, such as %run or %timeit
Exercise
Run the cells below one at a time and predict each Out before you press Run. Which cell surprised you, and why?
Press Restart kernel, then run only cell 4. Explain the error you would get in a real notebook.
In a real notebook, try print?, then type pd.read_ and press Tab. How many read_ functions are there?
Language Semantics
Concept
- Python uses indentation, not braces, to group code — four spaces is the convention. A colon ends the line before an indented block.
- Everything is an object: numbers, strings, lists, functions and modules all carry a type and live in memory as their own thing.
- Assignment makes a reference, not a copy: after
b = a, both names point at the same list, so changing it through one is visible through the other. Function arguments are passed the same way. - Types are dynamic (a name can point at anything) but strong:
"5" + 5raises TypeError instead of guessing. Check types withisinstance(x, (int, float)). - Duck typing: care what an object can do, not what it is — "if it walks like a duck…". A function that accepts any iterable is more useful than one that demands a list.
istests identity (same object);==tests equality (same value). Lists and dicts are mutable; strings and tuples are immutable.
Key Terms
- Reference
- a name bound to an object; several names can share one object
- Strongly typed
- no silent conversion between unrelated types
- Duck typing
- judging an object by its behaviour, not its declared type
- is vs ==
- same object vs. equal value
- Mutable
- can be changed in place after it is created
Worked example
def append_element(some_list, element):
some_list.append(element)
data = [1, 2, 3]
append_element(data, 4) # the function changes the caller's list
print(data)
a = [1, 2, 3]
c = list(a) # a new list with the same values
print(a == c, a is c) [1, 2, 3, 4]
True False Exercise
Write a function that takes a list and doubles every value in place. Show that the caller's list changed, then write a second version that returns a new list instead.
Write isiterable(obj) using try: iter(obj) — return True or False. Test it on a string, a list, and the number 5.
Scalar Types
Concept
intcan hold arbitrarily large numbers;floatis double precision./always gives a float (3 / 2is1.5);//is floor division.- First-edition trap: in Python 2 (what my old copy used)
3 / 2was1. If an old example gives odd numbers, check its division. stris an immutable sequence of Unicode characters — you can slice it but not assign into it. f-strings format values:f"{amount:.2f} {currency}".bytesare raw encoded data;.encode("utf-8")turns a string into bytes and.decode("utf-8")turns them back.boolisTrue/False(withand,or,not);Noneis the "no value" value — functions without areturngiveNone.- The
datetimemodule givesdate,timeanddatetime.strftimeformats a date into text;strptimeparses text into a date.
Key Terms
- / vs //
- true division (float) vs. floor division
- f-string
- a string literal prefixed with f that formats {expressions} inside it
- encode / decode
- str to bytes / bytes to str, using an encoding like UTF-8
- None
- the single null value in Python
- strftime / strptime
- datetime to string / string to datetime
Worked example
from datetime import datetime
print(3 / 2, 3 // 2)
amount = 4.5560
print(f"{amount:.2f} Thai baht")
dt = datetime(2011, 10, 29, 20, 30, 21)
print(dt.strftime("%Y-%m-%d %H:%M"))
print(datetime.strptime("20091031", "%Y%m%d"))
print(dt - datetime(2011, 10, 1)) 1.5 1
4.56 Thai baht
2011-10-29 20:30
2009-10-31 00:00:00
28 days, 20:30:21 Exercise
Store your birthday as a datetime and print how many days old you are, using datetime.now() and subtraction.
Encode "สวัสดี" to UTF-8 bytes and print how many bytes it takes compared with its len() as a string. Why are they different?
Control Flow
Concept
if/elif/elsechecks conditions in order and runs only the first true branch.and/orshort-circuit: the right side is skipped if the left decides the answer.for x in collection:loops over any iterable.continueskips to the next item;breakleaves the innermost loop.whilerepeats until its condition becomes false — make sure something inside changes it.passis the "do nothing" statement, a placeholder for code you haven't written yet.range(start, stop, step)produces evenly spaced integers lazily, stopping beforestop. Later chapters replace most of these loops with array operations.
Key Terms
- Short-circuit
- stop evaluating a boolean expression once the result is known
- continue / break
- skip to the next iteration / exit the loop
- pass
- a statement that does nothing
- range()
- a lazy sequence of integers
Worked example
total = 0
for i in range(100_000):
# sum the multiples of 3 or 5
if i % 3 == 0 or i % 5 == 0:
total += i
print(total)
sequence = [1, 2, None, 4, None, 5]
total = 0
for value in sequence:
if value is None:
continue
total += value
print(total) 2333316668
12 Exercise
Loop over [1, 2, 0, 4, 6, 5, 2, 1] and add values up until you reach a 5, then stop. What is the total?
Rewrite the multiples-of-3-or-5 loop using sum() and a generator expression on one line. Check you get the same answer.