Introduction to Programming
# Introduction to programming
_Written by Luke Chang_
There are lots of free useful resources to learn how to use python and various modules. See [Jeremy Manning's](https://github.com/ContextLab/cs-for-psych) or [Yaroslav Halchenko's](https://github.com/dartmouth-pbs/psyc161) excellent Dartmouth courses. [Codeacademy](https://www.codecademy.com/) is a great interactive tutorial. [Stack Overflow](http://stackoverflow.com/) is an incredibly useful resource for asking specific questions and seeing responses to others that have been rated by the development community.
Marimo Notebooks¶
We will primarily be using marimo notebooks to interface with Python. A marimo notebook is a reactive Python notebook stored as a plain .py file — no JSON, no out-of-order-execution traps, and clean diffs in git.
A marimo notebook consists of cells. Unlike Jupyter, there is only one cell type — every cell is Python. Prose is written by calling mo.md(r"...") (using a triple-quoted raw string for multi-line markdown) and letting the cell evaluate to that markdown object, like this very cell.
Reactive execution¶
The biggest conceptual difference from Jupyter is reactivity. marimo statically analyzes which variables each cell defines and reads, and builds a dataflow graph from that. When you change a cell, every cell that depends on it re-runs automatically — there is no "I forgot to re-run cell 4" problem, and the notebook's state always matches the code on screen.
A consequence of this design: every variable name must be defined in at most one cell. If you want to reuse a name (e.g., x) for a quick experiment, prefix it with an underscore (_x) to make it cell-local.
Running and editing cells¶
- Run a cell:
Ctrl/⌘ + Enter(or click the run button in the cell's gutter). - Add a cell: click the
+button that appears between cells, or useCtrl/⌘ + Shift + Enterto run the current cell and add a new one below. - Render markdown, plots, or UI: whatever the cell's last expression evaluates to is what gets displayed —
mo.md(...)for prose,plt.gcf()for a matplotlib figure, a DataFrame for a table,mo.ui.slider(...)for an interactive control. - Hide cell code: click the eye icon in the gutter. Code stays in the file; only the output is shown. The prose cells in this notebook all have their code hidden.
Launching marimo¶
From the project root:
Hello World
Installing Python with uv (Recommended)¶
uv is a fast, modern Python package manager that handles both installing Python itself and managing project dependencies.
Install uv¶
macOS / Linux:
Windows:
Set up the DartBrains project¶
# Clone the repository
git clone https://github.com/ljchang/dartbrains.git
cd dartbrains
# Install Python and all dependencies (this one command does everything)
uv sync
# Open a notebook
uv run marimo edit content/Introduction_to_Programming.py
uv sync reads the pyproject.toml file and automatically installs the correct Python version (3.13) and all required packages. No need to manually install Python or create virtual environments — uv handles it all.
Running Python with uv¶
To run any Python script or command with the project's dependencies available:
Installing Python with Conda (Legacy)¶
If you prefer using Conda for package management, the following instructions still work.
Package Management¶
marimo has a built-in package manager that works seamlessly with uv. When you import a module that isn't installed, marimo detects it, prompts you to install it, and pins the dependency in the project's pyproject.toml — so the environment stays reproducible across machines and the next person who clones the repo just runs uv sync.
You'll see comments like this near package-using cells:
# packages added via marimo's package management: pandas, numpy
import pandas as pd
import numpy as np
That comment is auto-managed by marimo — you don't need to write it yourself.
Installing additional packages¶
The cleanest way is to just import what you want and let marimo prompt you. If you'd rather pre-install from a terminal, use uv directly:
uv add scikit-learn # add a runtime dependency
uv add --dev pytest # add a dev-only dependency
uv sync # sync the environment to pyproject.toml
Getting help on a package manager¶
For one-off ad-hoc installs into the current environment (without modifying pyproject.toml), pip still works — but for project work, prefer uv add so the dependency is tracked.
Package Version Latest Type ----------------- -------------- ------------ ----- attrs 23.2.0 26.1.0 wheel Automat 22.10.0 25.4.16 wheel Babel 2.10.3 2.18.0 wheel bcrypt 3.2.2 5.0.0 wheel blinker 1.7.0 1.9.0 wheel boto3 1.34.46 1.42.97 wheel botocore 1.34.46 1.42.97 wheel certifi 2023.11.17 2026.4.22 wheel chardet 5.2.0 7.4.3 wheel click 8.1.6 8.3.3 wheel configobj 5.0.8 5.0.9 wheel cryptography 41.0.7 47.0.0 wheel dbus-python 1.3.2 1.4.0 sdist httplib2 0.20.4 0.31.2 wheel idna 3.6 3.13 wheel incremental 22.10.0 24.11.0 wheel Jinja2 3.1.2 3.1.6 wheel jmespath 1.0.1 1.1.0 wheel jsonpatch 1.32 1.33 wheel jsonpointer 2.0 3.1.1 wheel jsonschema 4.10.3 4.26.0 wheel launchpadlib 1.11.0 2.1.0 wheel lazr.uri 1.0.6 1.0.8 wheel markdown-it-py 3.0.0 4.0.0 wheel MarkupSafe 2.1.5 3.0.3 wheel mercurial 6.7.2 7.2.1 wheel netaddr 0.8.0 1.3.0 wheel oauthlib 3.2.2 3.3.1 wheel packaging 24.0 26.2 wheel pip 24.0 26.1 wheel pyasn1 0.4.8 0.6.3 wheel pyasn1-modules 0.2.8 0.4.2 wheel Pygments 2.17.2 2.20.0 wheel PyGObject 3.48.2 3.56.2 sdist PyJWT 2.7.0 2.12.1 wheel pyOpenSSL 23.2.0 26.1.0 wheel pyparsing 3.1.1 3.3.2 wheel pyparted 3.12.0 3.13.0 sdist python-dateutil 2.8.2 2.9.0.post0 wheel python-debian 0.1.49+ubuntu2 1.1.0 wheel pytz 2024.1 2026.1.post1 wheel PyYAML 6.0.1 6.0.3 wheel requests 2.31.0 2.33.1 wheel rich 13.7.1 15.0.0 wheel s3transfer 0.10.1 0.16.1 wheel service-identity 24.1.0 24.2.0 wheel setuptools 68.1.2 82.0.1 wheel six 1.16.0 1.17.0 wheel ssh-import-id 5.11 5.13 wheel Twisted 24.3.0 25.5.0 wheel typing_extensions 4.10.0 4.15.0 wheel urllib3 2.0.7 2.6.3 wheel wadllib 1.3.6 2.0.0 wheel wheel 0.42.0 0.47.0 wheel zope.interface 6.1 8.4 wheel zstandard 0.22.0 0.25.0 wheel
0
Variables¶
Python is a dynamically typed language, which means that you can easily change the datatype associated with a variable. There are several built-in datatypes that are good to be aware of.
- Built-in
- Numeric types:
- int, float, long, complex
- String: str
- Boolean: bool
- True / False
- NoneType
-
User defined
-
Use the type() function to find the type for a value or variable
-
Data can be converted using cast commands
# Integer
a = 1
print(type(a))
# Float
b = 1.0
print(type(b))
# String
c = 'hello'
print(type(c))
# Boolean
d = True
print(type(d))
# None
e = None
print(type(e))
# Cast integer to string
print(type(str(a)))
<class 'int'> <class 'float'> <class 'str'> <class 'bool'> <class 'NoneType'> <class 'str'>
Math Operators¶
- +, -, *, and /
- Exponentiation **
-
Modulo %
-
Note that division with integers in Python 2.7 automatically rounds, which may not be intended. It is recommended to import the division module from python3
from __future__ import division
# Addition
a_1 = 2 + 7
print(a_1)
b_1 = a_1 - 5
# Subtraction
print(b_1)
print(b_1 * 2)
print(b_1 ** 2)
# Multiplication
print(4 % 9)
# Exponentiation
# Modulo
# Division
print(4 / 9)
9 4 8 16 4 0.4444444444444444
String Operators¶
- Some of the arithmetic operators also have meaning for strings. E.g. for string concatenation use
+sign - String repetition: Use
*sign with a number of repetitions
HelloWorld HelloHelloHelloHelloHello
Logical Operators¶
Perform logical comparison and return Boolean value
x == y # x is equal to y
x != y # x is not equal to y
x > y # x is greater than y
x < y # x is less than y
x >= y # x is greater than or equal to y
x <= y # x is less than or equal to y
| X | not X |
|---|---|
| True | False |
| False | True |
| X | Y | X AND Y | X OR Y |
|---|---|---|---|
| True | True | True | True |
| True | False | False | True |
| False | True | False | True |
| False | False | False | False |
# Works for string
a_3 = 'hello'
b_3 = 'world'
c_1 = 'Hello'
print(a_3 == b_3)
print(a_3 == c_1)
print(a_3 != b_3)
d_1 = 5
# Works for numeric
e_1 = 8
print(d_1 < e_1)
False False True True
Conditional Logic (if...)¶
Unlike most other languages, Python uses tab formatting rather than closing conditional statements (e.g., end).
- Syntax:
- Implicit conversion of the value to bool() happens if
conditionis of a different type than bool, thus all of the following should work:
if condition:
do_something
elif condition:
do_alternative1
else:
do_otherwise # often reserved to report an error
# after a long list of options
n = 1
if n:
print("n is non-0")
if n is None:
print("n is None")
if n is not None:
print("n is not None")
n is non-0 n is not None
Loops¶
- for loop is probably the most popular loop construct in Python:
- However, it's also possible to use a while loop to repeat statements while
conditionremains True:
P y t h o n i s g o i n g t o m a k e c o n d u c t i n g r e s e a r c h e a s i e r
x = 0
end = 10
csum = 0
while x < end:
csum = csum + x
print(x, csum)
x = x + 1
print(f'Exited with x=={x}')
0 0 1 1 2 3 3 6 4 10 5 15 6 21 7 28 8 36 9 45 Exited with x==10
Functions¶
A function is a named sequence of statements that performs a computation. You define the function by giving it a name, specify a sequence of statements, and optionally values to return. Later, you can “call” the function by name.
* The expression in the parenthesis is the argument. * It is common to say that a function “takes” an argument and “returns” a result. * The result is called the return value.The first line of the function definition is called the header; the rest is called the body.
The header has to end with a colon and the body has to be indented. It is a common practice to use 4 spaces for indentation, and to avoid mixing with tabs.
Function body in Python ends whenever statement begins at the original level of indentation. There is no end or fed or any other identify to signal the end of function. Indentation is part of the the language syntax in Python, making it more readable and less cluttered.
def make_upper_case(text):
return text.upper()
string_1 = 'Python is going to make conducting research easier'
print(make_upper_case(string_1))
PYTHON IS GOING TO MAKE CONDUCTING RESEARCH EASIER
Python Containers¶
There are 4 main types of builtin containers for storing data in Python: * list * tuple * dict * set
Lists¶
In Python, a list is a mutable sequence of values. Mutable means that we can change separate entries within a list. For a more in depth tutorial on lists look here
- Each value in the list is an element or item
- Elements can be any Python data type
-
Lists can mix data types
-
Lists are initialized with
* Elements within a list are indexed (starting with 0)[]orlist()
* Elements can be nested lists
* Lists can be sliced.
- Like all python containers, lists have many useful methods that can be applied
* List comprehension is a Very powerful technique allowing for efficient construction of new lists.
# Indexing and Slicing
a_4 = ['lists', 'are', 'arrays']
print(a_4[0])
print(a_4[1:3])
a_4.insert(2, 'python')
# List methods
a_4.append('.')
print(a_4)
print(len(a_4))
# List Comprehension
print([x.upper() for x in a_4])
lists ['are', 'arrays'] ['lists', 'are', 'python', 'arrays', '.'] 5 ['LISTS', 'ARE', 'PYTHON', 'ARRAYS', '.']
Dictionaries¶
-
In Python, a dictionary (or
dict) is mapping between a set of indices (keys) and a set of values -
The items in a dictionary are key-value pairs
-
Keys can be any Python data type
-
Dictionaries are unordered
-
Here is a more indepth tutorial on dictionaries
# Dictionaries
eng2sp = {}
eng2sp['one'] = 'uno'
print(eng2sp)
eng2sp = {'one': 'uno', 'two': 'dos', 'three': 'tres'}
print(eng2sp)
print(eng2sp.keys())
print(eng2sp.values())
{'one': 'uno'}
{'one': 'uno', 'two': 'dos', 'three': 'tres'}
dict_keys(['one', 'two', 'three'])
dict_values(['uno', 'dos', 'tres'])
Tuples¶
In Python, a tuple is an immutable sequence of values, meaning they can't be changed
-
Each value in the tuple is an element or item
-
Elements can be any Python data type
-
Tuples can mix data types
-
Elements can be nested tuples
-
Essentially tuples are immutable lists
Here is a nice tutorial on tuples
(1, 2, 3, 4) (1, 2)
sets¶
In Python, a set is an efficient storage for "membership" checking
-
setis like adictbut only with keys and without values -
a
setcan also perform set operations (e.g., union intersection) -
Here is more info on sets
# Union
print({1, 2, 3, 'mom', 'dad'} | {2, 3, 10})
# Intersection
print({1, 2, 3, 'mom', 'dad'} & {2, 3, 10})
# Difference
print({1, 2, 3, 'mom', 'dad'} - {2, 3, 10})
{1, 2, 3, 10, 'mom', 'dad'}
{2, 3}
{1, 'mom', 'dad'}
Modules¶
A Module is a python file that contains a collection of related definitions. Python has hundreds of standard modules. These are organized into what is known as the Python Standard Library. You can also create and use your own modules. To use functionality from a module, you first have to import the entire module or parts of it into your namespace
- To import the entire module, use
- You can also import a module using a specific name
- To import specific definitions (e.g. functions, variables, etc) from the module into your local namespace, use
namespace
Here let's try and get the path of the current working directory using functions from the os module
'/home/runner/work/dartbrains/dartbrains'
It looks like we are currently in the notebooks folder of the github repository. Let's use glob, a pattern matching function, to list all of the csv files in the Data folder.
[]
This gives us a list of the files including the relative path from the current directory. What if we wanted just the filenames? There are several different ways to do this. First, we can use the the os.path.basename function. We loop over every file, grab the base file name and then append it to a new list.
[]
Alternatively, we could loop over all files and split on the / character. This will create a new list where each element is whatever characters are separated by the splitting character. We can then take the last element of each list.
file_list_1 = []
for f_1 in data_file_list:
file_list_1.append(f_1.split('/')[-1])
print(file_list_1)
[]
It is also sometimes even cleaner to do this as a list comprehension
Exercises¶
Find Even Numbers¶
Let’s say I give you a list saved in a variable: a = [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]. Make a new list that has only the even elements of this list in it.
Find Maximal Range¶
Given an array length 1 or more of ints, return the difference between the largest and smallest values in the array.
Duplicated Numbers¶
Find the numbers in list a that are also in list b
a = [0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361]
b = [0, 4, 16, 36, 64, 100, 144, 196, 256, 324]
Speeding Ticket Fine¶
You are driving a little too fast on the highway, and a police officer stops you. Write a function that takes the speed as an input and returns the fine.
If speed is 60 or less, the result is $0. If speed is between 61 and 80 inclusive, the result is $100. If speed is 81 or more, the result is $500.