The Basics of Python Syntax

Introduction

Welcome to the first lesson of this Python Fundamentals course. This lesson is designed to lay the groundwork by briefly introducing you to the core concepts of Python programming. While subsequent lessons will explore these topics in greater detail, this introduction plays an important role in your learning journey.

This lesson provides a fast-track approach to starting to develop your Python programming. By focusing on the essential syntax and concepts, you’ll quickly be able to read and write basic Python code. Should you chose to do so, it will enable you to employ the effective strategy of learning the basics first, and then expanding your knowledge, as-needed, through a practical projects.

In addition to offering a quick start, this lesson helps solidify your understanding of basic concepts, making it easier to grasp more advanced topics later on. A strong foundation in these essentials will pave the way for a smoother learning experience as you encounter more complex ideas.

Moreover, this introduction addresses the challenge of navigating mutually dependent topics. Often, mastering one concept requires familiarity with another, such as understanding Python container objects before tackling for loops, and vice versa. By presenting these fundamentals early, this lesson prepares you to approach later topics with greater confidence.

In addition to the material here, as you progress to more in-depth lessons, you’ll find brief explanations or links to related concepts included. This interconnected approach ensures you can easily reference and revisit foundational material as needed, reinforcing your understanding and supporting your ongoing learning.

By the end of this lesson, you’ll have the essential tools to begin your Python programming path, setting a solid foundation for further exploration and more advanced challenges.

Note for Experienced Learners: This lesson is designed for those who are new to Python or programming in general. If you already have significant experience with Python, you may find the material in this lesson familiar. In that case, you can skip this lesson and go to the next one or, alternatively, review the summary section at the end to ensure you haven’t missed any key points.

What is Syntax?

In programming, syntax refers to the set of rules that defines the combinations of symbols that are considered to be correctly structured programs in a particular language. Just as grammar governs how words are arranged in a sentence to make sense in human languages, syntax governs how code must be written for the computer to interpret it correctly.

In Python, the syntax determines how you should write and format your code, including the use of spaces, indentation, punctuation, keywords, and more. If the syntax rules are not followed, Python will raise an error, preventing the program from running.

Understanding Python’s syntax is essential because it ensures that your code is not only correct and functional but also readable and maintainable. Well-structured code adheres to Python’s syntax rules and follows best practices, making it easier for you and others to understand and modify it later.

The following sections will introduce you to the basic components of Python’s syntax, laying a solid foundation for more the more advanced lessons that come next.

Keywords

Keywords are reserved words in Python that have special meanings. They form the foundation of Python’s syntax and cannot be used for any other purpose in your code, such as for variable or function names, as you’ll see in the following sections.

These words are reserved because they are integral to Python’s structure and are used to define the logic and flow of a program.

Some common Python keywords that you’ll encounter in this lesson are def, return, if, elif, else, and, or, not, for, and while.

Variables

Variables are important building blocks in Python programming. They are used to store data that can be referenced and manipulated throughout your code. You can think of a variable as a labeled container that holds a value, which you can easily access or change whenever needed.

Declaring Variables

In Python, you declare a variable by simply assigning a value to it using the equals sign =.

Each variable has a type, which is the kind of data it holds. But, there is no need to explicitly declare the type of variable, like in some other programming languages, because Python is dynamically typed. This means that the type of the variable is inferred from the value you assign to it.

Example:

age = 25
name = "Alice"
is_student = True

In the example above:

  • age is a variable that holds the integer value 25 (line 1).
  • name is a variable that holds the string value “Alice” (line 2).
  • is_student is a variable that holds the Boolean value True (line 3).

Changing Variable Values

Variables can be reassigned to new values at any time. When you assign a new value to a variable, the old value is replaced. The equals sign = is also used to reassign values to variables.

counter = 10
counter = 20

In the example above, the variable counter initially holds the value 10 (line 1). After reassignment, it holds the value 20 (line 2).

Variable Types

