COMP 1510: Programming Methods
Welcome to COMP 1510. This course introduces programming through Python, with a focus on systematic problem solving and writing clear, working programs. You will build from the fundamentals toward more involved problems while learning how to organize code, work with data, test your solutions, and debug when things go wrong.
This is a living coursebook and our main learning resource for the course. It provides the structure for our lectures, examples, and review, and new chapters will be added as we progress through the term. Substantive additions or revisions will be announced through Learning Hub.
Python is the language we use to learn the larger ideas of programming and problem solving.
Course Logistics
Our course shell on Learning Hub is the source of truth for announcements, labs, assessments, due dates, and grades. This coursebook contains the instructional material we will use throughout the term, while the official course outline covers course outcomes, evaluation, and policies.
Toolchain
Everything you need is free:
- The Python language itself: Python 3.14.x, from python.org.
- PyCharm, an integrated development environment for Python. Its core features are free, and eligible students can obtain additional professional features through the JetBrains Student Pack.
- Git for version control, plus a free GitHub account for accessing and submitting course repositories.
Any modern operating system is fine: Windows, macOS, or Linux. Lab 1 walks through installing and configuring all of this, step by step.
Companion Reading
- Beej’s Guide to Python Programming by Brian “Beej Jorgensen” Hall: a free, friendly, informal guide that follows along with much of this course, with exercises and chapter projects along the way. It is a work in progress, available to read online or as a PDF.
Formatting Convention
Bold introduces terms or concepts worth learning, italics add emphasis or contrast, and code formatting represents literal code, commands, programming names, or other computer text.
Credits
Special thanks to Christopher Thompson, who taught the course before the book existed, and whose support and materials shaped these pages. Thank you, Chris.
Acknowledgement
This coursebook was developed and edited by the instructor, with AI-assisted tools used during parts of the writing and revision process. All material was reviewed and verified by the instructor before publication. As the coursebook continues to evolve, minor typographical, formatting, link, or rendering issues may remain.
Image Credits
Image licences are listed in image-credits.md.
Chapters
Week 1
1 A Brief History of Programming
The laptop in front of you is, at heart, billions of tiny switches, each either on or off. That sounds nothing like writing a Python program, and closing the gap between those two worlds took two ideas. The first is old: that a machine could follow a stored set of instructions without a person guiding its every move. The second is physical: that you could build such a machine out of something that simply switches on and off. This chapter tells both stories, and shows how they collided in the 1940s to produce the machine on your desk. Class time will only sample this story; here it is in full, so skim where it overlaps with the lecture and linger where your curiosity takes you.
1.1 The Idea of a Programmable Machine
Long before electronic computers existed, people had already discovered one of the central ideas of programming: a machine’s behaviour could be controlled by instructions encoded separately from the machine itself.
In 1804, the Jacquard loom used punched cards to control the pattern of a weave automatically. Change the cards, and the same machine produced a different pattern. The loom was not a computer, but the idea behind it was remarkably familiar: instead of rebuilding the machine for every new task, change the instructions it follows.
In the nineteenth century, Charles Babbage designed the Analytical Engine, a mechanical general-purpose computer that was never completed. Ada Lovelace translated an article about it and added her own notes. In Note G she described an algorithm for computing Bernoulli numbers, making it the first published algorithm intended for a machine. She also noticed that the engine could one day compose music if the rules of harmony could be expressed as operations.
| Charles Babbage (1791–1871), designer of the Analytical Engine | Ada Lovelace (1815–1852), wrote the first published algorithm for a machine |
We may say most aptly, that the Analytical Engine weaves algebraical patterns just as the Jacquard-loom weaves flowers and leaves.
— Ada Lovelace, Note A, 1843
Lovelace saw what a machine that followed instructions could become, but no one yet had a fast, reliable way to build one. That problem starts somewhere completely different: electricity.
1.2 From Electricity to Switches
To do anything useful with electricity, we first need a way to control its flow through a wire. The switch was invented for exactly this purpose: to open and close a circuit, allowing current to pass or stopping it entirely. At first, controlling these switches was a manual task: a person flipped a lever, pressed a button, or turned a dial. Over time, we learned to control switches electronically, using one electrical signal to operate another. That step, letting electricity control itself, is the foundation of all computing.
1.3 Vacuum Tubes: The First Electronic Switches
The vacuum tube was the first practical electronic switch. Electromechanical relays, switches operated by an electrical signal, had come before it, but a vacuum tube could be turned on and off by another electrical signal with no moving parts at all. This opened the door to a wave of inventions that reshaped the twentieth century. With vacuum tubes we built radio, television, radar, sound recording and reproduction, large telephone networks, industrial process control, and, crucially for our story, the first analog and digital computers.
1.4 Analog vs. Digital
Early electronic devices worked with information in two different ways. Analog signals are translated into electrical impulses of varying amplitudes: that is, the strength of the signal carries the information, in a continuous range. A vinyl record is an analog medium: the shape of the groove varies continuously to represent the sound wave.
Digital information, by contrast, is represented using discrete values: there is no “in between”, and each piece of information is represented as one of a fixed set of values. Modern computers overwhelmingly use binary, representing those values with 0s and 1s. This distinction matters because digital representation is what makes modern computers possible. When your phone stores a photo or a song, there is no groove, no continuous physical trace. There is only a long pattern of 0s and 1s. Because the representation is discrete, copying that pattern reproduces the original exactly, without the gradual generation loss associated with analog media. Storage and communication systems can also use error-detection and correction techniques to protect that information, so the file can travel anywhere and be processed without degrading.
Modern digital computers overwhelmingly use the simplest possible code: two symbols. And that idea is much older than electronics.
1.5 Binary: The Language of Computers
Electronic digital computers use binary. Inside the hardware, a 1 and a 0 correspond to two distinguishable electrical states, such as two different voltage levels; the exact representation depends on the hardware. These 0s and 1s are known as bits, short for binary digits.
Binary itself is not a new idea. As far back as 1605, the English philosopher Francis Bacon devised a cipher in which each letter of the alphabet was represented by a sequence of five symbols drawn from a set of just two: the two typefaces of his biliteral cipher, conventionally written today as a and b, and mapped just as naturally to 0 and 1 (so aaaaa for one letter, aaaab for the next, and so on). Bacon was encoding text, not building a computer, but the underlying idea is exactly what makes digital computing work: any information can be represented using just two symbols.
Two breakthroughs are now in place: the idea of a machine that follows stored instructions, and a way to represent information with on-off switches. In the 1930s and 1940s, these two threads finally met.
1.6 A Universal Machine
In 1936, the British mathematician Alan Turing described a universal Turing machine: a theoretical device that reads symbols, follows a table of rules, and moves between states as it works. He proved that a single such machine could, in principle, compute anything that is computable. He was not building hardware; he was working out what “computation” itself means. Nearly a century after Lovelace’s notes, Turing had given the idea of a programmable machine a rigorous mathematical foundation.
A decade later, in 1945, the Hungarian-American mathematician John von Neumann helped articulate the stored-program computer architecture in the First Draft of a Report on the EDVAC. In a von Neumann machine, both the program (the instructions) and the data (the information the program works on) are stored in the same memory. This is such a fundamental idea that it can be hard to imagine computing any other way, but it was a genuine breakthrough at the time. Here the two threads of this chapter meet: the idea of a machine that follows instructions, built out of electronic switches, storing both instructions and data as 0s and 1s.
1.7 Managing Complexity
To see what the stored-program idea replaced, picture the earliest electronic computers: enormous machines, filling entire rooms and containing thousands of vacuum tubes. Configuring them to perform a task was a manual, painstaking process: technicians rewired the machine or set banks of switches by hand for each new computation. This approach did not scale.
In the stored-program computer, the CPU, or central processing unit, is the part that executes a list of instructions, each of which performs a small calculation. Instead of rewiring the machine, you change the list of instructions, the program, and let the CPU carry it out. The results of those calculations are stored in memory, a circuit that holds 0s and 1s in addressed locations, so that the CPU can read and write them as needed.
This separation is the heart of the von Neumann architecture, and it is how we manage complexity: we break a large problem down into a long list of small, simple steps, and let the machine carry them out one at a time. That is the same move you will make as a programmer. When a problem looks overwhelming, you will break it into steps small enough for the machine to execute, and solve them one at a time.
1.8 Miniaturization
Computers did not stand still. The vacuum tube gave way to the transistor, transistors were packed together into integrated circuits, and integrated circuits shrank until an entire CPU fit on a single microprocessor. Each step made computers smaller, faster, and more reliable, and the laptop from this chapter’s opening, billions of switches on a few chips of silicon, is where that line of development leads.
1.9 Summary
Programmable machines separate instructions from the machinery that follows them. The Jacquard loom demonstrated this through punched cards; Babbage’s Analytical Engine and Lovelace’s notes explored more general possibilities. Turing later established a mathematical foundation for computation.
Electronic switches and binary representation made electronic computing practical. In a stored-program computer, instructions and data share memory, and the CPU executes the instructions. Vacuum tubes gave way to transistors, integrated circuits, and microprocessors, making computers smaller, faster, and more reliable.
1.10 References and Further Reading
- Lovelace’s Notes on the Analytical Engine (1843): the translation containing Note G, the first published algorithm for a machine
- Turing, On Computable Numbers (1936): the paper behind the universal machine
- Von Neumann architecture
- History of computing hardware
2 Programming Languages
A CPU (central processing unit) executes instructions for operations such as moving values, adding numbers, comparing values, and jumping to another instruction. But programmers want to express larger ideas, such as “calculate the average of these grades” or “print a message if the password is wrong.” Programming languages help bridge that gap.
Abstraction hides lower-level details so you can focus on the problem you want to solve.
2.1 Programming Language Levels
Programming languages express instructions at different levels of abstraction. We will start with machine language, move to assembly, and then see how high-level languages such as Python let programmers focus on the problem instead of processor details.
2.1.1 Machine Language: Programming in Binary
A CPU executes machine instructions encoded in binary: patterns of 0s and 1s. These instructions form its machine language. Each instruction tells the CPU to perform an operation, such as adding two values or moving a value into a register.
Different processor families can use different instruction sets and binary encodings. Machine code built for one instruction set generally cannot run directly on a processor with a different instruction set.
2.1.2 Assembly Language: A Human-Readable Step Up
Assembly language represents machine instructions using readable names. An assembler translates those instructions into machine code.
For example, these two forms represent the same instruction on an x86 processor:
10110000 01100001
MOV AL, 61h
Both tell the processor to put the value 61h—97 in decimal—into AL, a register. Registers are small, fast storage locations inside the CPU.
Assembly is easier to read than binary, but programmers still work closely with the processor’s instructions and storage. You will not write assembly in COMP 1510; this example shows what high-level languages let you leave behind.
2.1.3 High-Level Languages and Abstraction
Machine language and assembly are low-level languages because they expose hardware details. High-level languages, such as Python, let you express a solution without specifying individual processor instructions.
For example, calculating an average in Python can look like this:
average = sum(grades) / len(grades)
For a non-empty collection of grades, this adds the grades and divides by how many there are. You do not have to decide which CPU registers hold the values or which machine instructions perform the calculation.
The diagram compares how a programmer approaches an average calculation in Python and assembly. The assembly branch uses illustrative pseudocode and shows only the final division step, assuming the total and count have already been calculated.
Abstraction lets you express a calculation while leaving more of its implementation to language tools.
2.1.4 Compilers and Interpreters
A compiler translates source code into another form, often machine code or an intermediate form called bytecode.
An interpreter executes a program by carrying out the operations described in its source code or intermediate form. Compilation and interpretation can work together.
When you run a Python program, its source code is typically compiled into bytecode, which the Python interpreter executes. These steps happen automatically.
Python also provides an interactive interpreter called the REPL (Read-Eval-Print Loop). You enter some code, Python evaluates it, displays a result when appropriate, and waits for your next input. This makes it convenient to try small expressions and explore how the language works.
Historical note: Kathleen Booth helped develop early assembly-language tools in the late 1940s. In the early 1950s, Grace Hopper developed A-0, an early compiler-like system. Both contributed to making programming more accessible than writing machine instructions directly.
2.1.5 Different Languages for Different Problems
High-level languages serve different purposes. Fortran was developed for scientific calculations, SQL expresses queries over data, and Python supports a wide range of programming tasks.
These languages are not successive steps on a single ladder. They make different choices about how programmers express solutions. Python’s readability and interactive environment make it useful for learning the fundamentals in this course.
2.2 Programming Paradigms
Language levels describe how much hardware detail a programmer must manage. Programming paradigms describe how a programmer organizes a solution.
A paradigm is a way of organizing a program and expressing a solution.
| Paradigm | Main idea | Example |
|---|---|---|
| Procedural | Describe steps and group them into procedures or functions. | Read a temperature, calculate its Fahrenheit equivalent, and display it. |
| Object-oriented | Combine related data and behaviour in objects. | A Temperature object stores a value and provides a to_fahrenheit() method. |
| Functional | Build calculations from functions, emphasizing results without changes to outside state. | A conversion function returns a Fahrenheit value while leaving other data unchanged. |
| Logic | Express facts and rules, then ask questions about them. | Use prerequisite rules and a student’s completed courses to determine course eligibility. |
A problem can often be approached through more than one paradigm.
2.2.1 Procedural Programming
Procedural programming describes what the computer should do through explicit instructions, grouped into reusable procedures or functions.
A program might read a temperature, convert it from Celsius to Fahrenheit, and display the result. As programs grow, they can make decisions, repeat instructions, and call functions to perform particular tasks.
This is the style you will spend most of COMP 1510 practising.
2.2.2 Object-Oriented Programming
Object-oriented programming organizes code around objects, which combine data and behaviour.
In a game, a Player object might store its health and position and provide actions such as move() and attack(). This approach helps organize programs containing interacting things, each with its own data and actions. You will explore it in later programming courses.
2.2.3 Functional Programming
Functional programming emphasizes computing results through functions and limiting changes to state—the data a program holds at a particular time.
A temperature-conversion function, for example, can take a Celsius value and return a Fahrenheit value without changing anything outside the function. A pure function produces the same result for the same input and has no side effects, such as modifying outside data or printing a message. These properties make its behaviour easier to reason about.
Calling a function does not, by itself, make a program functional; procedural programs use functions too. The distinction is the emphasis on pure calculations and combining their results.
2.2.4 Logic Programming
Logic programming expresses facts and rules that a system uses to answer questions.
In Prolog, for example, you could state which courses Alex has passed and which prerequisites a course requires. The system can then use those facts and rules to determine whether Alex meets the prerequisites.
2.2.5 Multi-Paradigm Languages
Many languages support more than one paradigm. Python supports procedural and object-oriented programming, as well as functional techniques.
In COMP 1510, we begin procedurally: writing clear instructions and grouping related work into functions. Other approaches become useful as you encounter different kinds of problems.
2.3 Summary
Abstraction lets programmers focus on a problem while language tools handle lower-level details. Machine language contains the instructions a CPU executes; assembly gives those instructions readable names. High-level languages such as Python let us express calculations without specifying individual processor operations.
Compilers translate code; interpreters execute it. Python typically combines both approaches by compiling source code into bytecode and executing it through an interpreter.
Programming paradigms describe how we organize solutions. Procedural programming uses instructions grouped into functions; other approaches emphasize objects, pure calculations, or facts and rules. Python supports several paradigms, and COMP 1510 begins with procedural programming.
2.4 References and Further Reading
- Python glossary: bytecode: the intermediate form used when running Python programs.
- Using the Python interpreter: running Python, including interactive mode.
- Kathleen Booth: her contributions to early computing.
- Grace Hopper: her work on early programming systems.
- Programming paradigms: further examples of ways to organize programs.
- History of programming languages: an optional survey of how languages developed.
3 Getting Started with Python
In the previous two chapters we traced the history of computing hardware and surveyed the landscape of programming languages and paradigms. Now it is time to get our hands on a language. This chapter introduces Python, the language we will use throughout COMP 1510, and walks you through installing it, running it, and understanding its basic building blocks.
3.1 What Is Python?
Python is a high-level, general-purpose, multi-paradigm programming language designed for readability: Python code often reads almost like English, so the ideas stay front and centre while you learn. It is also genuinely practical, used across the industry in web development, data analysis, and automation, and it ships with a large standard library, meaning that many common tasks (working with files, fetching data from the web, doing math) can be done without installing anything extra.
For an introductory course, three reasons stand out:
- Readable syntax lets you focus on programming concepts rather than language mechanics.
- A large standard library means you can do a great deal without installing third-party packages.
- A huge community means tutorials, documentation, and help are easy to find.
3.2 Installing Python
Before you can write Python, you need to install it: download Python 3.14.x for your operating system from python.org and run the installer. Windows offers more than one installer, so follow the installation instructions for the one you choose; if it offers an “Add Python to PATH” checkbox, select it so your system can find Python from the command line.
3.3 The Python Interpreter
Once Python is installed, you can interact with it through the interpreter: the program that reads, evaluates, and executes your Python code.
3.3.1 Opening the Interpreter
-
Open a Terminal (on macOS or Linux) or PowerShell (on Windows).
-
Type the following to confirm that Python is installed and check its version:
python3 --versionYou should see a version number starting with
Python 3.14(for example,Python 3.14.7). On Windows, typepy --versioninstead; thepylauncher takes the place ofpython3on Windows, and that one substitution covers every command in this chapter. -
To start the interpreter, type:
python3(On Windows, use
py.)
3.3.2 The REPL
When the interpreter starts, you are in the REPL: the Read-Eval-Print Loop. The REPL does exactly what its name says:
- Read an instruction you type.
- Evaluate (execute) it.
- Print the result.
- Loop back and wait for the next instruction.
You will see the >>> prompt, which means the interpreter is waiting for you to type something. Try your very first Python instruction:
>>> print("Hello, COMP 1510!")
Hello, COMP 1510!
Congratulations: you have just run your first Python program.
3.3.3 Basic Output
The print function displays values on the screen. It can print the result of an expression, and it can print several values at once, separated by commas:
print("Hello, COMP 1510!")
print(2 + 3)
name = "Ada"
print("Hello,", name)
Running this program produces:
Hello, COMP 1510!
5
Hello, Ada
Notice that 2 + 3 was evaluated before being printed, and that the comma in print("Hello,", name) simply puts a space between the two values. You will use print constantly, both to make programs talk to their users and to see what your own code is doing while you develop it.
3.3.4 Evaluating Expressions
The REPL is not limited to running commands like print. It also evaluates expressions and displays their results automatically. Try a few simple calculations:
>>> 2 + 3
5
>>> 10 * 4
40
You type an expression, press Enter, and the REPL shows you the result. This makes the REPL an excellent tool for experimenting and learning: you can try things out one at a time and see immediately what happens.
3.3.5 Exiting the Interpreter
When you are done experimenting, you can exit the REPL in a few ways:
- Type
quit()and press Enter. - On Windows, press Ctrl-Z then Enter.
- On macOS or Linux, press Ctrl-D.
3.3.6 Source Files
The REPL is great for quick experiments, but real programs are usually too long to type interactively. Python programs can also be stored in source files: plain text files with a .py extension, such as hello.py. You write your code in the file, save it, and then run it as a program:
python3 hello.py
(On Windows, run py hello.py.) Save your hello.py into a folder you can find again, such as a comp1510 folder inside your Documents. Locating that folder and running the file from the command line is exactly the next chapter’s job.
3.4 Python Keywords
Every programming language has a set of keywords: reserved words that have a predefined meaning in the language. You cannot use these words as variable names, because Python has already claimed them for specific purposes.
Here is the full table of Python keywords:
False |
await |
else |
import |
pass |
True |
break |
except |
in |
raise |
None |
class |
finally |
is |
return |
and |
continue |
for |
lambda |
try |
as |
def |
from |
nonlocal |
while |
assert |
del |
global |
not |
with |
async |
elif |
if |
or |
yield |
A few soft keywords, such as match, case, and type, are contextual: Python treats them as keywords only inside specific constructs, so they can still be used as names elsewhere.
Do not try to memorize all of these at once. You will learn them naturally as they become relevant: if, else, for, and while will show up almost immediately, while others like async and nonlocal you may not need for a while. For now, just know that these words are reserved, and if you ever get an error when trying to name a variable, check whether you accidentally used a keyword. The official list lives in the language reference.
3.5 The Zen of Python
Python has a set of design aphorisms known as the Zen of Python. They capture some of the values that have shaped Python and its programming culture.
You can display the full Zen at any time in the interpreter:
>>> import this
You do not need to memorize it. A few of its ideas are especially useful as you begin programming:
- Readability counts. Code is read by people as well as computers. Choose names and structures that make your intentions clear.
- Simple is better than complex. Prefer a straightforward solution when one is available.
- Explicit is better than implicit. Make important behaviour visible rather than relying on assumptions or hidden details.
- Beautiful is better than ugly. Well-organized code should be pleasant to read and work with.
- Now is better than never. You do not need to understand everything before you start writing programs. Experiment, inspect the result, and keep learning.
These principles will make more sense as you write larger programs. For now, keep one idea close at hand: readability counts.
3.6 Summary
Python is a high-level, general-purpose language designed for readability. Its standard library provides tools for many common tasks without requiring additional packages.
The REPL lets you enter code and inspect results immediately. A source file saves code in a .py file so you can run and revise a program. In both settings, print() displays messages and calculated results.
Python’s keywords have reserved roles in the language. Its design principles, collected in the Zen of Python, encourage clear, simple, readable code. You will become familiar with both through practice.
3.7 References and Further Reading
- PEP 20 — The Zen of Python
- Python 3.14 documentation
- Built-in functions
- A brief history of Python
- Beej’s Guide to Python Programming, chapter 3: installing Python and running your first commands
4 The Command Line
Chapter 3 left you with a hello.py saved in a folder such as Documents/comp1510. A saved file is only useful if you can get back to it: if you close the terminal and return tomorrow, how do you find that folder and run the program again? As your scripts pile up, you need a way to move around, name things clearly, and run them without retyping everything. That is what the command line gives you.
The command line is a text-based interface for interacting with an operating system and its tools. Where a graphical desktop lets you point and click, the command line asks you to type what you want done. Programmers use it to run programs, inspect files, create directories, use version control, manage packages, and automate repetitive tasks. You open it with Terminal on macOS or Linux, or PowerShell on Windows. This chapter’s examples use Terminal on macOS; readers on Windows can follow along in PowerShell, where the everyday commands in the table below use the same spellings.
This chapter introduces the ideas you need to navigate the command line confidently: paths, the difference between absolute and relative locations, and the essential commands you will use every day.
4.1 Paths
When you open the command line, you usually start at your home directory, a personal folder reserved for your user account. From there, every file on the computer can be reached by following a path: a list of nested folders, read from left to right, that leads to the file or folder you want.
The details depend on your operating system. On macOS and Linux, the root directory is written /. Home-directory paths commonly look like:
macOS:
/Users/moose
Linux:
/home/moose
On Windows, paths usually begin with a drive root such as C:\, and the same home path looks like:
C:\Users\moose
The delimiting character differs too: Windows accepts both \ and /, while macOS and Linux use / exclusively. The differences that matter are called out as they come up.
4.2 Absolute vs Relative Paths
Paths come in two flavours, and understanding the distinction will save you a great deal of confusion.
An absolute path points to the same location no matter where you happen to be working. It always begins from the root directory, so there is no ambiguity. For example:
cd /Users/moose/exams
This command takes you to exams regardless of your current directory, because the path starts at /.
A relative path, by contrast, starts from your current working directory. If you are already inside /Users/moose, you can reach the same exams folder with:
cd exams
Relative paths are shorter and convenient, but they only make sense relative to where you are. From /Users, cd exams would look for /Users/exams, not /Users/moose/exams. A relative path is interpreted from your current directory. Absolute paths are longer but unambiguous: cd /Users/moose/exams reaches the very same exams folder from anywhere. As you work, you will learn to choose whichever fits the moment.
4.3 Essential Commands
Most day-to-day command-line work comes down to a small set of commands, and the same spellings work in Terminal and in PowerShell:
| Action | Command | Example |
|---|---|---|
| Print the current directory | pwd |
pwd |
| List directory contents | ls |
ls |
| Enter a subdirectory | cd alpha |
cd comp1510 |
| Move up one directory | cd .. |
cd .. |
| Make a new directory | mkdir name |
mkdir comp1510 |
| Move or rename a file | mv old new |
mv hello.py greetings.py |
| Delete a file | rm file |
rm hello.py |
| Clear the terminal screen | clear |
clear |
A few of these are worth a second look. The single dot . always refers to the current directory, while the double dot .. refers to its parent. These two shorthand symbols are the foundation of relative paths and appear constantly in real work: for example, cd .. to back out of a folder, or cd ../.. to climb two levels at once.
You will also meet one more shorthand, the tilde ~. It is shorthand for your home directory, the folder your account starts in, so ~/Documents means the Documents folder inside your home directory.
One command deserves a warning before you use it: rm deletes a file immediately. Unlike dragging a file to the Recycle Bin or Trash, deleting from the command line generally cannot be undone, so check the filename before pressing Enter.
You do not need to memorize every command at once. Pick a handful (pwd, ls, cd, and mkdir are a fine starting set) and practise them until they become muscle memory. The rest will follow naturally as your projects grow more ambitious.
Command Prompt, the older Windows shell, still appears on some machines. If one greets you, the survival kit is dir to list files, del to delete, rename to rename, and cls to clear the screen; typing bare cd prints the current directory. Typing powershell there launches PowerShell, the shell Windows readers can follow along in.
4.4 From Folder to Program
Here is the whole round trip, from a freshly opened terminal to a running program. On macOS or Linux:
cd ~/Documents/comp1510
ls
python3 hello.py
On Windows (PowerShell):
cd ~\Documents\comp1510
ls
py hello.py
The cd moves you into the project folder, ls confirms that hello.py is there, and the last line runs it. The path spelling (/ versus \) and the Python launcher (python3 versus py) are the only differences.
Use the location where you actually saved your file; the paths here are examples. If a folder name contains spaces, enclose the path in quotes, such as cd "COMP 1510".
Three habits make all of this faster:
- Tab completion: type the first few letters of a file or folder name and press Tab, and the terminal completes it.
cd Docfollowed by Tab becomescd Documents. - Command history: press the up arrow to bring back a previous command, edit it if you need to, and run it again.
- Drag and drop: dragging a folder from Finder or File Explorer into the terminal window inserts its path right at the prompt, which saves typing long paths by hand.
4.5 Summary
The command line lets you interact with your computer by typing commands. Your current working directory is the starting point for relative paths. Absolute paths identify locations independently of it, while ., .., and ~ refer to the current directory, its parent, and your home directory.
The essential navigation commands are pwd to check your location, ls to list its contents, and cd to move elsewhere. Use mkdir to create a directory, and take care with rm: deleted files generally do not go to the Trash or Recycle Bin.
To run a Python source file, navigate to its folder and enter python3 hello.py, or py hello.py on Windows. Tab completion and command history reduce repeated typing.
The next chapter introduces variables, which let a program name values and reuse them as it runs.
4.6 References and Further Reading
5 Variables and Assignment
You can now navigate the file system and run a Python program. As programs grow, they need to reuse values and carry results from one step to the next. Variables give those values names so we can refer to them throughout a calculation. This chapter introduces variables and explains how assignment binds names to values while a program runs.
5.1 Statements
The text you write to create a program is called code. A single row of text in that code is called a line of code.
A statement is a complete instruction that Python executes. It tells Python to do something: assign a value, display output, import a module, and so on. An expression is code that produces a value; 2 + 2 is an expression that evaluates to 4. The two are related, not opposed: statements often contain expressions. In area = pi * radius ** 2, the whole line is an assignment statement, while pi * radius ** 2 is the expression whose value it stores. A Python program (sometimes called a script) is a sequence of statements, evaluated and executed one at a time, in order, by the Python interpreter.
Consider the following statements:
print('Able was I ere I saw Elba')
print('Out darn spot, out!')
print('Buckle up, buckaroos!')
print(4 + 8)
print(3 * 2.5 ** 2 + 2.5 * 2 + 4)
When the interpreter runs this script, it reads the first print statement, carries it out, moves to the second, carries it out, and continues down the list. Each statement is a complete instruction. Some print text, some print the result of an arithmetic expression, but all of them are executed in the order they appear. This top-to-bottom flow is the simplest model of how a program runs, and it is the foundation everything else is built upon.
5.2 Variables
Printing values is useful, but a program that only prints literals, values written directly into the code, is limited. What we really want is a way to remember values so we can use them again later, perhaps in many places. This is what a variable provides: a name bound to a value.
Here is a simple example:
pi = 3.1415926535
colour = "red"
The first line binds the name pi to the value 3.1415926535. The second binds the name colour to the value "red", the string of three characters r, e, and d. Once a name is bound, we can use it anywhere in the program, and Python works with the value it refers to. It helps to picture a variable as a label attached to a value rather than a box containing it.
The two assignments from the example above, drawn as bindings rather than boxes:
Physically, those values live in the computer’s memory, the RAM (random access memory), along with everything else the machine is working on right now. Python chooses exactly where each value sits and keeps track of it for you: when you use the name pi, Python follows the binding to the value’s place in memory and fetches it. You never see or type a memory address. The name is the only handle you need.
5.3 Assignment
A variable is just a name. On its own, a name is not very useful: we must assign a value to it. An assignment statement associates the value on the right of the equals sign (=) with the variable on the left.
There are two rules to keep in mind:
- In the simple assignments we use for now, the left side is a variable name.
- The right side can be a value or an expression.
When Python encounters an assignment, it first evaluates the right side completely, then binds the resulting value to the name on the left. This is why an expression like area = pi * (radius ** 2) works: Python computes the value of the expression using whatever pi and radius currently refer to, and only then stores the result under the name area. The expression is the circle-area formula you know from geometry, , translated into Python: each quantity gets a descriptive name, multiplication becomes *, and the superscript becomes ** 2.
5.4 Variable Names (Identifiers)
Every variable needs a meaningful name, and that name is called its identifier. For COMP 1510, use the following rules when choosing one:
- Identifiers can be composed of letters (
a–z,A–Z), underscores (_), and digits (0–9). - An identifier may not start with a digit.
player1is fine;1playeris not. - Python is case sensitive, so
Pythonandpythonare two completely different names.
(Python itself permits a broader range of Unicode letters; the rules above are the ones we follow in this course.)
These rules define what is legal, but they do not define what is good. That is a matter of convention. Python’s official style guide, PEP 8, codifies it in detail, and that brings us to naming practices.
5.5 Naming Conventions
Identifiers must describe their purpose. A name is documentation: it tells the next person reading your code, perhaps you, three weeks from now, what a variable represents. Compare the following two versions of the same calculation:
| Vague | Descriptive |
|---|---|
a = 3.14159 |
pi = 3.14159 |
b = 20.18 |
radius = 20.18 |
c = a * (b ** 2) |
area = pi * (radius ** 2) |
Both versions produce the same result, but only the second one is readable. The vague names cost you every time the code is read: weeks later, a could be anything and must be decoded anew; nothing says whether 20.18 is a radius, an angle, or an age; and the formula itself is unrecognizable, so you cannot check it against the problem it is supposed to solve.
A few practical guidelines follow from this principle:
- Avoid single-character variable identifiers. They rarely communicate purpose, and a reader has nothing to go on when the code is revisited weeks later.
- Use abbreviations only when they are widely understood. Names like
apporfaqare common enough to be clear; abbreviations likeusrfor “user” ortmpfor “temporary” save only a few keystrokes while costing readability. - Be specific. If a variable in a game stores a non-player character’s age,
age_in_yearsis better thana, and better even thanage, because it removes all ambiguity about the unit.
5.6 Naming Cases in Python
Identifiers can be written in several typographic styles, and the programming community has names for the most common ones:
- snake_case:
in_python_we_do_this, Python’s convention for variables and functions. (Python, the snake, uses snake case: folklore, but a memorable one.) - UPPER_CASE:
THIS_IS_UPPER_CASE, Python’s convention for constants. - CapWords (
ThisIsCapWords, also called CamelCase): Python’s convention for class names, which you will meet in a later course. Classes are not something you write yet, but you will recognize the style the moment you see it.
For the variables you write now, snake_case is the expected choice. Following it makes your code feel native to the language and easier for other Python programmers to read.
5.7 Summary
A statement is an instruction Python executes; an expression evaluates to a value. Statements often contain expressions, as in area = pi * radius ** 2.
A variable is a name bound to a value. Assignment evaluates the entire right-hand expression before binding its result to the name on the left. Assigning again can make that name refer to a different value.
Good names explain what values represent. Follow the course’s identifier rules, choose descriptive names, and use snake_case for variables. UPPER_CASE indicates constants by convention, while CapWords is used for class names.
The next chapter puts those named values to work through arithmetic, comparisons, and other expressions.
5.8 References and Further Reading
- PEP 8, the official style guide, naming conventions section
- Assignment statements, language reference
- Snake case
- Beej’s Guide to Python Programming, chapter 5: data, variables, and assignment
6 Operators and Expressions
The previous chapter gave you a way to name values so a program can remember them. But a name on its own doesn’t do much. The real work starts when you combine those values: add them, compare them, test conditions, and build up results. That is what operators do. This chapter looks at the families of operators Python provides, sees how they combine into expressions, and finishes with the rules that decide which operator goes first when several appear together.
6.1 Operators and Operands
The phrase to remember is simple: operators operate on operands. Consider the familiar plus sign. In an expression like 5 + 5, the two 5s are the operands and + is the operator. Because it sits between two operands, + is called a binary infix operator: “binary” because it takes two operands, and “infix” because it appears in between them.
The operands in 5 + 5 are literals: raw values written directly in the code. Python has several kinds of literals:
- Numeric literals, such as
5or3.14 - String literals, such as
"Hello" - Boolean literals, namely
TrueandFalse
Literals are the raw material of expressions; operators are the tools that shape them.
6.2 Arithmetic Operators
Arithmetic operators do what you expect from mathematics, with a couple of additions that reflect how computers work with numbers.
| Operator | Name | Example |
|---|---|---|
+ |
Addition | 1 + 2.0 |
- |
Subtraction | 3.14 - 1.4142 |
* |
Multiplication | 5 * 5 |
// |
Floor Division | 4 // 2 |
/ |
Division | 6.0 / 4 |
% |
Remainder/Modulo | 10 % 4 |
** |
Exponent/Power | 4 ** 4 |
Two of these deserve special attention. The / operator always produces a floating-point result, even when the division is exact: 6 / 3 yields 2.0. The // operator, by contrast, performs floor division (older books sometimes call it integer division): it rounds the quotient down to a whole number, in the sense of the floor function , the greatest whole number at or below :
So 7 // 2 is 3, while -7 // 2 is -4, not -3: “down” means down the number line, past zero when the quotient is negative.
One caution: floor describes the value, not the type of the result. Floor division of two integers gives an integer: 7 // 2 is the int 3. But if either operand is a float, the result is a float: 7.0 // 2 is 3.0, rounded down just the same. The rounding is the operator’s job; the type follows the operands.
The % operator returns the remainder after floor division. Quotient and remainder always reassemble into the number you started with; dividing 10 by 4 gives the quotient 2 and the remainder 2:
In Python, 10 // 4 computes the quotient and 10 % 4 the remainder. For a positive divisor , the remainder always satisfies : divided by 2, a whole number leaves a remainder of 0 or 1 and nothing else, which is why n % 2 == 0 tests whether a number is even. The remainder is just as useful for cycling through a fixed set of values.
6.3 Comparison Operators
Comparison operators examine two values and produce a Boolean result: True or False.
| Operator | Meaning | Example |
|---|---|---|
< |
Strictly less than | 5 < 4 |
> |
Strictly greater than | "z" > "Z" |
<= |
Less than or equal to | 5 <= 7 |
>= |
Greater than or equal to | "better" >= "bad" |
== |
Equal to | 2 == 2.0 |
!= |
Not equal to | 3.14 != 3 |
Notice that comparison is not limited to numbers. Strings can be compared too, and Python orders them lexicographically, roughly alphabetically, using the numeric codes of each character. That is why "z" > "Z" is True: lowercase letters sort after uppercase ones in the character encoding. Also note the equality operator ==, which tests for equal value, is distinct from the assignment operator =. Confusing the two is one of the most common early mistakes, so keep them straight: = assigns, == compares.
The distinction is quickest to see in the REPL, where the assignment produces nothing to print while the comparison answers a question:
>>> age = 19
>>> age
19
>>> age == 19
True
The first line binds the name age to the value 19, silently. The last line stores nothing: it asks whether the two values are equal and evaluates to a Boolean, True here, and False whenever the sides differ.
6.4 Logical Operators
Preview: You will see these operators in simple conditions soon; we will study Boolean logic in more depth in Week 5.
Logical operators combine Boolean values, letting you build richer conditions.
| Operator | Name | Example |
|---|---|---|
and |
Boolean and | 4 < 5 and 9 < 10 |
or |
Boolean or | 6 < 5 or 9 < 10 |
not |
Boolean not | not True |
and yields True only when both operands are true. or yields True when at least one operand is true. not flips a Boolean value: not True is False, and not False is True. These descriptions assume Boolean operands, the True and False values that comparisons produce; handed values of other types, and and or behave a little differently, a detail we will meet much later. For now, the three operators are the glue that holds compound conditions together, letting you combine simple comparisons into richer ones.
6.5 Expressions
Operators and operands together form expressions. A value all by itself is the simplest possible expression: the literal 64738 evaluates to 64738. More generally, in mathematics and computing, an expression is a sequence of operators and their operands that specifies a computation.
Evaluating an expression produces a result (also called a value). The expression 2 + 2 generates the result 4. A short aside on built-ins such as print: calling print("Hello") displays the text, and that display is the whole point, yet the call itself evaluates to None, a special value meaning “no useful value”. The visible side effect and the value returned are two different things; you will meet None again later in the course.
6.6 Operator Precedence
When an expression contains several operators, Python does not simply evaluate them left to right. Instead, it follows precedence rules that determine the order of evaluation. From highest to lowest, the order is:
( ): parentheses are always evaluated first- Arithmetic operators (
**,*,//,/,%,+,-): remember BEDMAS (Brackets, Exponents, Division and Multiplication, Addition and Subtraction) - Comparison operators (
<,<=,>,>=,==,!=) not: logical NOTand: logical ANDor: logical OR
Consider z - 45 * y < 53. Python evaluates the multiplication 45 * y first, then the subtraction z - ..., and finally the comparison ... < 53. The result is not the same as reading left to right, so precedence matters.
Exponentiation carries one wrinkle worth knowing: -2 ** 2 is -4, not 4, because ** binds more tightly than the unary minus. In mathematical notation, Python reads the expression as , not ; the two differ only in where the minus sign sits. If you mean the square of negative two, write (-2) ** 2.
To see the whole order at once, draw the earlier example, z - 45 * y < 53, as a tree:
The tree makes the order visible: 45 * y is evaluated first, the subtraction second, and the comparison last.
Precedence can also surprise you with logical operators. The expression x == 5 or y == 10 and z != 10 evaluates as (x == 5) or ((y == 10) and (z != 10)), because and binds more tightly than or. If that is what you intended, fine, but it is easy to misread.
The remedy is simple: use parentheses to make your intended order explicit. Writing (x == 5) or (y == 10 and z != 10) removes all doubt, both for Python and for the next person who reads your code. As the Python community likes to say, “Readability counts.” When precedence is unclear, parentheses are not redundant: they are a courtesy to your reader, and often to your future self.
6.7 Compound Operators
One assignment comes up so often that Python gives it its own shorthand. Suppose a variable already holds a value, and you want to increase it by one:
age_years = 19
age_years = age_years + 1 # age_years now refers to 20
The right side is evaluated first, using the value age_years currently refers to, and the name is then bound to the result. Because this read-then-update pattern is so common, Python provides compound operators, each of which combines an arithmetic operator with assignment:
age_years = 19
age_years += 1 # 20: age_years = age_years + 1
account_balance = 100.00
account_balance -= 50.00 # 50.0: subtraction
number_of_calls = 4
number_of_calls *= 2 # 8: multiplication
average = 7.5
average /= 2 # 3.75: division
slices = 7
slices //= 2 # 3: floor division
remainder = 10
remainder %= 4 # 2: the remainder of 10 by 4
For the simple numerical examples above, each compound operator behaves exactly like its longhand form: age_years += 1 does the same thing as age_years = age_years + 1, just shorter. After each line above, the name refers to the freshly computed value. Whenever you find yourself writing x = x <op> y, there is a compound operator that lets you write x <op>= y instead.
6.8 Summary
Operators act on operands to produce results. Arithmetic operators perform calculations, comparisons produce Boolean values, and logical operators let us combine or negate conditions. An expression evaluates to a value and may also have a side effect: print("Hello") displays text and returns None.
Division needs particular care. For the integer and float operands used here, / produces a float, while // rounds the quotient down, including for negative numbers. Floor division produces an integer when both operands are integers and a float when either is a float. The % operator gives the remainder.
Precedence determines how an expression is grouped. Multiplication takes precedence over addition, comparisons follow arithmetic, and the logical operators follow in the order not, and, or. Parentheses make the intended grouping clear. Compound operators such as += combine an operation with assignment, making common numerical updates shorter to write.
So far, we have supplied values directly in our code. The next chapter introduces programs that ask users for information and convert their responses into values we can calculate with.
6.9 References and Further Reading
- Operator precedence, the full table
- Modulo operation
- Beej’s Guide to Python Programming, appendix A: order of operations, floor division, and modulo
7 Input and Types
So far, every value in our programs has been written directly into the code. Real programs also need to work with information provided by users. This chapter introduces input() for reading what a user types, then looks at the different types of values Python can work with.
7.1 Basic Input
The input() function pauses the program and waits for the user to type something and press Enter. The value entered by the user can then be stored in a variable.
input() can also display a prompt: a short message that tells the user what to enter.
user_input = input()
user_age_years = input("Enter your age in years: ")
In the first line, the program waits silently for input. In the second, it displays Enter your age in years: before waiting.
Whatever the user types is accepted as input. The important detail is what Python does with that input, which we look at next.
7.2 input() Always Returns a String
The most important thing to remember about input() is simple: it always returns a string, even when the user types something that looks like a number.
If the user types 42, Python receives the string "42", not the integer 42. The string contains two characters: '4' and '2'.
For example:
age = input("Enter your age in years: ")
If the user enters 42, the variable age refers to the string "42".
This matters when we want to perform calculations. Python treats text and numbers differently, so we first need to understand the different types of values it can work with.
7.3 Data Types
Every value in Python has a type. A value’s type determines what kind of information it represents and which operations make sense for it.
You will work with four basic types from the beginning of this course:
| Type | Description | Examples |
|---|---|---|
int |
Integers (whole numbers) | -4, 17, 2022 |
float |
Floating-point numbers | 1.0, 3.14, -19.73 |
str |
Strings (text) | "hello", 'blue', "42" |
bool |
Boolean values (True or False) |
True, False |
An int represents a whole number. A float represents a floating-point number and can represent fractional values, although many decimal fractions cannot be represented exactly. A str represents text as a sequence of characters. A bool represents one of two truth values: True or False.
Python provides the built-in type() function when you want to check the type of a value:
print(type(42))
print(type(3.14))
print(type("hello"))
print(type(True))
The program prints:
<class 'int'>
<class 'float'>
<class 'str'>
<class 'bool'>
We can now use type() to confirm what happens with user input:
age = input("Enter your age in years: ")
print(type(age))
If the user enters 42, Python prints:
<class 'str'>
The characters look like a number to us. Python still sees the value returned by input() as a string.
7.4 Data Conversion
If we want to use numerical input in a calculation, we need to convert it from a string to a numeric type. This is called type conversion.
Python provides several built-in functions for conversion:
| Function | Creates | Examples |
|---|---|---|
int() |
Integers | int("42"), int(3.14) |
float() |
Floats | float("3.14"), float(42) |
str() |
Strings | str(42), str(3.14) |
Each function takes a value and produces a value of the requested type.
int("42") # 42
float("3.14") # 3.14
str(42) # "42"
The value being converted still has to make sense as the requested type. For example:
int("42") # works
float("3.14") # works
int("3.14") # ValueError
int("hello") # ValueError
int("3.14") fails because the string does not contain an integer. int("hello") fails because the string does not represent a number at all.
These invalid string conversions raise a ValueError: Python accepts a string as an argument to int(), but the string must represent an integer. We will study errors and exceptions in more detail later in the course.
7.5 Implicit Conversion
Sometimes Python performs a conversion automatically.
Consider an expression that combines an int and a float:
result = 5 + 2.5
print(result)
Python produces:
7.5
For this operation, Python treats the integer 5 as the floating-point value 5.0, then performs the addition. The result is therefore a float.
This kind of automatic conversion is called implicit conversion, or coercion.
In mixed int and float arithmetic, Python converts the integer operand to a float for the operation. Converting the float to an integer could discard its fractional part.
7.6 Putting It Together
We can now combine input and conversion in a small program:
price = input("Price: ")
quantity = input("Quantity: ")
total = float(price) * int(quantity)
print(total)
Suppose the user enters:
Price: 19.99
Quantity: 3
input() gives us two strings:
"19.99"
"3"
The program then converts "19.99" to the float 19.99 and "3" to the integer 3. Once both values are numeric, Python can multiply them and produce:
59.97
If we tried this instead:
total = price * quantity
Python would raise a TypeError because both values are strings and string-by-string multiplication is not defined.
The pattern is worth remembering:
- Read input as a string.
- Convert it to the type you need.
- Compute with the converted value.
You will use this pattern throughout the course.
7.7 Built-ins So Far
A built-in function is a function Python makes available automatically. No import is required.
You have now met these built-in functions:
| Function | Purpose | Example |
|---|---|---|
print() |
Display values on the screen | print("Hello") |
input() |
Read a line typed by the user | input("Age: ") |
type() |
Report the type of a value | type(3.14) |
int() |
Convert a value to an integer | int("42") |
float() |
Convert a value to a float | float("3.14") |
str() |
Convert a value to a string | str(42) |
Python provides many more built-in functions. You can find the complete list in the official built-in functions reference.
7.8 Summary
input() returns a string, even when the user enters a number. It can display a prompt before waiting for the user to type and press Enter.
Every value has a type that determines which operations it supports. The four types introduced here are int, float, str, and bool; type() reports a value’s type.
Type conversion lets us turn input into values suitable for calculations. Use int() for integers, float() for floating-point numbers, and str() for text. Invalid string conversions, such as int("hello"), raise a ValueError. Python also performs some conversions automatically during mixed numeric arithmetic.
The practical pattern is read → convert → compute: collect the input, convert it to the type you need, and use the result.
The next chapter introduces the tools you will use to write, run, and share those programs: an editor, an IDE, and version control.
7.9 References and Further Reading
- Built-in functions: includes
input(),type(),int(),float(), andstr() - Type system
- Floating-point arithmetic
- Beej’s Guide to Python Programming, chapter 5: user input, data types, and converting between them
8 Text Editors, PyCharm, and Version Control
Our first chapters were about ideas: the history of computing, the levels of programming languages, and the core building blocks of Python itself. This chapter is about the workshop. Writing programs for real means writing, running, fixing, and sharing files, and for that you need tools. In COMP 1510 we use three: a code editor, an integrated development environment called PyCharm, and the version control system git together with the GitHub service. This chapter explains what each tool is for and why it matters.
8.1 From Text Editor to IDE
A Python source file is nothing more than plain text, so in principle any text editor can write one. In practice, the choice of editor makes an enormous difference:
- A plain editor (like Notepad) shows raw text and offers no help at all.
- A programmer’s editor adds conveniences aimed at code: syntax highlighting colours keywords, strings, and numbers so mistakes stand out, and automatic indentation keeps your program’s structure visible.
- An integrated development environment (IDE) goes further still: it combines an editor with tools to run and debug programs, manage projects, and work with version control, all in one application.
We use PyCharm, an IDE built specifically for Python. Among other things, it will:
- Highlight syntax and flag likely errors as you type, before you ever run the program.
- Run your programs with a single click.
- Include a built-in terminal, so the command-line skills from an earlier chapter are always one keystroke away.
- Integrate with git, which we turn to next.
8.2 Projects
PyCharm organizes your work into projects: a folder on disk that holds your code plus PyCharm’s own settings, including which Python interpreter to use. Creating a project and choosing its Python interpreter takes only a few minutes. After that, opening PyCharm and opening your project is all it takes to pick up where you left off.
When you create a new project, PyCharm normally creates a virtual environment, usually stored in a folder named .venv inside the project folder. A virtual environment is an isolated Python environment for that project, so each project can manage its own packages without interfering with other projects or your system. We will only take a brief look at it this week; it will become more important later in the course, when we begin installing packages.
8.3 Version Control with git
Sooner or later, every programmer loses a working version of a program to a careless edit. Saving copies by hand (assignment01.py, assignment01_v2.py, assignment01_final.py, assignment01_final_FINAL.py) only postpones the problem.
git solves it. A git repository records a series of snapshots, called commits, of your project. A commit stores the exact state of the files git is tracking, containing precisely the changes you staged, along with a short message you write describing what changed and why. A commit does not automatically sweep in every file in the folder: git records only the files you have told it to track, and staging chooses which of their current edits belong in the snapshot. Work that has been committed can normally be recovered from the repository’s history, even if the current files get deleted or damaged. At any moment you can look back through the history, compare versions, or return to any earlier snapshot.
The workflow is a small loop you will repeat thousands of times:
- Edit your files.
- Stage your changes: tell git which edits belong in the next snapshot.
- Commit: take a snapshot with a message, such as “add input validation”.
- Keep working.
Commit early and commit often. Small commits are easy to understand and easy to roll back; big ones are neither. This is “now is better than never” applied to your work history.
Drawn as a loop, the workflow looks like this:
The highlighted step is the one that matters: the commit is the snapshot that makes your work recoverable. Push and pull just move commits between your machine and GitHub (pull also integrates what it fetches into your copy), which the next section explains. PyCharm runs most of this loop for you: it stages your changed files, commits them with your message, and pushes, all from a few clicks.
8.4 GitHub
git works entirely on your own machine, which raises an obvious question: what happens if your laptop dies the night before a deadline? GitHub is the answer. It is a website that hosts git repositories in the cloud, giving you backup, sharing, and collaboration.
Here is the three-way distinction, stated plainly. A commit records a snapshot in your repository’s history, on your machine. A push transfers your new commits from your machine to a remote copy. GitHub is the hosting service where that remote copy lives: git is the tool, GitHub is a place to store repositories that use it.
The daily loop gains two steps:
- Push: send your new commits from your machine to GitHub.
- Pull: fetch any new commits from GitHub and integrate them into your local copy. Pulling is really two steps in one: it fetches the new commits, then combines them with your own work so your copy is up to date.
In COMP 1510, your work is submitted by pushing it to your GitHub repository. Your instructors retrieve it the same way.
8.5 Summary
PyCharm brings programming tools into one workspace. Its editor helps you read and write code, while its other tools let you run programs, investigate errors, and manage projects. Each project uses a selected Python interpreter, often through a virtual environment that keeps its packages separate from other projects.
git records your project’s history. Staging selects the changes for the next commit; committing records them with a message. Small, regular commits make it easier to understand how your program developed and return to earlier work.
GitHub hosts a remote copy of your repository. Pushing sends your commits to GitHub, while pulling fetches remote commits and integrates them into your local copy. In COMP 1510, pushing your work to the assigned repository makes it available to your instructors for assessment.
8.6 References and Further Reading
- Pro Git, the definitive book on git, free to read online
- Official git documentation
- GitHub Docs
- PyCharm documentation
9 Image Credits
The images in this book are either public domain or used under Creative Commons licences. Source links go to the image’s page on Wikimedia Commons, where the full attribution information lives.
- Ada Lovelace portrait: public domain. Source
- Charles Babbage portrait: public domain. Source
- Bacon alphabet scan: public domain. Source
- Jacquard loom photograph: by Stephencdickson, CC BY-SA 4.0. Source
- Vacuum tubes photograph: by Stefan Riepl, CC BY-SA 2.0 DE. Source