This book is awesome!
2 Python Primer
In this chapter, we will give a quick introduction to Python. The goal is to focus only on the bare minimum of concepts that we need to know so that we can use them in generating our climate change visualizations and insights in the book.
We are by no means experts in Python even after writing this book. We are still learning! Our treatment is also incremental as we documented our learning on the way, including the mistakes that we made.
There are many excellent books on learning Python, and we refer the readers to those books for further exploration. All else fails, there is always Google!
One book that we learned from is Introducing Python.
Let us start with the most basic of statements, the print statement.
We will discuss more fancy ways of printing later in this primer.
In this case, text is the variable, and we are printing the value stored in the variable, which is “This book is awesome!”.
Now, what is a variable?
First, let us discuss literals and variables
2.1 Literals and Variables
We can specify data values in Python in two ways
- Literal
- Variable
A literal value in Python refers to a fixed value that is directly written in the code and does not change during program execution.
We can use directly in expressions or assign it to a variable.
An example of an integer literal is
An example of an string literal is
Literal values are used to represent constant values in the code and provide initial values for variables. They are directly interpreted by the Python interpreter and do not require any further computation or evaluation.
Variables are names for location in the computer memory that is used to store data. Variables are used to store and manipulate data during the execution of a program. We use variables a lot in the book and in programming in general. So let us dig in a bit more into the variables.
Variables can hold a value of any data type that we listed in the Table 2.1. We can assign a value to the variable using the assignment operator (=).
Using the literal values before, we can assign a integer variable a value
or
we can see what value the variable holds by printing it
This way of printing is always not clear. What if we were to print multiple values? We will see later how to use print statement better.
The idea is that we will use the variables and their values throughout the program. While a and b are valid variable names, they are not descriptive.
Will we remember what we are supposed to hold in a and b later? What if, by mistake, we assign a or b another value later in the program because we forgot that we have used them before?
Let us look at
- rules for naming variables
- some best practices for naming variables
We need to follow some rules for naming variables in Python 3.12:
- Variable names must start with a letter (a-z, A-Z) or an underscore (_).
- The rest of the variable name can contain letters, numbers, and underscores.
- Variable names are case-sensitive, meaning ‘myvariable’ and ‘Myvariable’ are different variables. This is a common mistake that we can make and wonder why our program is not running correctly!
- Variable names should not start with a number.
- Variable names can’t be one of the reserved keywords.
What are reserved keywords in Python? These keywords have special meanings in Python and cannot be used as variable names or identifiers.
We can find the reserved keywords with the following command:
Here is a list of the Python keywords. Enter any keyword to get more help.
False class from or
None continue global pass
True def if raise
and del import return
as elif in try
assert else is while
async except lambda with
await finally nonlocal yield
break for not
Some examples of valid variable names are:
- temperature
- Temperature
- num_counties
- total_sum
Some examples of invalid variable names are:
- 123abc (starts with a number)
- if (reserved keyword)
- my-variable (contains a hyphen)
As we mentioned before, not all valid variable names make good variable names.
For example, do we want to use?
- i (unless we use it as an index in a loop counter that we will discuss later)
- a_b_c
Let us look at some best practices for naming variables:
- Use descriptive and meaningful names that accurately represent the purpose or content of the variable.
- Follow the snake_case naming convention, which uses lowercase letters and underscores to separate words.
- Avoid using single-letter variable names, unless they are commonly used as loop counters (e.g., i, j, k).
- Use lowercase for variable names, except for constants which should be in uppercase.
- Be consistent with your naming conventions throughout your program.
- Use nouns or noun phrases for variable names, and avoid using verbs or verb phrases.
- Use singular nouns for variables that represent a single item, and plural nouns for variables that represent collections or lists.
- Avoid using abbreviations or acronyms unless they are widely known and understood. For example, TTPD may be known only to Swifties, but who isn’t? 😵💫
- Use meaningful prefixes or suffixes to indicate the type or purpose of the variable (e.g., str_name, num_count).
- Avoid using names that are too generic or ambiguous, as they can lead to confusion and bugs.
- Consider using self-explanatory names that make the code more readable and understandable.
- Document the purpose and usage of complex or non-obvious variables using inline comments.
Our code becomes clean and with meaningful and self-explanatory variable names.
Remember, you may have to go back to the code a few years later and try to figure out what you have written! We started the book a few years back while we started learning Python. Needless to say our choice of variables was not great. We had to go back and change some of the variable names and code during our review!
We will start with the basic data types in Python.
2.2 Data Types
We list below some of the basic data types in Python. Note that the list is not exhaustive. We are limiting to the basic data types that we need in later chapters in the book.
Data Type | Type | Example |
---|---|---|
Integer | int | 10, -10 |
Float | float | 98.6, -0.57 |
Boolean | bool | True, False |
String | str | “Hello”, “Climate Change” |
List | list | [1, 2, 3], [‘apple’, ‘banana’, ‘cherry’] |
Tuple | tuple | (1, 2, 3), (‘red’, ‘green’, ‘blue’) |
Dictionary | dict | {‘name’: ‘John’, ‘age’: 25} |
Let us go through the data types one by one with some more examples. But ultimately naming variables is a personal choice and there are a wide variety of preferences in naming variables.
Now that we know literal values and variables, let us go back to the data types and learn a bit more about them.
2.2.1 Numbers
Numbers in Python can be Integers, floating-point numbers or Boolean
Integer is a whole number without a decimal point.
or better still
or even better
What did this code do?
- In the first line, a variable named year is being assigned the integer value 2023.
- Formatted String (f-string) The second line uses an f-string to print a message that includes the value of the year variable. F-strings, introduced in Python 3.6, provide a way to embed expressions inside string literals, using curly braces {}. The f before the string indicates that it is a formatted string. Inside the curly braces, the variable year is evaluated, and its value is inserted into the string at that position.
We will see why this type of formatted printing may be useful later.
2.2.2 Integer Operations
We will go through in more detail the integer operations in Table 2.2 below
Operator | Description | Example |
---|---|---|
+ | Addition | 5 + 7 |
- | Subtraction | 5 - 7 |
* | Multiplication | 5 * 7 |
/ | Division | 5 / 7 |
// | Floor Division | 5 // 7 |
% | Modulo | 5 % 7 |
** | Exponentiation | a ** b |
Addition
We can add numbers or variables using \(+\) sign
Subtraction
We can calculate the difference using \(-\) sign
The difference between 5 and 4 is 1
Note we didn’t assign a and b new values. They use the previously assigned values that are in the memory.
But just in case, we close the notebook and run this part of the code, we will use the variable assignment in each code.
Multiplication
We can calculate the product of two numbers using \(*\) sign
The product of 5 and 3 is 15
Note that we assigned a new value to b. Now b is 3 and not 4. From now on, b holds 3 and doesn’t know that it has a previous value of 4. Another reason to be careful in naming the variables and assigning the values.
Division
We can divide two numbers using \(/\) sign
The result when 5 is divided by 3 is 1.6666666666666667
by the way, what happens when you divide by zero?
We get an error message!
ZeroDivisionError Traceback (most recent call last)
1 a = 5
2 b = 0
----> 3 quotient = a / b
4 print(f"The result when {a} is divided by {b} is {quotient}")
ZeroDivisionError: division by zero
Floor Division
When we divide an integer by another integer, we may end up with a float. In the previous example, when a=5 and b =3, we have a quotient of 1.6666666666666667. What if we only want the integer value of the ratio?
We can use \(//\) operation to get the integer value
a = 5
b = 3
floor_quotient = a // b
print(f"The integer value of the result when {a} is divided by {b} is {floor_quotient}")
The integer value of the result when 5 is divided by 3 is 1
Modulo
How about the remainder? We can use \(%\) operation
The remainder when 5 is divided by 3 is 2
Exponentiation
We want to raise one number to the power of another number, we can use \(**\) operation
2.2.3 Precedence of Operations
Our code may contain many operations. How would they be processed? The standard rules of precedence apply for operations in Python.
Here are the key rules, listed from highest to lowest precedence:
- Parentheses (): Operations inside parentheses are performed first.
- Exponentiation
- Unary Plus and Minus +x, -x: Unary operations are performed next.
- Multiplication *, Division /, Floor Division //, Modulus %: These operations are performed from left to right.
- Addition +, Subtraction -: These operations are performed from left to right.
Let us look at an example with all the operations.
result = 5 + 3 * 2 - 4 / 2 ** 2
# Step-by-step evaluation:
# 1. Exponentiation: 2 ** 2 = 4
# 2. Division: 4 / 4 = 1.0
# 3. Multiplication: 3 * 2 = 6
# 4. Addition and Subtraction: 5 + 6 - 1.0 = 10.0
print(result) # result is 10.0
10.0
or with variables
For example,
So far, we have mostly used integers. But not all numbers are integers or whole numbers.
2.2.4 Floating Numbers
A Float can be used for numbers with a decimal point.
We can do many of the same operations that we have done with integers on floating numbers
For example:
a = 5.2
b = 3.1
sum = a + b
difference = a- b
product = a * b
quotient = a / b
exponent = a ** b
floor_quotient = a // b
remainder = a % b
print(f"The sum of {a} and {b} is {sum}")
print(f"The difference of {a} and {b} is {difference}")
print(f"The product of {a} and {b} is {product}")
print(f"The result when {a} is divided by {b} is {quotient}")
print(f"The result of {a} to the power of {b} is {exponent}")
print(f"The remainder when {a} is divided by {b} is {remainder}")
print(f"The integer value of the result when {a} is divided by {b} is {floor_quotient}")
The sum of 5.2 and 3.1 is 8.3
The difference of 5.2 and 3.1 is 2.1
The product of 5.2 and 3.1 is 16.12
The result when 5.2 is divided by 3.1 is 1.6774193548387097
The result of 5.2 to the power of 3.1 is 165.80986483300362
The remainder when 5.2 is divided by 3.1 is 2.1
The integer value of the result when 5.2 is divided by 3.1 is 1.0
We have made extensive use of f-string here to print.
2.2.5 Booleans
Booleans can only take two values: True or False
Sometimes we may use integer value for a boolean.
It evaluates to True
It still evaluates to True
Remember any non-zero value, positive or negative evaluates, integer or floating evaluates to True
It evaluates to True
False has a value of zero.
It evaluates to False.
Similarly, we can do operations on Boolean noting that True is 1 and False is zero.
2.3 Strings
Strings are sequences of characters enclosed in quotes. They can be single, double, or triple quotes.
In Python, both single (’) and double (“) quotes can be used to define strings. The choice between them is largely a matter of personal preference or convenience, but there are some practical considerations:
When to Use Single Quotes (’):
Consistency: If your project or codebase predominantly uses single quotes, its a good practice to maintain consistency.
Embedding Double Quotes: When your string contains double quotes, using single quotes can avoid the need for escaping.
For example, the following two commands are the same
or
However, we need single quote when the string contains double quotes
This is a string with "double quotes" inside.
similarly, when the string contains single quotes, using double quotes can avoid the need for escaping by including double quotes
Triple Quotes (’’’ or “““):
Triple quotes are used for multi-line strings or docstrings.
multi_line_string = '''
This is a multiline string.
It can span multiple lines.
You can include line breaks and indentation.
'''
print(multi_line_string)
This is a multiline string.
It can span multiple lines.
You can include line breaks and indentation.
This is an example of docstring in Python.
"""
This is an example of a documentation comment.
It provides information about the purpose or behavior of the code.
You can use documentation comments to explain the code, provide usage examples, or describe any important details.
Remember to keep your documentation clear, concise, and up-to-date.
"""
Why are docstrings useful?
Improves Code Readability: Docstrings provide a clear explanation of what a function, class, or module does, making the code easier to understand for others (or yourself in the future).
Automatic Documentation Generation: Tools like Sphinx can automatically generate documentation from docstrings, making it easier to maintain and update documentation.
Interactive Help: In interactive environments like Jupyter Notebooks or Python’s interactive shell, you can use the help() function to access the docstring of a function, class, or module.
Standardized Documentation: Docstrings follow a standard format, which helps in maintaining consistency across the codebase.
IDE Support: Many Integrated Development Environments (IDEs) and code editors can display docstrings as tooltips, providing instant documentation while coding.
2.3.1 Some Operations on Strings -
Just as we have done some integer operations, we can do some operations on strings. These will be very useful in later chapters.
Concatenation
Concatenation on strings is in some ways, the same as addition on numbers.
We can add the three strings to form a longer string.
my_concat_string = my_string1 + my_string2 + my_string3
print(f"the concatenated string is {my_concat_string}")
the concatenated string is Climate ChangeisAlarming
While the concatenated string is correct, it would be better with space between my_string2 and my_string3.
We can instead use
my_concat_string = my_string1 + " " + my_string2 + " " + my_string3
print(f"the concatenated string is {my_concat_string}")
the concatenated string is Climate Change is Alarming
Length
We need to check the length of the strings many a time.
my_string1 = "Climate Change"
my_string2 = "is"
my_string3 = "Alarming"
my_concat_string = my_string1 + " " + my_string2 + " " + my_string3
len_my_string1 = len(my_string1)
len_my_string2 = len(my_string2)
len_my_string3 = len(my_string3)
len_concat_string = len(my_concat_string)
print(f"length of {my_string1} is {len_my_string1}")
print(f"length of {my_string2} is {len_my_string2}")
print(f"length of {my_string3} is {len_my_string3}")
print(f"length of {my_concat_string} is {len_concat_string}")
length of Climate Change is 14
length of is is 2
length of Alarming is 8
length of Climate Change is Alarming is 26
Note that the length of the concatenated string = 14 + 2 + 8 + 2 empty spaces that we added to make the string more readable. So, a total of 26.
2.3.2 Accessing Characters
Strings can be thought of just as a sequence of characters. That is, if we take,
my_string = "Climate Change"
print(f"The first letter of {my_string} is {my_string[0]}")
print(f"The second letter of {my_string} is {my_string[1]}")
print(f"The third letter of {my_string} is {my_string[2]}")
print(f"The fourth letter of {my_string} is {my_string[3]}")
print(f"The fifthletter of {my_string} is {my_string[4]}")
print(f"The sixth letter of {my_string} is {my_string[5]}")
print(f"The seventh letter of {my_string} is {my_string[6]}")
The first letter of Climate Change is C
The second letter of Climate Change is l
The third letter of Climate Change is i
The fourth letter of Climate Change is m
The fifthletter of Climate Change is a
The sixth letter of Climate Change is t
The seventh letter of Climate Change is e
Note that Index in Python always starts at zero. That is, in order to get the first character of “climate change”, we start using an index value of 0 and not 1.
We will see how we can write shorter code, using loops, instead of writing all the code above to get the sequential characters in the word “Climate Change”.
Strings are interesting! How do we get the last character of a string? Do we need to count all the characters in the string and then use it as an index?
There are a couple of ways of doing it based on the code that we have written so far.
my_string = "Climate Change"
len_my_string = len(my_string)
print(f"length of {my_string} is {len_my_string}")
print(f"The last letter of {my_string} is {my_string[len_my_string-1]}")
length of Climate Change is 14
The last letter of Climate Change is e
What did we do?
We first computed the length of the string 14. As we mentioned, in Python index starts at 0, so to get the last character, we need to use 13 as index.
Is there a easier way? Of course!
The last letter of Climate Change is e
We get the correct answer! That is, in Python, we can index with negative numbers to get characters from the end of the string.
2.3.3 Slicing
Many a time we need to get only parts of the string. How do we do it?
my_string = "Climate Change"
1my_substring = my_string[0:7]
2print(f"The substring of {my_string} from index 1 to 6 is {my_substring}")
3print(f"The substring of {my_string} from index 1 to 6 is {my_string[0:7]}")
- 1
- We can assign the substring to a new variable, in this case, my_substring. We have to use [0:7] as index in order to get the first 6 characters.
- 2
- We just printed the substring as we did before
- 3
- We can directly print part of the substring without creating a new variable.
The substring of Climate Change from index 1 to 6 is Climate
The substring of Climate Change from index 1 to 6 is Climate
2.3.4 Splitting
my_string = "Climate Change"
split_string = my_string.split(" ")
print(f"The split string of {my_string} is {split_string}")
The split string of Climate Change is ['Climate', 'Change']
What did the code do?
- We split the string based on the empty space ” ” using the split method of string.
- We printed the split string.
What if we want to do by some other character?
my_string = "Hello,World"
1split_string = my_string.split(",")
print(f"The split string is {split_string}")
- 1
- We used split method with “,” as the delimiter to split the string.
The split string is ['Hello', 'World']
How do we know all the methods associated with string?
['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isascii', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'removeprefix', 'removesuffix', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
>>> string = "Hello, World!" >>> methods = dir(string) >>> print(methods) ['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isascii', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
We are not going to go through all of these in detail. We will focus on those that we need in the later chapters in the book.
.join()
Of course, what is the opposite of .split(). It is .join().
.join(): Joins elements of an iterable(ex. list) into a single string
Changing Case
my_string = "Climate Change"
1my_string_upper = my_string.upper()
2my_string_lower = my_string.lower()
print(f"The upper case string is {my_string_upper}")
print(f"The lower case string is {my_string_lower}")
- 1
- Here we are invoking the upper method for the string to converr the string to upper case
- 2
- Here we are invoking the lower method for the string to convert the string to lower case
The upper case string is CLIMATE CHANGE
The lower case string is climate change
2.3.5 Manipulating Strings
Here are some methods that we can use to manipulate the strings.
Many a time, the data that we use from the internet may have whitespace either at the begining of the string, middle of the string or at the end of the string. Depending on our needs, we can remove the whitespace by using:
.strip. The .strip() method in Python is used to remove any leading and trailing whitespace characters from a string. This includes spaces, tabs, and newline characters. It can also be used to remove specific characters from the beginning and end of a string if specified.
# Original string with leading and trailing spaces
original_string = " Hello, World! "
# Using .strip() to remove the spaces
stripped_string = original_string.strip()
print(f"'{original_string}'") # Output: ' Hello, World! '
print(f"'{stripped_string}'") # Output: 'Hello, World!'
' Hello, World! '
'Hello, World!'
Comments Comments are extremely important in coding. They help you document and keep track of your code. We have used comments in the last two lines of code above.
To write comments in python you use the # symbol and anything after that is a comment
By default, .strip() removes all leading and trailing whitespace characters.
We can modify to remove custom characters to remove by passing them as an argument to .strip().
For example:
custom_string = "xxHello, World!xx"
stripped_custom = custom_string.strip('x')
print(f"'{stripped_custom}'") # Output: 'Hello, World!'
'Hello, World!'
Depending on our needs, we can use
- .lstrip(): Removes leading whitespace (or specified characters).
- .rstrip(): Removes trailing whitespace (or specified characters).
# Using .lstrip() and .rstrip()
original_string = " Hello, World! "
left_stripped = original_string.lstrip()
right_stripped = original_string.rstrip()
print(f"'{left_stripped}'") # Output: 'Hello, World! '
print(f"'{right_stripped}'") # Output: ' Hello, World!'
'Hello, World! '
' Hello, World!'
Let us look at some more of the string methods that would be useful.
.replace(old, new): replaces occurences of a substring with another substring
.str(): Use this when you want to convert a python object into a string
We will later see how we can use .astype(str) for a similar operation on a column in a DataFrame. But we are getting ahead!
To know what type the variable is you can use the type function:
isinstance(): The isinstance() function is used to check if an object is an instance or subclass of a specified class or a tuple of classes. It returns True if the object is an instance or subclass of the class (or any class in the tuple), and False otherwise.
.isdigit(): Checks if all characters in the string are digits
.isalpha(): Checks if all characters in the string are alphabetic
.isspace(): Checks if all characters in the string are whitespace
We are not going to make much use of tuple, lists and dictionaries in this book. But for the sake of completeness, here is some information on these:
2.3.6 Tuple
What is a Tuple?
- Is a immutable sequence of python objects
- Tuples are enclosed in () but can be created without them as well
- A tuple os created by comma-separated elements within ()
- Use the “tuple()” statement to convert other sequences like lists or strings into tuples
- The values in the tuple can be accessed with [] and the index number
- The index number starts at 0
- To concatenate tuples use the + symbol
- To multiply tuples with an integer use * symbol
- Tuples are important when you dont’t want the values to be changed
Example of creating a tuple:
Example of accessing elements in a tuple:
Example of concatenating tuples:
tuple1 = (1, 2, 3)
tuple2 = (4, 5, 6)
concatenated_tuple = tuple1 + tuple2
print(concatenated_tuple)
(1, 2, 3, 4, 5, 6)
Example of multiplying tuples:
Example of converting a list to a tuple:
2.3.7 Lists
- Lists are mutable
- Lists are defined by []
- The list function is used if you want to change an iterator or generator expression into a list
- To add values to the end of the list you use the append function
- If you want to insert a value at a specific location in the list you use insert(index number, value)
- The index starts at 0
- To remove a value use remove()
- To combine(concatenate) lists you use the + symbol
- To sort through the list use the sort() function
- To slice lists the format is start:stop; What is the starting point in the list that want to get and what is the end point in the the list that you want to get?
Creating a List:
Accessing Elements:
Modifying Elements:
Appending Elements:
Inserting Elements:
Removing Elements:
Concatenating Lists:
another_list = [7, 8, 9]
combined_list = my_list + another_list
print(combined_list) # Output: [1, 15, 3, 4, 5, 6, 7, 8, 9]
[1, 15, 3, 4, 5, 6, 7, 8, 9]
Sorting a List:
unsorted_list = [3, 1, 4, 1, 5, 9, 2]
unsorted_list.sort()
print(unsorted_list) # Output: [1, 1, 2, 3, 4, 5, 9]
[1, 1, 2, 3, 4, 5, 9]
Slicing a List:
Advanced Operations List Comprehensions:
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Filtering with List Comprehensions:
even_squares = [x**2 for x in range(10) if x % 2 == 0]
print(even_squares) # Output: [0, 4, 16, 36, 64]
[0, 4, 16, 36, 64]
Using map() and filter():
numbers = [1, 2, 3, 4, 5]
doubled = list(map(lambda x: x * 2, numbers))
print(doubled) # Output: [2, 4, 6, 8, 10]
even_numbers = list(filter(lambda x: x % 2 == 0, numbers))
print(even_numbers) # Output: [2, 4]
[2, 4, 6, 8, 10]
[2, 4]
This illustrates three useful features in python, map() and filter() in lists and lamda functions
Lets take a closer look.
Step 1: Define a List of Numbers
Here, we define a list named numbers containing the integers from 1 to 5.
Step 2: Double each number in the List
- map function: Applies a given function to all items in the input list.
- lambda x: x * 2: An anonymous function (lambda function) that takes an argument x and returns x multiplied by 2.
- list(map(…)): Converts the map object to a list.
Result: Each number in numbers is doubled, resulting in [2, 4, 6, 8, 10].
Step 3: Filter Even Numbers from the List
- filter function: Filters items out of the input list based on a given function.
- lambda x: x % 2 == 0: An anonymous function that returns True if x is even (i.e., divisible by 2 without a remainder).
- list(filter(…)): Converts the filter object to a list.
Result: Only the even numbers [2, 4] are retained from numbers.
In summary, some key features of lists are
- Mutable: Lists can be modified after creation.
- Ordered: Elements have a defined order and can be accessed by their index.
- Versatile: Lists can contain elements of different data types.
- Common Operations: Creating, accessing, modifying, appending, inserting, removing, concatenating, sorting, and slicing.
- Lists are a fundamental part of Python programming and are used extensively for various tasks, from simple data storage to complex data manipulation.
2.3.8 Dictionary
A dictionary is a built-in data structure in Python that holds a collection of key-value pairs. Keys and Values are Python objects. Each key is paried with a value, making it easy to retrieve, insert, update or delete values using keys.
Dictionaries are defined using curly braces {} and colons : to separate keys and values.
Let us create a dictionary.
{'name': 'Alice', 'age': 25, 'courses': ['Math', 'Science']}
Note that Keys always come first.
We can access elements in a dictionary by using their keys.
# Accessing elements using keys
print(student["name"]) # Output: Alice
print(student["age"]) # Output: 25
Alice
25
Insert or modify elements:
# Inserting a new key-value pair
student["grade"] = "A"
print(student)
# Modifying an existing key-value pair
student["age"] = 26
print(student)
{'name': 'Alice', 'age': 25, 'courses': ['Math', 'Science'], 'grade': 'A'}
{'name': 'Alice', 'age': 26, 'courses': ['Math', 'Science'], 'grade': 'A'}
Deleting Elements:
# Using del statement
del student["grade"]
print(student)
# Using pop() method
age = student.pop("age")
print(age)
print(student) #
{'name': 'Alice', 'age': 26, 'courses': ['Math', 'Science']}
26
{'name': 'Alice', 'courses': ['Math', 'Science']}
Merging Dictionaries:
# Merging dictionaries
student_info = {"name": "Bob", "age": 22}
student.update(student_info)
print(student)
{'name': 'Bob', 'courses': ['Math', 'Science'], 'age': 22}
Iterating over a Dictionary.
We can iterate over keys, values, or key-value pairs in a dictionary.
name Bob
courses ['Math', 'Science']
age 22
name Bob
courses ['Math', 'Science']
age 22
- The keys for dictionaries have to be immutable objects such as int, float, strings, or tuples
- To check if a object can be used as a key in the dictionary use the hash() function
Further Examples:
Counting Occurences of Each Character in a String
text = "hello world"
char_count = {}
for char in text:
if char in char_count:
char_count[char] += 1
else:
char_count[char] = 1
print(char_count)
{'h': 1, 'e': 1, 'l': 3, 'o': 2, ' ': 1, 'w': 1, 'r': 1, 'd': 1}
Using a Dictionary to store user Information:
2.4 Control Flow in Python
So far, we have seen basic data types and basic operations in Python.
But many a time, we need to perform an operation only if a condition is met.
2.4.1 If Statment
checks if a condition is true and if it is it executes the code in the lines that follow the if statment
Since this statment is true it is being executed
and if statement can be followed by one or multiple elif blocks which also check if that statement is true before moving on to a else block.
x = 4
if x<1:
print("X is less than 1")
elif x<2:
print("X is less than 2 ")
else:
print("X is greater than 2")
X is greater than 2
We could also use compound conditions such as and or or.
2.4.2 For Loops:
A for loop is used to iterate over a sequence (such as a list, tuple, string, or range) and execute a block of code for each element in the sequence. For loops are very versatile and they make our code much shorter. But they need to be used with caution!
- A for loop iterates over a sequence(lists, tuples, or strings)
- It executes a block of code for each element in the sequence
- It continues iterating until all the elements in the list, tuple, or string are done or until a condition is fulfilled
- The “break” statement exits out of the loop when a certain condition is met
- For loops can also have if , elif, and else statements.
Iterating over a list
Iterating over a String
Using range()
Many a time, we need to loop over values in a range
Note that the index starts at 0 and ends at 4.
We can also loop over an interval.
break Statement
The break statement is used to exit the loop prematurely when a certain condition is met.
Note that values 5 and above are not printed as the loop is exited when the value of num takes 5.
continue Statement The continue statement skips the current iteration and moves to the next iteration of the loop.
Notice that all values in the range except 2 are printed.
Nesting For loops
We can nest for loops by writing one inside another loop
i: 0, j: 0
i: 0, j: 1
i: 1, j: 0
i: 1, j: 1
i: 2, j: 0
i: 2, j: 1
While easy, we need to be careful in writing for loops, especially nested for loops. They can lead to a significant increase in the number of iterations. Performing many operations inside the loops can take more time.
2.4.3 While Loops:
- A while loop repeats a block of code while the condition being stated is true
- It continues iterating until the condition becomes false or until the loop is broken with the statement “break”
As an example,
We can use the break statement similar to the for loop.
We can also continue similar to for loop
We basically skip printing if count has a value of 3.
Infinite Loops: An infinite loop is a loop that continues to execute indefinitely because the terminating condition is never met. This can happen with both for and while loops, but it is more common with while loops due to their nature of relying on a condition to terminate.
We don’t ever want this!
2.4.3.1 Some Useful Built-In Functions
enumerate(): is a function that shows you the number of iterations in a loop. The enumerate() function is used to add a counter to an iterable and returns it as an enumerate object. This can be useful when you need both the index and the value of each item in a loop.
fruits = ["apple", "banana", "cherry"]
# Using enumerate to get both index and value
for index, fruit in enumerate(fruits):
print(f"Index: {index}, Fruit: {fruit}")
Index: 0, Fruit: apple
Index: 1, Fruit: banana
Index: 2, Fruit: cherry
sorted: sorts the list you pass
# Example list
numbers = [5, 2, 9, 1, 5, 6]
# Using sorted() to sort the list
sorted_numbers = sorted(numbers)
print("Original list:", numbers) # Output: [5, 2, 9, 1, 5, 6]
print("Sorted list:", sorted_numbers) # Output: [1, 2, 5, 5, 6, 9]
Original list: [5, 2, 9, 1, 5, 6]
Sorted list: [1, 2, 5, 5, 6, 9]
We can also do it in reverse order
# Example list
numbers = [5, 2, 9, 1, 5, 6]
# Using sorted() to sort the list in reverse order
sorted_numbers_desc = sorted(numbers, reverse=True)
print("Sorted list in descending order:", sorted_numbers_desc) # Output: [9, 6, 5, 5, 2, 1]
Sorted list in descending order: [9, 6, 5, 5, 2, 1]
- zip: add elements from multiple lists, tuples, or other seuences to form a list of tuples
2.4.4 User Defined Functions
We will make use of functions in later chapters.
- Functions help make code concise and reuseable
- Use functions to avoid repeating code and to organize your code
- Functions are defined using the ‘def’ followed by the function name and ()
- The ‘return’ statement is used to send the functions output back to the caller
- It ends the functions execution and returns the specified values
- Parameters: A variable that is in () that is information passed into the function
- Parameters: They act as placeholders for the values that will be passed to the function
- Arguments: Value that is sent to the function called. These values are assigned to the functions parameters
- Variables defined inside a function are only local to that function(local variables)
- Global Variables: Variables defined outside any function are global and can be accessed inside functions
How to Write Function(Step by Step): - Use “def” to define a function:
Function with Parameters:
Function Arguments and Return Values:
2.4.5 Formatted Printing
We have used f-strings earlier, but here is some more useful information on the f-string.
Formatted printing using f-strings in Python allows you to easily insert variables and expressions into strings. It provides a concise and readable way to format output.
To use f-strings, prefix the string with the letter ‘f’ or ‘F’. Inside the string, you can include expressions enclosed in curly braces {}. The expressions inside the curly braces will be evaluated and replaced with their values.
You can substitute variables directly into the string using f-strings. Place the variable name inside curly braces {} to include its value in the string.
Example:
My name is Sahasra and I am 17 years old.
We can also include expressions and operations inside the curly braces. The expressions will be evaluated and the result will be substituted into the string.
Example:
We can apply formatting options to the substituted values. These options include specifying the width, precision, alignment, and more.
The value of pi is approximately 3.142.
In the example above, :.3f specifies that the value of pi should be formatted as a floating-point number with 3 decimal places.
Formatted printing using f-strings is a powerful and convenient way to create formatted output in Python. It allows you to easily include variables, expressions, and apply formatting options within strings.