Although Python does not require you to declare the type of a variable, it’s important to understand that every variable in Python has a type, which is automatically determined based on the value assigned to it. Common types include:

  • Integers (int type): Whole numbers, e.g., 5, 100, -42.
  • Floating-Point Numbers (float type): Numbers with decimal points, e.g., 3.14, -0.001.
  • Strings (str type): Sequences of characters, e.g., “hello”, “Python”, which are created with surrounding quotes. Strings can be formed with either double quotes ("), or single quotes ('), e.g. 'hello'.
  • Booleans (bool type): Logical true or false values, represented in Python by True, or False values.

Printing to the Console

Printing to the console (or terminal) is an important capability.

It allows a program to:

  1. Output data and messages about program execution.
  2. Provide debugging information, allowing the programmer to fix problems.
  3. Interact with users in command-line programs.

To print data to the console in Python, you use the print() function. The basic syntax of the print() function is straightforward: simply place the data you want to print inside parentheses.

Example:

print("Hello, World!")

Output:

Hello, World!

In the example above, the string “Hello, World!” is passed to the print() function, and when the code is executed, the string’s text is displayed in the console.

As you can see, the print() function is also useful in lessons such as this one for showcasing the output of example code.

The print() function can also print various data types, variables, and combinations of those. Additionally, it offers different formatting options. You’ll encounter some more of print()‘s various features throughout this course.

Functions

Functions are a key feature in Python that allow you to organize your code into reusable blocks. By defining a function, you can encapsulate a specific task or a group of related tasks into a single unit, which can then be easily invoked whenever needed. This not only makes your code more modular and easier to maintain but also helps reduce redundancy.

Defining a Function

To define a function in Python, you use the def keyword, followed by the function name and a pair of parentheses () and a colon :. Inside the parentheses, you can optionally include parameters that allow you to pass data into the function.

The function’s code block starts below the colon : and is indented.

Example:

def greet():
    print("Hello,")
    print("Welcome to Python!")

In the example above, a function named greet is defined. When called, it prints the message “Hello, welcome to Python!” to the console. Notice the indentation of the print() statement, which indicates that it is part of the function.

Calling a Function

Once a function is defined, you can execute (or “call”) it by writing its name followed by parentheses. The function call will execute the function’s code block at the spot the call is made.

Example:

def greet():
    print("Hello,")
    print("Welcome to Python!")

greet()

Output:

Hello, welcome to Python!

In the example above, the greet() function is called (line 5), which triggers the print() statement inside the function, resulting in the output.

Functions with Parameters

Functions can also take parameters, which are values passed into the function to customize its behavior. You define parameters inside the parentheses during function definition, and then provide corresponding arguments when calling the function.

Example:

def start_a_conversation_with_person(name):
    print(f"Hello, {name}!")
    print(f"How are you?")

start_a_conversation_with_person("Alice")

Output:

Hello, Alice!
How are you?

In the example above, the start_a_conversation_with_person() function takes one parameter, name (line 1). When the function is called with the argument “Alice”, it prints a personalized greeting.

Parameters make functions more flexible, allowing them to handle different inputs.

In computer programming, the term “parameters” refers to the variables declared in a function’s definition, while “arguments” are the actual values passed to the function when it is called. These two terms are often a confused.

Return Values

Functions can also return a value using the return statement. This allows the function to output a result that can be used later in your code.

Example:

def add(a, b):
    return a + b

result = add(5, 3)
print(result)

Output:

8

In the example above, the add() function (lines 1-2) takes two parameters, a and b, adds them together, and returns the result (line 2). The returned value is then stored in the variable result (line 4) and printed to the console (line 5).

Why Use Functions?

Functions are essential for writing clean, efficient, and maintainable code. They allow you to:

  • Organize your code by breaking down complex tasks into smaller, manageable pieces.
  • Reuse code by defining a function once and calling it whenever needed.
  • Reduce Errors by eliminating the need to write the same code multiple times, and isolating code into smaller chunks.
  • Enhance readability by giving descriptive names to code blocks, making it easier to understand what the code does.

As you continue learning Python, you’ll find that functions are a critical part of programming that can greatly improve your coding efficiency and effectiveness.

Indentation and Its Significance In Python

In many programming languages, indentation is often used to improve readability but has no impact on how the code functions. Python, however, is different. In Python, indentation is not just for aesthetics—it is a fundamental part of the language’s syntax. Proper indentation is crucial, as it defines the structure of the code and determines how it is executed.

Why Indentation Matters

Python uses indentation to indicate blocks of code. A block of code is a group of statements intended to be executed together. For example, when you define a function, all the code within that function must be indented to show that it belongs to that function.

Example:

def greet():
    print("Hello, welcome to Python!")
    print("Let's learn about indentation.")

In the example above, the two print() statements (lines 2-3) are indented to indicate that they are part of the greet() function. Without proper indentation, Python would not understand which statements belong to the function.

To better understand how indentation works, let’s look at the same code above, but rewritten with slightly different indentation.

Example:

def greet():
    print("Hello, welcome to Python!")
print("Let's learn about indentation.")

Output:

Let's learn about indentation.

In the code above, the second print statement is un-indented (line 3). Now, only the first print is inside the greet() function (line 2). When you run the code above, which doesn’t have a function call, it prints “Let’s learn about indentation.”, because the print statement is outside the function and executes without a function call. If you were to call greet() it would print “Hello, welcome to Python!” and nothing else.

The code above also demonstrates the biggest drawback of indent-based syntax – vulnerability to subtle bugs. By accidentally deleting a few blank spaces, you can completely change the structure of the code without any complaints (syntax errors) from Python.

In contrast, other programming languages, rely on a keyword (such as end) to close blocks of code or brackets to enclose them. This avoids bugs because omitting an end or a closing bracket results in a syntax error.

The Rules of Indentation

Python requires the number of spaces you use for indentation to be consistent within a block of code. Mixing spaces and tabs or using a different number of spaces in the same block will lead to an IndentationError.

Inconsistent indentation would look like this:

def some_function():
    print("This will cause an error.")
  print("This line is not properly indented.")

In the above incorrect example, the second print() statement has fewer spaces than the first one, causing Python to raise an error.

By convention, Python uses 4 spaces per indentation level. While it is technically possible to use a different number of spaces, sticking to 4 spaces is recommended because it makes your code more readable and consistent with Python’s community standards.

Common Errors Due to Improper Indentation

Improper indentation is a common source of errors for beginners in Python. The most common error related to indentation is the IndentationError, which occurs when Python detects incorrect indentation in your code.

Here are some common mistakes:

  • Mixing Spaces and Tabs: Python does not allow mixing spaces and tabs for indentation. Always choose one method and stick with it.
  • Inconsistent Indentation: Using a different number of spaces for indentation within the same block will lead to errors.
  • Incorrectly Indented Statements: Forgetting to indent or indenting when it is not needed can cause the program to behave unexpectedly. This can be especially harmful when an accidental indentation change does not cause a syntax error and therefore goes unnoticed.

Comments

A comment is text within your code that is not executed by the program. Comments are used to leave notes, explanations, or reminders for yourself or others who may read your code in the future.

Single-Line Comments

The most common type of comment in Python is the single-line comment. These are created by placing a # symbol at the beginning of the line. Everything after the # on that line will be ignored by Python.

Example:

# This is a single-line comment explaining the code below
name = "Alice"  # This a more specific comment about this line

In the example above:

  • The first line is a comment that spans the entire line. This type of comment typically explains sections of code below it.
  • The comment at the end of the second line explains what that specific line of code is doing.

Multi-Line Comments

While Python does not have a dedicated syntax for multi-line comments, you can create them by using multiple single-line comments, or by using a multi-line string (with triple quotes) that isn’t assigned to any variable or used in any operation. The latter method is often used as a workaround for creating multi-line comments that document functions.

The next example demonstrates using multiple single-line comments.

Example:

# This is a multi-line comment
# that spans multiple lines.
# It explains something more complex.

And the next example show a multi-line string comment.

Example:

"""
This is another way to create
a multi-line comment using a
multi-line string. This string is not assigned
to any variable, so it is ignored by Python.
"""

'''
Multi-line comment strings can also be
enclosed with three single quotation markes.
'''

""" The new line after and before the tripel quotes
is optional. """

Multi-line strings can also be formed with triple singe-quote characters, i.e. '''.

The multi-line string method, while not technically a comment, is treated as such because the string is not used or printed.

Why Use Comments?

Comments play an important role in making your code more understandable, both for your future self and others who may need to work with it. Good commenting practices can enhance the readability and maintainability of your code.

Here’s why comments are important:

  • Clarification: Comments can explain why certain decisions were made in the code, especially when the reasoning might not be immediately obvious.
  • Documentation: They serve as a form of documentation, helping others (or yourself at a later date) quickly understand what the code does.
  • Debugging: Comments can temporarily disable code during debugging, allowing you to isolate issues without deleting code.

Best Practices for Writing Comments

While comments are useful, it’s important to use them effectively. Here are some best practices for writing comments in Python:

  • Be concise: Keep comments short and to the point. They should provide value without cluttering the code.
  • Avoid obvious comments: Don’t state the obvious. For example, avoid comments like # Assign 10 to x when the code x = 10 is self-explanatory.
  • Keep them up-to-date: Ensure that your comments are updated when you modify the corresponding code. Outdated comments can be misleading and confusing.
  • Use comments to explain why, not what: Focus on explaining the reasoning behind your code, rather than describing what the code does. The code itself should be clear enough to explain what it does.

Operators

Operators are symbols in a computer program that perform operations on variables and values. They are essential for performing calculations, comparisons, and logical operations within your code.

Python provides a variety of operators, each serving a specific purpose. The following sections will give you a brief survey of what they can do, showcasing some of them in the examples.

Arithmetic Operators

Arithmetic operators are used to perform basic mathematical operations such as addition, subtraction, multiplication, division and more.

Example:

x = 10
y = 5

# Addition
result = x + y
print(result)  # --> 15

# Subtraction
result = x - y 
print(result)  # --> 5

# Multiplication
result = x * y  
print(result)  # --> 50

# Division
result = x / y 
print(result)  # --> 2.0

Output:

15
5
50
2.0

In the example above, various arithmetic operations are performed on the variables x and y. The results of these operations are stored in the variable result and then printed.

Comparison Operators

Comparison operators are used to compare two values. These operators return a Boolean value (True or False) based on the comparison.

Example:

x = 10
y = 5

# Equal to
print(x == y)  # --> False

# Not equal to
print(x != y)  # --> True

# Greater than
print(x > y)  #  --> True

# Less than
print(x < y)  # --> False

# Greater than or equal to
print(x >= y)  #  --> True

# Less than or equal to
print(x <= y)  #  --> False

Output:

False
True
True
False
True
False

In the example above, various comparison operators are used to compare the values of x and y. The output of each comparison is a Boolean value that indicates whether the comparison is true or false.

Logical Operators

Logical operators are used to combine conditional statements. Python provides three logical operators: and, or, and not.

Example:

x = 10
y = 5
z = 0

# and
print(x > y and y > z)  # --> True

# or
print(x > y or y < z)  # --> True

# not
print(not(x > y))  # --> False

Output:

True
True
False

In the example above, logical operators are used to evaluate multiple conditions. The and operator returns True if both conditions are True, the or operator returns True if at least one condition is True, and the not operator reverses the Boolean value.

Assignment Operators

Assignment operators are used to assign values to variables. The most basic assignment operator is the equals sign =, which assigns the value on its right-hand side to a variable on the left-hand side.

Python also provides augmented assignment operators (a.k.a. compound assignment operators) for performing operations and reassigning the variable involved to the result in a single step.

Example:

# The basic assignemt operator
x = 10  # x is now 10

# Add and assign
x += 5  # x is now 15
print(x)

# Subtract and assign
x -= 3  # x is now 12
print(x)

# Multiply and assign
x *= 2  # x is now 24
print(x)

# Divide and assign
x /= 4  # x is now 6.0
print(x)

Output:

15
12
24
6.0

In the example above, first the basic assignment operator = assigns a value to the variable x. Then various augmented assignment operators perform arithmetic operations on the variable x and update its value in a single step.

Operator Overloading

Some operators have different meanings and effects depending on what data types they are used with. This concept is known as overloading because the phrase “overloaded meaning” means having more than one meaning. 🙂

Example:

greeting = "Hello"
phrase = greeting + " there!"
print(phrase)

Output:

"Hello there!"

In the example above, the plus + operator is used to concatenate two strings (line 1). The first string is in the variable greeting, while the other is the string ” there!”, giving the combined phrase “Hello there!”. As you can see, while + means arithmetic addition when used with numbers, when used with strings, it means joining them together.

Not all operators work with all data types. For instance, while + works with strings, the division operator does not.

Example:

"Hello" / "there"

Output:

TypeError: unsupported operand type(s) for /: 'str' and 'str'

The division in the example above results in an error because / is not defined for two strings.

In some cases, operators work with two different data types, while in other cases they don’t.

Example:

"Hello " * 3

Output:

Hello Hello Hello

The example above demonstrates multiplication of a string and an integer. This results in the string repeated the number of times specified by the integer.

Multiplying a string by a floating point number, however, does not work because fractional repetitions of strings don’t have a clearly defined meaning.

Example:

"Hello " * 0.5

Output:

TypeError: can't multiply sequence by non-int of type 'float'

Statements vs. Expressions

In most programming languages, and Python as well, there are two types of things you can write in code: statements and expressions. A brief explanation of the difference is that statements perform actions, while expressions have a value. Understanding statements and expression is fundamental to learning a programming language and helps you write code that’s correct.

What is an Expression?

An expression in Python is a piece of code that has a value. It can be as simple as a single variable or a more complex combination of variables, operators, and function calls that ultimately produces a value. The key point about expressions is that they always return a value.

The following example showcases a few different type of expressions.

Example:

# A single value
42

# A variable
x

# A combination of variables and operators
x + y

# A function call that returns a value
len("Python")

In the examples above:

  • The number 42 is a basic expression that evaluates to the integer 42.
  • The variable x is an expression that evaluates to whatever value x holds.
  • The expression x + y will return a value that is the result of adding x and y.
  • The function call len("Python") evaluates to the integer 6, which is the length of the string "Python".

An important characteristic of expressions is that they can be combined with other expressions to form more complex expressions. Furthermore, they can do so on the same line of code.

Example:

print(len("Python") * 2)

Output:

12

In the example above, the function call len("Python") is an expression that results in the value 6. Therefore, it can be combined with another expression, 2, using the * operator, to form the larger expression len("Python") * 2.

What is a Statement?

A statement, on the other hand, is a complete unit of code that performs an action. Unlike expressions, statements do not return a value. they are executed by Python and may cause some side effects, such defining a function or altering the value of a variable.

Examples:

# An assignment statement
x = 10

# A function definition statement
def greet():
    print("Hello!")

# A conditional statement
if x > 5:
    print("x is greater than 5")

In the examples above:

  • The assignment x = 10 assigns the value 10 to the variable x. This is a statement because it performs an action (assignment), but it does not produce a value.
  • The def keyword is used to define a function, which is a statement that sets up a function but doesn’t have a resulting value.
  • The if statement checks a condition and, based on the result, executes a block of code or not.

Unlike expressions, Python statements can’t be combined on the same line. They can only appear on separate rows, as you can see in the example above.

Expressions That Are Also Statements

In Python, functions can do things and return a value. Actually, even functions that don’t explicitly return a value with return, implicitly return the value None.

None is a value that ironically means no value, but it’s still a value!

The print() statement, for instance, doesn’t return any meaningful value, as it’s always None. And since its only purpose is to do something – print to the console, print() is often referred to as a print statement. Although, technically, print() is an expression that has the value None, which can be combined with other expressions.

Example:

x = print("I'm returning None.") or True
print(x)

Output:

True

In the example above the print() function call is used in a compound expression (line 1), which is assigned to the variable x, and printed (line 2). This proves that the print() call is an expression.

Combining Statements and Expressions

In Python, you can often find expressions within statements. For example, in an assignment statement, the right-hand side of the equals sign (=) is usually an expression, while the entire line is a statement.

Example:

y = x + 5

In the example above, x + 5 is an expression that has a value, and y = x + 5 is a statement that assigns this value to the variable y.

Why the Distinction Matters

Expressions can be used in places where a value is required (such as in function arguments or return statements), while statements are used to structure your code and perform actions.

For instance, you cannot place a statement where Python expects an expression.

Example:

print(x = 10)

The above code results in an error because the assignment statement x = 10 has no resulting value, and the print() function expects an argument that is a value.

Parentheses in Expressions

When used within expressions, parentheses can group sub-expressions and control the order of operations.

Controlling Order of Operations

All operators in Python have an order of precedence, meaning that some operators are evaluated before others in an expression, just like how multiplication is performed before addition in mathematics. This order dictates the sequence in which operations are executed when an expression contains multiple different operators. But, placing a part of an expression in parentheses, causes it to be evaluated first.

When evaluating mathematical expressions, Python follows the standard order of operations in mathematics known as PEMDAS (Parentheses, Exponents, Multiplication and Division, and Addition and Subtraction).

Example:

result1 = 2 + 3 * 4
print(result1)

Output:

14

In the example above, multiplication has a higher precedence than addition, therefore 3 * 4 is calculated first, resulting in 12, and then 2 is added, giving a final result of 14.

However, if you want addition to be performed before multiplication, you can use parentheses.

Example:

result = (2 + 3) * 4
print(result)  # Output: 20

Output:

20

Now, the expression inside the parentheses 2 + 3 is calculated first, resulting in 5, and then this result is multiplied by 4, giving a final result of 20.

Operators other than mathematical also have a precedence.

Example:

logic1 = True and True or False and False
print(logic1)  # --> True

logic2 = True and (True or False) and False
print(logic2)  # --> False

Output:

True
False

The example above demonstrates that the logical and operator has a higher precedence than or, so the and operations are evaluated first. This results in True for the logic1 expression (lines 1-2). However, the parentheses in logic2 (line 4) cause the or operation to be evaluated first, resulting in an overall value of False (line 5).

Nested Parentheses

You can also nest parentheses to further control the order of operations in more complex expressions. Python evaluates the innermost parentheses first and then works its way outward.

Example:

result = (5 * (2 + 3)) - ((4 + 1) * 2)
print(result)

Output:

15

In example above, the expression 2 + 3 is calculated first inside the innermost parentheses, resulting in 5. This value is then multiplied by 5, resulting in 25. Also, the expression 4 + 1 inside the other set of parentheses is calculated to give 5, which is then multiplied by 2 to give 10. Finally, 25 is subtracted by 10, resulting in 15.

Lists, Tuples, and Dictionaries

Python provides several built-in data structures that let you organize and manage collections of related data. Among the most commonly used are lists, tuples, and dictionaries. Each of these data structures has unique characteristics and is suited to different types of tasks.

Lists

Lists are ordered, collections of items that are enclosed in square brackets [], and they can contain items of any data type. Lists are mutable, meaning that the items that the list contains can be switched after the list is created.

The items in a collection data structure, such as a list, are also known as ‘elements’.

Example:

fruits = ["apple", "banana", "cherry"]
print(fruits)

Output:

['apple', 'banana', 'cherry']

In the example above, fruits is a variable that’s assigned a list containing three string elements. Note that the output is not itself a list, but merely a printable string representation of if.

Accessing List Elements

You can access an individual element by an index number. The index number represents the specific ordered position of the element, where the first position is numbered 0, and the rest go up by one to the right. You can specify an index by placing its number in square brackets immediately to the right of the list.

Example:

fruits = ["apple", "banana", "cherry"]

first_fruit = fruits[0]
second_fruit = fruits[1]
third_fruit = fruits[2]

print(first_fruit)
print(second_fruit)
print(third_fruit)

Output:

apple
banana
cherry

In the example above, the first item, 'apple', is accessed using fruits[0] (line 3), the second item, 'banana', is accessed using fruits[1] (line 4), and the third, 'cherry', using fruits[2] (line 5). The three fruit items are then printed separately (lines 7-9).

Assigning List Elements

Since lists are mutable, you can switch which items they hold by indexing and assigning a new value.

Example:

fruits[1] = "blueberry"
print(fruits)

Output:

['apple', 'blueberry', 'cherry']

In the above example, the second item of the list is changed from 'banana' to 'blueberry' (line 1).

Tuples

Tuples are similar to lists in that they are ordered collections of elements. However, tuples are immutable, meaning that once a tuple is created, its elements cannot be switched – and consequently, element assignment in tuples is invalid. Tuples are defined by placing its elements inside parentheses ().

Example:

colors = ("red", "green", "blue")
print(colors)

Output:

('red', 'green', 'blue')

In the example above, colors is a tuple that contains three strings.

Accessing Tuple Elements

Just like with a list, you can access the elements of a tuple by their index.

Example:

colors = ("red", "green", "blue")
print(colors[1])

Output:

green

The example above demonstrates accessing the second element of the colors tuple.

Why Use Tuples?

The immutability of tuples enables faster execution performance and a guarantee that they won’t change.

Dictionaries

Dictionaries are unordered collections of key-value pairs. Each key in a dictionary must be unique, and keys are used to access the corresponding values. Dictionaries are defined by placing key-value pairs inside curly braces {}.

Example:

dog = {
    "name": "Snoopy",
    "age": 5,
    "breed": "Beagle"
}
print(dog)

Output:

{'name': 'Snoopy', 'age': 5, 'breed': 'Beagle'}

In this example, dog is a dictionary with three key-value pairs, where 'name', 'age', and 'breed' are keys, and 'Snoopy', 5, and 'Beagle' are their corresponding values. (Even though this example writes the dictionary on multiple lines, it’s also common to place all key-value pairs on the same line, if the dictionary is small.)

Accessing Dictionary Values

You can access the value associated with a specific key using the key itself.

Example:

print(dog["name"])
print(dog["age"])

Output:

Snoopy
5

In the example above, the value associated with the key 'name' is accessed, returning “Snoopy”, and the value associated with the key 'age' is accessed, returning 5.

Modifying Dictionaries

Dictionaries are mutable, so you can change their values, add new key-value pairs, or remove existing ones.

Example:

dog = {"name": "Snoopy", "age": 5, "breed": "Beagle"}

dog["age"] = 6  # Modify an existing value
dog["owner"] = "Charlie Brown"  # Add a new key-value pair
del dog["breed"]  # Remove a key-value pair
print(dog)

Output:

{'name': 'Snoopy', 'age': 6, 'owner': 'Charlie Brown'}

Flow Control

Flow control in a computer program allows you to manage the order in which your code is executed, how many times sections of your code are executed, or whether they are executed at all. By using flow control statements, you can create programs that make decisions, repeat actions, and react differently to various inputs or conditions. The two primary types of flow control structures in Python are conditional statements and looping statements.

Conditional Statements

Conditional statements allow your program to make decisions based on certain conditions. In Python, the if, elif, and else keywords are used to control the flow of your program based on whether a condition is true or false.

Example:

x = 10

if x > 5:
    print("x is greater than 5")
elif x == 5:
    print("x is equal to 5")
else:
    print("x is less than 5")

Output:

x is greater than 5

In the example above, the program checks whether x is greater than 5 (line 3). If the condition is true, the first block of code (line 4) is executed, printing “x is greater than 5.” If the condition were false, the program would check the next condition given in the elif (which stands for else-if) statement (line 5) and execute the corresponding code block (line 6), if that condition were true. If none of the conditions are met, the else block (line 8) would be executed.

Looping Statements

Looping statements allow your program to execute a block of code repeatedly, either a specific number of times or until a certain condition is met. Python provides two types of loops: for loops and while loops.

The for Loop

A for loop is used to iterate over a sequence of items (such as a list, tuple, or string) and execute a block of code for each item in the sequence.

Example:

fruits = ["apple", "banana", "cherry"]

for fruit in fruits:
    print(fruit)

Output:

apple
banana
cherry

In this example, the for loop (line 3) iterates over each item in the fruits list. The loop runs three times, once for each fruit, and prints the name of each.

The while Loop

A while loop continues to execute a block of code as long as a specified condition remains true.

Example:

count = 0

while count < 3:
    print(f"Count is {count}")
    count += 1

Output:

Count is 0
Count is 1
Count is 2

In this example, the while loop (line 3) runs as long as the value of count is less than 3. During each iteration, the current value of count is printed (line 4), and then count is incremented by 1 (line 5). The loop stops once count reaches 3.

Nested Loops

Nested loops are loops within loops, which let you handle more complex data structures or create intricate repetitive patterns. In Python, you can nest for loops and while loops inside each other.

Example:

To demonstrate nested loops, let’s use two for loops to print a 3×3 matrix.

rows = 3
cols = 3

for i in range(rows):
    for j in range(cols):
        print(f"({i}, {j})", end=" ")
    print()

Output:

(0, 0) (0, 1) (0, 2)
(1, 0) (1, 1) (1, 2)
(2, 0) (2, 1) (2, 2)

In the example above, the outer for loop (line 4) iterates over the rows of the matrix, while the inner for loop (line 5) iterates over the columns. The print() function inside the inner loop prints each element in the format (i, j), with end=" " preventing a new line after each element (line 6). The print() function outside the inner loop ensures that each row starts on a new line (line 7).

Multiple Levels of Indentation

When using nested loops, maintaining proper indentation is crucial. Each nested loop must be indented one level further than the loop containing it. In the example above, the code block of the outer for loop spans lines 7-5, and is indented one level. The code block of the inner for loop spans line 6 and is indented an additional level. This indentation visually represents the structure of the nested loops and ensures that the code executes in the intended manner. In Python, consistent indentation helps in organizing the code, as well as prevents syntax errors and logical mistakes.

Summary & Reference for Python Syntax Basics

Syntax refers to the set of rules that govern how code must be structured in Python. Correct syntax ensures code is readable and executable by the computer.


Keywords are reserved words in Python that have special meanings. They form the foundation of Python’s syntax and cannot be used for any other purpose. Examples of common keywords include def, return, if, elif, else, and, or, not, for, and while.


Variables store data in Python and are declared by assigning a value to them using =. Python infers the type of the variable based on the assigned value.

age = 25

Variables can be reassigned to new values, replacing the old ones.

counter = 10
counter = 20

Although Python does not require variables to be declared with a type, every variable does have a type that is automatically determined based on the value assigned to it. Common types include int, float, str, and bool.


The print() function is used to output data of various types to the console.

print("Hello, World!")

Functions are reusable blocks of code defined with the def keyword, followed by the function name, parentheses and a colon. The function’s code block starts below the colon and is indented.

def greet():
    print("Hello,")
    print("Welcome to Python!")

Functions can take parameters, which are values that customize its behavior, and return values.

def add(a, b):
    return a + b

Python uses indentation to indicate blocks of code, which are groups of statements intended to be executed together.

def foo():
    print("First line of code block")
    print("Last line of code block")

Python requires the number of spaces you use for indentation to be consistent within a block of code, and by convention, 4 spaces per indentation level is considered best practice.


Comments are text in your code ignored by Python, used for notes, explanations, or reminders. They can clarify code, document decisions, and aid debugging.


A single-line comment starts with a # symbol, and everything after it on the line is ignored by Python.

# This is a comment
name = "Alice"  # Another comment

Multi-line comments can be created using multiple single-line comments or with multi-line strings enclosed in triple quotes.

# This is a
# multi-line comment

"""
This is another way to write
a multi-line comment using 
an unassigned multi-line string.
"""

'''
Multi-line comment strings can also be
enclosed with three single quotation markes.
'''

""" The new line after and before the tripel quotes
is optional. """

Good commenting practices include being concise, avoiding obvious comments, keeping comments up-to-date, and explaining why the code exists rather than what it does.


Operators in Python are symbols that perform operations on variables and values, enabling calculations, comparisons, and logical operations.


Arithmetic operators perform basic math like addition (+), subtraction (-), multiplication (*), and division (/).

x = 10
y = 5

print(x + y)  # --> 15

Comparison operators compare two values and return a Boolean (True or False). They include equal to (==), not equal to (!=), greater than (>), less than (<), less than or equal to (<=), and greater than or equal to (>=).

x = 10
y = 5

print(x > y)  # --> True

Logical operators combine conditional statements. They include and, or, and not.

x = 10
y = 5

print(x > y and y > 0)  # --> True

Assignment operators assign values to variables. The basic assignment operator is =, while augmented operators such as +=, -=, *=, and /=, perform operations and assign the result to the variable.

x = 10
x += 5  # x --> 15

Operator overloading allows some operators to work differently based on the data type. For example, the + operator adds numbers, but concatenates strings.

greeting = "Hello"
phrase = greeting + " there!"  # --> "Hello there!"

Statements perform actions, while expressions return values. An expression can be as simple as a single value or a complex combination of variables, operators, and function calls.

# The right side of the follwoing assignment is an expression, while the whole line is a statement.
x = 10 + 5

In Python, expressions can appear within statements, but statements cannot be used where Python expects an expression.

# The following has an error because the print function expects an expression 
# that results in a printable value, but x = 10 is a statement that has no value.
print(x = 10)

Parentheses in Python are used to group sub-expressions and control the order of operations.


By default, Python follows PEMDAS (Parentheses, Exponents, Multiplication and Division, and Addition and Subtraction) for operator precedence. Parentheses can override the default precedence to ensure a particular order of evaluation.

result = 2 + 3 * 4  # --> 14
result = (2 + 3) * 4  # --> 20

All other operators, such as logical operators, also follow precedence rules. For logical operators, and has a higher precedence than or.

logic1 = True and True or False and False  # --> True
logic2 = True and (True or False) and False  # --> False

Nested parentheses are evaluated from the innermost to the outermost.

result = (5 * (2 + 3)) - ((4 + 1) * 2)  # --> 15

Python provides several built-in data structures that let you organize and manage collections of related data. Among the most commonly used are lists, tuples, and dictionaries.


Lists are ordered collections enclosed in square brackets [] and can contain items of any data type.

fruits = ["apple", "banana", "cherry"]

Lists are mutable, meaning that the items the list contains can be switched for different ones after the list is created.


You can access list elements by their index, starting at 0.

first_fruit = fruits[0]  # --> 'apple'
second_fruit = fruits[1]  # --> 'banana'

You can modify lists by reassigning values at specific indices.

fruits[1] = "blueberry"  # fruits --> ["apple", "blueberry", "cherry"]

Tuples are similar to lists but are immutable and enclosed in parentheses ().

colors = ("red", "green", "blue")

Access tuple elements by their index, just like lists.

print(colors[1])  # --> "green"

Dictionaries are unordered collections of key-value pairs enclosed in curly braces {}. Each key must be unique.

dog = {"name": "Snoopy", "age": 5, "breed": "Beagle"}

Access dictionary values using their keys.

print(dog["name"])  # --> "Snoopy"

Modify dictionaries by changing values, adding new key-value pairs, or removing existing ones.

dog["age"] = 6  # dog --> {'name': 'Snoopy', 'age': 6, 'breed': 'Beagle'}
dog["owner"] = "Charlie Brown"  # dog --> {'name': 'Snoopy', 'age': 6, 'breed': 'Beagle', 'owner': 'Charlie Brown'}
del dog["breed"]  # dog --> {'name': 'Snoopy', 'age': 6, 'owner': 'Charlie Brown'}

Flow control structures allow you to manage the execution order and repetition of code in a program.


Conditional statements in Python use the if, elif, and else keywords to make decisions based on whether conditions are true or false.

if x > 5:
    print("x is greater than 5")
elif x == 5:
    print("x is equal to 5")
else:
    print("x is less than 5")

Looping statements repeat a block of code, either for a specific number of times or until a condition is met. Python supports for and while loops.


A for loop iterates over a sequence, executing a block of code for each item.

for fruit in fruits:
    print(fruit)

A while loop continues to execute as long as a specified condition remains true.

while count < 3:
    print(f"Count is {count}")
    count += 1

Nested loops (either for or while loops) are loops within loops that allow you to handle more complex data structures or repetitive patterns.

for i in range(rows):
    for j in range(cols):
        print(f"({i}, {j})", end=" ")
    print()

Each nested loop must be indented one level further than the loop containing it.