1.2. Fundamental Concepts and Operations in Python#

1.2.1. Order of Operations#

In Python, as in most programming languages, certain rules dictate the order in which operators are evaluated in an expression. These rules are known as the “order of operations” or “operator precedence.” Following the correct order of operations is crucial to getting the expected results from your expressions. The order of operations in Python is as follows, from highest to lowest precedence [Downey, 2015, Python Software Foundation, 2023]:

  1. Parentheses: Expressions enclosed in parentheses are evaluated foremost.

  2. Exponentiation (**): The exponentiation operator is evaluated subsequently.

  3. Multiplication (*), Division (/), Floor Division (//), and Modulus (%): These arithmetic operations are evaluated from left to right.

  4. Addition (+) and Subtraction (-): These arithmetic operations are also evaluated from left to right.

  5. Bitwise NOT (~): Pertains to binary values and is evaluated thereafter.

  6. Bitwise AND (&): Pertains to binary values and is evaluated subsequently.

  7. Bitwise OR (|): Pertains to binary values and is evaluated subsequently.

  8. Bitwise XOR (^): Pertains to binary values and is evaluated subsequently.

  9. Left Shift (<<) and Right Shift (>>): Apply to binary values and are evaluated subsequently.

  10. Comparison Operators: These include ==, !=, >, <, >=, and <=.

  11. Logical NOT (not): Used for negation and is evaluated subsequently.

  12. Logical AND (and): Evaluates the left operand first; if it is False, the right operand is not evaluated.

  13. Logical OR (or): Evaluates the left operand first; if it is True, the right operand is not evaluated.

  14. Assignment Operators: These encompass =, +=, -=, *=, /=, //=, %=.

Note

In Chapter 8, we’ll leverage bitwise operations for tasks related to Graphics and Image Processing.

result = 2 + (3 * 4)
print(result)
14

In this example, multiplication has higher precedence than addition, so the expression will be evaluated as follows:

result = 2 + (3 * 4)
result = 2 + 12
result = 14

To ensure that the addition is performed first, you can use parentheses:

result = (2 + 3) * 4

In this case, the addition is evaluated first:

result = 5 * 4
result = 20

Summary

A summary of the operator priority in Python, from highest to lowest precedence:

  1. Parentheses: ()

  2. Exponentiation: **

  3. Multiplication: *, Division: /, Floor Division: //, Modulus: %

  4. Addition: +, Subtraction: -

  5. Bitwise NOT: ~

  6. Bitwise AND: &

  7. Bitwise OR: |

  8. Bitwise XOR: ^

  9. Left Shift: <<, Right Shift: >>

  10. Comparison Operators: ==, !=, >, <, >=, <=

  11. Logical NOT: not

  12. Logical AND: and

  13. Logical OR: or

  14. Assignment Operators: =, +=, -=, *=, /=, //=, %=.

Keep in mind that the priority order determines how expressions are evaluated. Operators with higher precedence are evaluated first, and if multiple operators with the same precedence are present in the expression, they are evaluated from left to right. Parentheses can be used to override the default precedence and explicitly define the order of operations.

1.2.2. String operations#

String operations in Python allow us to manipulate and perform various actions on strings. Strings are sequences of characters, and Python provides a wide range of built-in functions and methods to work with them. Here are some common string operations in Python [Downey, 2015, Python Software Foundation, 2023]:

1.2.2.1. Concatenation#

String concatenation is the process of combining two or more strings to form a new string. In Python, you can use the + operator for concatenation.

Example:

first_name = "John"
last_name = "Doe"
full_name = first_name + " " + last_name
print(full_name)  # Output: "John Doe"
John Doe

1.2.2.2. String Length#

You can find the length of a string using the len() function.

Example:

text = "Hello, World!"
length = len(text)
print(length)
13
../_images/HelloWorld.png

Fig. 1.1 Visual representation of “Hello, World”.#

1.2.2.3. String Indexing and Slicing#

You can access individual characters in a string using indexing. Indexing starts from 0 for the first character and goes up to the length of the string minus one. Slicing allows you to extract substrings from a string based on start and end indices.

Example:

text = "Python"
print(text[0])
print(text[1:4])
P
yth
../_images/Python.png

Fig. 1.2 Visual representation of “Python”.#

1.2.3. Basic String Methods#

Python provides several built-in methods to manipulate strings, such as:

  • upper() and lower(): Convert the string to uppercase or lowercase, respectively.

  • strip(): Remove leading and trailing whitespaces from the string.

  • replace(): Replace occurrences of a substring with another substring.

  • split(): Split the string into a list of substrings based on a specified separator.

  • join(): Join a list of strings into a single string using a specified separator.

Example:

text = "    Hello, World!    "
print(text.strip())                # Output: "Hello, World!"
print(text.replace("World", "Python"))   # Output: "    Hello, Python!    "

sentence = "This is a sample sentence."
words = sentence.split(" ")        # Output: ['This', 'is', 'a', 'sample', 'sentence.']
new_sentence = "-".join(words)     # Output: "This-is-a-sample-sentence."
Hello, World!
    Hello, Python!    

1.2.3.1. String Formatting#

String formatting allows you to embed variables or expressions within a string. There are multiple ways to achieve string formatting in Python, including f-strings, str.format(), and % formatting.

Example:

name = "Alice"
age = 30
formatted_string = f"My name is {name} and I am {age} years old."
print(formatted_string)
# Output: "My name is Alice and I am 30 years old."
My name is Alice and I am 30 years old.

Note

Here are several typical string operations found in Python. Strings exhibit versatility and find extensive employment within Python programming to fulfill diverse tasks such as text processing, data manipulation, and conveying information to users. Our exploration of strings in Python will be more comprehensive in Chapter 3.

1.2.4. Comments#

Comments in Python are non-executable lines of text that provide information, explanations, or notes within the code. Comments are useful for making code more readable, documenting the code, and helping other developers understand the purpose and functionality of specific sections of code. Comments are ignored by the Python interpreter and do not affect the execution of the program [Downey, 2015, Python Software Foundation, 2023].

In Python, there are two ways to add comments:

1.2.4.1. Single-line comments#

Single-line comments start with the hash (#) symbol and extend to the end of the line. Anything written after the # symbol on the same line is considered a comment.

Example:

# This is a single-line comment
x = 10  # This is also a comment

1.2.4.2. Multi-line comments (Docstrings)#

Multi-line comments are typically used for more extensive documentation, especially for functions, classes, or modules. They are created using triple quotes (''' or """) at the beginning and end of the comment [Downey, 2015, Python Software Foundation, 2023].

Example:

'''
This is a multi-line comment.
It can span multiple lines
and is often used as a docstring for functions or classes.
'''
def my_function():
    """This is also a docstring comment for the function."""
    pass

Using comments wisely can improve code maintainability and facilitate collaboration among developers. They provide insights into the code’s intention and help in understanding complex logic or algorithms. However, it’s essential to use comments judiciously and avoid excessive or redundant commenting, as it can clutter the code unnecessarily.

1.2.5. Displaying Data: print and pprint in Python#

print and pprint are both functions in Python that are used for displaying data, but they have different purposes and behaviors [Python Software Foundation, 2023].

1.2.5.1. print#

The print function in Python is a built-in function that allows you to output text and values to the console or standard output. It’s commonly used for debugging, displaying information to users, or just for showing the value of variables during program execution. The print function takes one or more arguments, which can be strings, numbers, variables, or even expressions. It converts these arguments to strings and displays them in the console. Here’s a simple example:

name = "John"
age = 35
print("Hello, my name is", name, "and I am", age, "years old.")
Hello, my name is John and I am 35 years old.

In this example, the print function is used to display a message that includes the values of the name and age variables.

1.2.5.2. pprint#

The pprint (pretty-print) function is part of the pprint module in Python. It’s used to pretty-print complex data structures, such as dictionaries and lists, making them more readable when printed to the console. This is particularly useful when dealing with nested data structures, where the default print output can be difficult to interpret. The pprint function takes a single argument, usually a data structure, and formats it in a more human-friendly way. Here’s a basic example:

import pprint

data = {
    'name': 'John',
    'age': 25,
    'address': {
        'street': '123 Main St',
        'city': 'Anytown',
        'zip': '12345'
    }
}

# This is a dictionary, and we'll delve deeper into this topic in Chapter 3.

pprint.pprint(data)
{'address': {'city': 'Anytown', 'street': '123 Main St', 'zip': '12345'},
 'age': 25,
 'name': 'John'}

In this example, the pprint function is used to print the data dictionary, which contains nested dictionaries. The output will be formatted with proper indentation and line breaks, making it easier to understand the structure of the data.

1.2.6. Debugging#

Syntax Error, Runtime Error, and Semantic Error are the three main types of errors encountered in programming. Let’s define each of them:

1.2.6.1. Syntax Error#

A syntax error occurs when the code violates the rules of the programming language’s syntax. These errors are caught by the Python interpreter during the parsing phase before the program is executed. Syntax errors are typically caused by missing or misplaced characters, incorrect indentation, or improper use of keywords and symbols [Downey, 2015, Python Software Foundation, 2023].

Example of a syntax error:

# Missing a colon after the 'if' statement
if x > 5
    print("x is greater than 5")

Output:

File "<ipython-input-2-b98671540bfa>", line 2 if x > 5 ^ SyntaxError: expected ':'

1.2.7. Runtime Error#

A runtime error (also known as an exception or an error) occurs during the execution of the program when something unexpected happens. These errors are not caught during the parsing phase but arise during the program’s runtime. Runtime errors can be caused by various factors, such as division by zero, accessing an out-of-bounds index in a list, or calling a function that does not exist [Downey, 2015, Python Software Foundation, 2023].

Example of a runtime error:

x = 5
y = 0
result = x / y  # This will raise a ZeroDivisionError

Output:

---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
Cell In[20], line 3
      1 x = 5
      2 y = 0
----> 3 result = x / y

ZeroDivisionError: division by zero

1.2.7.1. Semantic Error#

A semantic error, also known as a logic error, occurs when the code is syntactically correct and runs without any errors, but it does not produce the expected or desired results due to incorrect logic or reasoning. These errors can be challenging to identify, as the program runs without any error messages. Semantic errors often lead to unexpected behavior or incorrect output [Downey, 2015, Python Software Foundation, 2023].

Example of a semantic error:

'''
The purpose of this function is to compute the average of a list of numbers
and present the result as an integer value.
'''
def calculate_average(numbers):
    total = 0
    for num in numbers:
        total = total + num
    average = total / len(numbers)
    return average

numbers_list = [5, 10, 15, 20]
result = calculate_average(numbers_list)
print(result)
# The above function will return 12.5, but it's not the correct average.
# The error is due to using 'total / len(numbers)' instead of 'total // len(numbers)'.
12.5

Summary

In summary,

  • Syntax errors are caught during the parsing phase before the program starts running.

  • Runtime errors occur during program execution when something unexpected happens, and they raise exceptions.

  • Semantic errors lead to incorrect behavior or output, but the code runs without any error messages. Identifying and fixing these errors is an essential part of the development process.