Session 1 — Chapter 1: Introduction · Chapter 2: Variables and Simple Data Types
>>> print("Hello world!")
Hello world!Setting up the environment · Installing a code editor
Running · Troubleshooting · Terminal (Windows) · macOS & Linux
Naming · Avoiding name errors · Variables as labels
Case · f-strings · Whitespace · Stripping · Syntax errors
Integers · Floats · Int vs float · Underscores · Multiple assignment · Constants
How to write · What to write · Exercises · Chapter summary
What learners will be able to do after this session:
Explain where Python came from, its major release milestones, and the design principles codified in the Zen of Python (PEP 20).
Install Python 3, choose an editor, and run a .py script from both an editor and a terminal on Windows, macOS, and Linux.
Create and name variables correctly following PEP 8 conventions; read and interpret a traceback (NameError, SyntaxError).
Manipulate strings (case methods, f-strings, strip), work with int and float types, define constants, and write purposeful comments.
Python was conceived in the late 1980s by Guido van Rossum at CWI (Centrum Wiskunde & Informatica) in the Netherlands. Before creating Python, van Rossum worked on the ABC language team at CWI. Python inherited several key ideas from ABC: indentation for grouping blocks, high-level built-in types, and an emphasis on readability.
In his own words, he built "a simple virtual machine, a simple parser, and a simple runtime," using indentation for statement grouping and a small set of core data types: dictionaries (hash tables), lists, strings, and numbers.
Ngắn - Độc - Vui
Many people assume Python is named after the large constrictor snake — a reasonable guess given the reptile logo used in some contexts.
This is not the actual origin of the name.
The name comes from the BBC comedy series Monty Python's Flying Circus (1969–1974). Guido van Rossum was a fan of the show and wanted a name that was short, unique, and slightly irreverent.
Van Rossum started the interpreter as a hobby project during Christmas week of December 1989. The official Python FAQ confirms this naming origin.
Source: docs.python.org/3/faq
Posted to alt.sources. Classes with inheritance, exception handling, functions, core types (list, dict, str), module system.
Added functional programming tools: lambda, map, filter, reduce.
List comprehensions, cycle-detecting garbage collector, Unicode support.
"Python 3000" / "Py3K" — intentionally not backward compatible with 2.x. A clean break.
Python 2 reached end of life. No further security updates or bug fixes.
This course uses Python 3 exclusively. The table below summarizes the key differences. Python 2 has been end-of-life since January 1, 2020.
>>> import thisBeautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Readability counts.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one— and preferably only one —obvious way to do it.
"Errors should never pass silently" — silent failures hide attacks and bugs. In security code, every exception must be logged or handled deliberately.
"Explicit is better than implicit" — magic behavior obscures what code actually does. Secure code should make data flows, permissions, and error paths visible and auditable.
These two aphorisms underpin defensive programming practices that will appear throughout this course.
Source: peps.python.org/pep-0020
Two PEP 20 principles that decide whether your code is defensible.
Never swallow errors.
Common student habit — dangerous code ❌
try:
verify_token(user_token) # Authenticate the user
except:
pass # Ignore so the program doesn't crashSecurity impact: Forged tokens or brute-force attempts trigger errors that the system silently swallows. Admins lose all monitoring traces (a blind spot) and never know an attack is underway.
Catch every exception specifically and log or audit it clearly. If an error is deliberately ignored, give an explicit justification (unless explicitly silenced).
Be explicit, not implicit.
Common student habit — dangerous code ❌
Relying on "magic" behavior, such as implicitly assuming data types or implicit permissions (for example, if no role is passed, silently assume the user role).
Security impact: Attackers can exploit implicit behavior to disrupt the data flow or escalate privileges (privilege escalation).
Make permission checks, data types, and error paths explicit, line by line. The more explicit the code, the easier it is for the whole team to run code reviews and audits and spot vulnerabilities.
GitHub Octoverse 2024 reports that Python overtook JavaScript as the most-used language on GitHub — a significant milestone reflecting Python's dominance in data science, automation, and security tooling.
Python also appears at or near the top of the TIOBE Index, a long-running measure of language popularity based on web search volume.
Sources: GitHub Octoverse 2024 · TIOBE Index
Packet crafting and analysis
SQL injection testing
Memory forensics
Network protocol library
Python is commonly called an interpreted language. More precisely, CPython (the reference implementation, written in C) compiles source to bytecode, then interprets that bytecode on a virtual machine. The bytecode is cached in __pycache__.
import dis
dis.dis('print("hi")')
# → bytecode instructionsThe coursebook (2022) required Python 3.6 or newer (f-strings were introduced in 3.6). Current best practice is to install a version that is still actively supported. The official Python Developer's Guide lists all versions and their end-of-life dates.
New features accepted
Only bug fixes
Security patches only
No further updates
Python 3.11 is documented as 10–60% faster than 3.10 (average 1.25× on the standard benchmark suite). For computationally intensive security tools, choosing a current version matters.
$ python3
Python 3.x.x ... on linux
Type "help", "copyright", "credits" or "license"
for more information.
>>> print("Hello Python interpreter!")
Hello Python interpreter!
>>> exit()The prompt >>> signals Python is waiting for a statement. The line beneath is the output. REPL stands for Read–Eval–Print Loop.
A virtual environment keeps each project's packages separate from the system Python and from other projects. This prevents version conflicts between dependencies.
For security work, tools such as Scapy and Impacket pin specific dependency versions. Isolation avoids conflicts and keeps the system Python clean.
python3 -m venv .venv
source .venv/bin/activate # macOS/Linux
.venv\Scripts\activate # Windows
pip install requestsSource: docs.python.org/3/library/venv
Each project folder gets its own .venv directory containing a private copy of the Python interpreter and installed packages. Activating a venv changes the shell's PATH so the project's Python is used first.
The coursebook uses Sublime Text. The table below compares it with editors common in 2024.
Name it python_work — lowercase letters and underscores, following Python naming conventions.
Create hello_world.py inside the folder. The .py extension tells both the editor and the OS that this is Python source code.
print("Hello Python world!")Save the file. The program is now ready to run.
python_work/
└── hello_world.pyIf this one line runs without error, the installation and editor are correctly configured. The "Hello, World" test is a quick sanity check used in virtually every programming course and environment setup guide.
Navigate to Tools → Build (shortcut: Ctrl+B on Windows, Cmd+B on macOS). The output panel at the bottom of the editor shows:
Hello Python world!
[Finished in 0.1s]Click the ▶ Run Python File button in the top-right toolbar, or open the integrated terminal and type:
python3 hello_world.pyOutput appears in the terminal panel below the editor.
print("Hello Python world!" File "hello_world.py", line 1
print("Hello Python world!"
^
SyntaxError: '(' was never closedFile "hello_world.py", line 1 — identifies exactly where the error occurred.
The line is printed with a caret ^ pointing to the location Python identified as problematic.
SyntaxError: '(' was never closed — the error class and a human-readable description.
A traceback is Python's structured report of where and why execution failed. Reading it bottom-up is the first debugging step. Python 3.10+ provides more precise error messages.
Source: docs.python.org/3/whatsnew/3.10
hello_world.py — no need to reinstall software.AI coding assistants can explain a traceback and suggest a fix. However, the learner must still:
Understanding the error — not just applying a patch — is the goal.
C:\> cd Desktop\python_work
C:\Desktop\python_work> dir
hello_world.py
C:\Desktop\python_work> python hello_world.py
Hello Python world!cdChange directory to the folder containing the file.
dirList files in the current directory — confirms hello_world.py is present before running.
python hello_world.pyInvoke the Python interpreter and pass the script as an argument.
~$ cd Desktop/python_work/
~/Desktop/python_work$ ls
hello_world.py
~/Desktop/python_work$ python3 hello_world.py
Hello Python world!Created by Guido van Rossum (1989–1991), named after Monty Python, guided by PEP 20 (Zen of Python).
Python 2 reached end of life on January 1, 2020. All code in this course targets Python 3.
CPython compiles source to bytecode and runs it on a virtual machine — not direct machine code execution.
REPL (>>>) for experiments; .py scripts for programs. Both produce the same output for the same code.
Errors produce tracebacks — read file name, line number, and error type first. Always work bottom-up.
What really happens when hello_world.py runs? The interpreter reads the file, identifies each token: print followed by parentheses → call the function and display what is inside the parentheses.
print("Hello Python world!")
# ↑ function name ↑ string literal ↑ call parenthesesmessage = "Hello Python world!"
print(message)
message = "Hello Python Crash Course world!"
print(message)Hello Python world!
Hello Python Crash Course world!The variable name message is bound to a value (the string). The value can be changed at any time; Python always uses the current binding.
No type declaration is needed. The type belongs to the value, not the name.
Only letters, digits, underscores; cannot start with a digit.message_1 ✔ — 1_message ✘
No spaces in names.greeting_message ✔ — greeting message ✘
Cannot be a keyword: class, if, for, import, …
import keyword
print(keyword.kwlist)Short but descriptive: name > n; student_name > s_n
Use lowercase_with_underscores (snake_case)
Avoid l (lowercase L) and O (uppercase o) — confused with 1 and 0
Avoid shadowing built-in names: print, list, str
Sources: PEP 8 — Naming · docs.python.org — keyword
message = "Hello Python Crash Course reader!"
print(mesage)Traceback (most recent call last):
File "hello_world.py", line 2, in <module>
print(mesage)
NameError: name 'mesage' is not defined.
Did you mean: 'message'?line 2 — Python found the error on line 2.
print(mesage) — the misspelled name that Python cannot find.
NameError — the name was never defined in the current scope.
A box named message contains the string. Implies the variable stores a copy of the value.
The object "Hello" lives in memory. The name message is a label — a reference — pointing to that object.
a = "python"
b = a
print(a is b) # True — same object
print(id(a) == id(b)) # True — same memory addressAssignment binds a name to an object; it does not copy the object. Both a and b refer to the same string in memory.
Sources: Naming and Binding · Data Model
x = 42
print(type(x)) # <class 'int'>
x = 3.14
print(type(x)) # <class 'float'>
x = "42"
print(type(x)) # <class 'str'>The same name x is rebound to values of different types. Python determines the type at runtime, not at compile time.
A string is a sequence of characters. In Python 3, str stores Unicode text — both single and double quotes are valid delimiters.
"This is a string."
'I said, "Python!"''This is also a string.'
"Python's syntax is clean."In Python 3, str natively stores Unicode. Text such as "An toàn thông tin" works without special handling.
Source: docs.python.org — str
name = "ada lovelace"
print(name.title()) # Ada Lovelace
print(name.upper()) # ADA LOVELACE
print(name.lower()) # ada lovelacename . title ( )
# ↑ variable
# ↑ dot operator
# ↑ method name
# ↑ parentheses (arguments here, empty)Source: docs.python.org — String Methods
allowed_domain = "ptit.edu.vn"
user_domain = "PTIT.EDU.VN"
print(user_domain == allowed_domain)
# False — bypass!
print(user_domain.lower() == allowed_domain)
# True — correctNormalize case (and whitespace — see 2.2.4) before comparing. Otherwise, allow-lists and block-lists can be bypassed using case variations such as "Admin" vs "admin".
Domain names are case-insensitive by RFC 4343 — PTIT.EDU.VN and ptit.edu.vn refer to the same host.
Any security check that compares strings — usernames, email domains, file extensions, command names — should normalize case first.
Store values in a canonical form (e.g., always lowercase) so lookups are consistent and predictable.
first_name = "ada"
last_name = "lovelace"
full_name = f"{first_name} {last_name}"
message = f"Hello, {full_name.title()}!"
print(message)
# Hello, Ada Lovelace!Prefix the opening quote with f (or F).
Expressions inside { } are evaluated and their results inserted into the string.
Any valid Python expression works inside the braces — including method calls like .title().
PEP 498 added f-strings as a concise, readable alternative to str.format(). They are the recommended approach for string interpolation in this course.
port = 443
print(f"{port=}")
# port=443The = specifier inside braces prints both the expression and its value — useful for quick debugging.
Source: PEP 498 — f-strings
Sources: PEP 3101 · PEP 498 · Python 3.8 — f-string debug specifier
print("Python")
# Python
print("\tPython")
# Python
print("Languages:\nPython\nC\nJavaScript")
# Languages:
# Python
# C
# JavaScript
print("Languages:\n\tPython\n\tC\n\tJavaScript")
# Languages:
# Python
# C
# JavaScript>>> favorite_language = ' python '
>>> favorite_language.rstrip()
' python'
>>> favorite_language.lstrip()
'python '
>>> favorite_language.strip()
'python'
>>> favorite_language
' python 'Removes leading (left) whitespace only
Removes whitespace from both ends
Removes trailing (right) whitespace only
Source: docs.python.org — str.strip
username = " admin \n"
print(username == "admin") # False
print(username.strip() == "admin") # TrueWithout stripping, a trailing newline or leading space causes a string comparison to fail — a common source of authentication bugs.
url = "https://ptit.edu.vn"
print(url.removeprefix("https://"))
# ptit.edu.vnmessage = 'One of Python's strengths is
its diverse community.' File "apostrophe.py", line 1
message = 'One of Python's strengths ...
^
SyntaxError: unterminated string literalPython interprets the apostrophe in Python's as the closing quote, leaving the rest of the line as unexpected tokens.
message = "One of Python's strengths is
its diverse community."
print(message)>>> 2 + 3
5
>>> 3 - 2
1
>>> 2 * 3
6
>>> 3 / 2
1.5
>>> 3 ** 2
9
>>> 10 ** 6
1000000
>>> 2 + 3*4
14
>>> (2 + 3) * 4
20Source: docs.python.org — Numeric Types
print(2 ** 16) # 65536 — TCP/UDP port space (0–65535)
print(2 ** 32) # 4294967296 — IPv4 address space
print(2 ** 128) # exact big integer — IPv6 / 128-bit keysprint(0xFF, 0b1010, 0o17) # 255 10 15
print(hex(255), bin(10)) # 0xff 0b1010Hexadecimal (0x), binary (0b), and octal (0o) literals are commonly used in low-level security and networking code.
Python's arbitrary-precision integers let code handle cryptographic-size numbers natively — no special library needed for basic arithmetic on RSA moduli or large primes.
The built-in pow(base, exp, mod) performs modular exponentiation efficiently — a core operation in RSA and Diffie-Hellman.
pow(2, 100, 1000000007) # fast modular expSources: RFC 791 — IPv4 · RFC 8200 — IPv6 · docs.python.org — pow()
>>> 0.1 + 0.1
0.2
>>> 2 * 0.1
0.2
>>> 0.2 + 0.1
0.30000000000000004
>>> 3 * 0.1
0.30000000000000004Floats use IEEE 754 double precision. Some decimal fractions — including 0.1 — cannot be represented exactly in binary, producing small rounding errors.
This occurs in all languages that use IEEE 754, not only Python.
Sources: docs.python.org — Floating Point · decimal module · math.isclose
>>> 4 / 2
2.0
>>> 1 + 2.0
3.0
>>> 2 * 3.0
6.0
>>> 3.0 ** 2
9.0Division / always returns a float, even if the result is a whole number.
Mixing int and float in any operation returns a float.
Use // for integer (floor) division: 7 // 2 → 3.
Source: docs.python.org — Numeric Types
universe_age = 14_000_000_000
print(universe_age) # 14000000000
MAX_FILE_SIZE = 10_485_760 # 10 MiB in bytes
print(1000 == 1_000 == 10_00) # TrueUnderscores are purely cosmetic. Python ignores them entirely when storing the numeric value. The grouping can be placed anywhere — the conventional 3-digit grouping matches standard number formatting.
Port ranges, address space sizes, memory sizes — any value where digit grouping aids reading.
Also works for floats: 3.141_592_653 is valid.
Combine with ALL_CAPS convention (Section 2.3.6) for readable constant definitions.
Available since Python 3.6 (PEP 515).
x, y, z = 0, 0, 0
host, port = "127.0.0.1", 8080
print(host, port) # 127.0.0.1 8080
a, b = 1, 2
a, b = b, a # swap without temp variable
print(a, b) # 2 1x, y = 1, 2, 3
# ValueError: too many values to unpack (expected 2)x, y, z = 0, 0, 0 is more concise than three separate assignment lines.
host, port = "127.0.0.1", 8080 — a common pattern in network programming and security tools.
The swap a, b = b, a is idiomatic Python — no temporary variable is needed because the right side is fully evaluated before assignment.
MAX_CONNECTIONS = 5000
DEFAULT_TIMEOUT = 3.0
API_BASE_URL = "https://api.example.com"from typing import Final
MAX_LOGIN_ATTEMPTS: Final = 5Static checkers such as mypy will flag any attempt to reassign a Final name — enforcement happens offline, not at runtime.
Sources: PEP 8 — Constants · PEP 591 — Final
# Say hello to everyone.
print("Hello Python people!")Hello Python people!Everything after # on a line is ignored by the interpreter. The comment does not appear in the output.
Sources: PEP 8 — Comments · PEP 257 — Docstrings
x = x + 1 # add 1 to xThe comment adds no information beyond what the code already says. A reader who can read Python gains nothing from it.
# Retry once more because the remote host
# may drop the first SYN under load.
retries = retries + 1This comment explains the reason for the code — information that cannot be inferred from the syntax alone.
The code already describes what happens. Comments should capture the intent, rationale, or approach.
Removing extra comments later is easier than reconstructing missing ones weeks later.
A comment that contradicts the code is worse than no comment — it actively misleads the reader (PEP 8).
Most software is written and maintained by teams. Clear comments are expected in professional and open-source projects.
Source: PEP 8 — Comments
Assign a message to a variable and print it.
Change the variable's value and print both messages.
Store a name; print "Hello Eric, would you like to learn some Python today?"
Print a name in lower, upper, and title case.
Print a quote with its author, including quotation marks.
Store the author in famous_person and the sentence in message.
Use \t and \n around a name; demonstrate lstrip(), rstrip(), strip().
Write four operations using +, -, *, / whose result is 8.
Build and print a message containing a number using an f-string.
Add a header comment and explanatory comments to two earlier programs.
Run import this in the REPL and read the full output.
History, naming, and design principles of Python (PEP 20 — Zen of Python)
Installing Python 3, choosing an editor, REPL vs .py scripts
Running programs from editor and terminal; reading tracebacks
Variables as labels; naming rules (PEP 8); NameError
Strings: case methods, f-strings, escape sequences, strip, quote handling
Numbers: int (arbitrary precision), float (IEEE 754), //, %, underscores, multiple assignment, constants
Comments: #, docstrings, explain "why" not "what"
Lists — creating, indexing, slicing, modifying
If Statements — conditional logic and branching
Eric Matthes, Python Crash Course, 2nd ed., No Starch Press, 2019
Official documentation: docs.python.org/3
Python Fundamentals & Simple Types