Python Code Example Handbook – Sample Script Coding Tutorial for Beginners

Hi! Welcome. If you are learning Python, then this article is for you. You will find a thorough description of Python syntax and lots of code examples to guide you during your coding journey.
What we will cover:
- Variable Definitions in Python
- Hello, World! Program in Python
- Data Types and Built-in Data Structures in Python
- Python Operators
- Conditionals in Python
- For Loops in Python
- While Loops in Python
- Nested Loops in Python
- Functions in Python
- Recursion in Python
- Exception Handling in Python
- Object-Oriented Programming in Python
- How to Work with Files in Python
- Import Statements in Python
- List and Dictionary Comprehension in Python
- and more...
Are you ready? Let's begin! 🔅
💡Tip: throughout this article, I will use<>
to indicate that this part of the syntax will be replaced by the element described by the text. For example,<var>
means that this will be replaced by a variable when we write the code.
🔹 Variable Definitions in Python
The most basic building-block of any programming language is the concept of a variable, a name and place in memory that we reserve for a value.
In Python, we use this syntax to create a variable and assign a value to this variable:
<var_name> = <value>
For example:
age =56
name ="Nora"
color ="Blue"
grades = [67,100,87,56]
If the name of a variable has more than one word, then theStyle Guide for Python Code recommends separating words with an underscore "as necessary to improve readability."
For example:
my_list = [1,2,3,4,5]
💡Tip: The Style Guide for Python Code (PEP 8) has great suggestions that you should follow to write clean Python code.
Here's an interactive scrim to help you understand variable definitions in Python:
Note that this scrim and the others in this handbook were narrated by a member of the Scrimba team and have been added to illustrate some key Python concepts.
🔸 Hello, World! Program in Python
Before we start diving into the data types and data structures that you can use in Python, let's see how you can write your first Python program.
You just need to call theprint()
function and write"Hello, World!"
within parentheses:
print("Hello, World!")
You will see this message after running the program:
"Hello, World!"
💡Tip: Writing a"Hello, World!"
program is a tradition in the developer community. Most developers start learning how to code by writing this program.
Great. You just wrote your first Python program. Now let's start learning about the data types and built-in data structures that you can use in Python.
🔹 Data Types and Built-in Data Structures in Python
We have several basic data types and built-in data structures that we can work with in our programs. Each one has its own particular applications. Let's see them in detail.
Numeric Data Types in Python: Integers, Floats, and Complex
These are the numeric types that you can work with in Python:
Integers
Integers are numbers without decimals. You can check if a number is an integer with thetype()
function. If the output is<class 'int'>
, then the number is an integer.
For example:
>>>type(1)<class 'int'>>>>type(15)<class 'int'>>>>type(0)<class 'int'>>>>type(-46)<class 'int'>
Floats
Floats are numbers with decimals. You can detect them visually by locating the decimal point. If we calltype()
to check the data type of these values, we will see this as the output:
<class 'float'>
Here we have some examples:
>>>type(4.5)<class 'float'>>>>type(5.8)<class 'float'>>>>type(2342423424.3)<class 'float'>>>>type(4.0)<class 'float'>>>>type(0.0)<class 'float'>>>>type(-23.5)<class 'float'>
Complex
Complex numbers have a real part and an imaginary part denoted withj
. You can create complex numbers in Python withcomplex()
. The first argument will be the real part and the second argument will be the imaginary part.
These are some examples:
>>>complex(4,5)(4+5j)>>>complex(6,8)(6+8j)>>>complex(3.4,3.4)(3.4+3.4j)>>>complex(0,0)0j>>>complex(5)(5+0j)>>>complex(0,4)4j
Strings in Python
Strings incredibly helpful in Python. They contain a sequence of characters and they are usually used to represent text in the code.
For example:
"Hello, World!"
'Hello, World!'
We can use both single quotes''
or double quotes""
to define a string. They are both valid and equivalent, but you should choose one of them and use it consistently throughout the program.
💡 Tip: Yes! You used a string when you wrote the"Hello, World!"
program. Whenever you see a value surrounded by single or double quotes in Python, that is a string.
Strings can contain any character that we can type in our keyboard, including numbers, symbols, and other special characters.
For example:
"45678"
"my_email@email.com"
"#IlovePython"
💡 Tip: Spaces are also counted as characters in a string.
Quotes Within Strings
If we define a string with double quotes""
, then we can use single quotes within the string. For example:
"I'm 20 years old"
If we define a string with single quotes''
, then we can use double quotes within the string. For example:
'My favorite book is "Sense and Sensibility"'
String Indexing
We can use indices to access the characters of a string in our Python program. An index is an integer that represents a specific position in the string. They are associated to the character at that position.
This is a diagram of the string"Hello"
:
String: H e l l oIndex:01234
💡 Tip: Indices start from0
and they are incremented by1
for each character to the right.
For example:
>>>my_string ="Hello">>>my_string[0]'H'>>>my_string[1]'e'>>>my_string[2]'l'>>>my_string[3]'l'>>>my_string[4]'o'
We can also use negative indices to access these characters:
>>>my_string ="Hello">>>my_string[-1]'o'>>>my_string[-2]'l'>>>my_string[-3]'l'>>>my_string[-4]'e'>>>my_string[-5]'H'
💡 Tip: we commonly use-1
to access the last character of a string.
String Slicing
We may also need to get a slice of a string or a subset of its characters. We can do so with string slicing.
This is the general syntax:
<string_variable>[start:stop:step]
start
is the index of the first character that will be included in the slice. By default, it's0
.
stop
is the index of the last character in the slice (this character willnot be included). By default, it is the last character in the string (if we omit this value, the last character will also be included).step
is how much we are going to add to the current index to reach the next index.
We can specify two parameters to use the default value ofstep
, which is1
. This will include all the characters betweenstart
andstop
(not inclusive):
<string_variable>[start:stop]
For example:
>>>freecodecamp ="freeCodeCamp">>>freecodecamp[2:8]'eeCode'>>>freecodecamp[0:3]'fre'>>>freecodecamp[0:4]'free'>>>freecodecamp[4:7]'Cod'>>>freecodecamp[4:8]'Code'>>>freecodecamp[8:11]'Cam'>>>freecodecamp[8:12]'Camp'>>>freecodecamp[8:13]'Camp'
💡 Tip: Notice that if the value of a parameter goes beyond the valid range of indices, the slice will still be presented. This is how the creators of Python implemented this feature of string slicing.
If we customize thestep
, we will "jump" from one index to the next according to this value.
For example:
>>>freecodecamp ="freeCodeCamp">>>freecodecamp[0:9:2]'feCdC'>>>freecodecamp[2:10:3]'eoC'>>>freecodecamp[1:12:4]'roa'>>>freecodecamp[4:8:2]'Cd'>>>freecodecamp[3:9:2]'eoe'>>>freecodecamp[1:10:5]'rd'
We can also use anegative step to go from right to left:
>>>freecodecamp ="freeCodeCamp">>>freecodecamp[10:2:-1]'maCedoCe'>>>freecodecamp[11:4:-2]'paeo'>>>freecodecamp[5:2:-4]'o'
And we can omit a parameter to use its default value. We just have to include the corresponding colon (:
) if we omitstart
,stop
, or both:
>>>freecodecamp ="freeCodeCamp"# Default start and step>>>freecodecamp[:8]'freeCode'# Default end and step>>>freecodecamp[4:]'CodeCamp'# Default start>>>freecodecamp[:8:2]'feCd'# Default stop>>>freecodecamp[4::3]'Cem'# Default start and stop>>>freecodecamp[::-2]'paeoer'# Default start and stop>>>freecodecamp[::-1]'pmaCedoCeerf'
💡 Tip: The last example is one of the most common ways to reverse a string.
f-Strings
In Python 3.6 and more recent versions, we can use a type of string called f-string that helps us format our strings much more easily.
To define an f-string, we just add anf
before the single or double quotes. Then, within the string, we surround the variables or expressions with curly braces{}
. This replaces their value in the string when we run the program.
For example:
first_name ="Nora"favorite_language ="Python"print(f"Hi, I'm{first_name}. I'm learning{favorite_language}.")
The output is:
Hi, I'm Nora. I'm learning Python.
Here we have an example where we calculate the value of an expression and replace the result in the string:
value =5print(f"{value} multiplied by 2 is:{value *2}")
The values are replaced in the output:
5 multiplied by2is:10
We can also call methods within the curly braces and the value returned will be replaced in the string when we run the program:
freecodecamp ="FREECODECAMP"print(f"{freecodecamp.lower()}")
The output is:
freecodecamp
String Methods
Strings have methods, which represent common functionality that has been implemented by Python developers, so we can use it in our programs directly. They are very helpful to perform common operations.
This is the general syntax to call a string method:
<string_variable>.<method_name>(<arguments>)
For example:
>>>freecodecamp ="freeCodeCamp">>>freecodecamp.capitalize()'Freecodecamp'>>>freecodecamp.count("C")2>>>freecodecamp.find("e")2>>>freecodecamp.index("p")11>>>freecodecamp.isalnum()True>>>freecodecamp.isalpha()True>>>freecodecamp.isdecimal()False>>>freecodecamp.isdigit()False>>>freecodecamp.isidentifier()True>>>freecodecamp.islower()False>>>freecodecamp.isnumeric()False>>>freecodecamp.isprintable()True>>>freecodecamp.isspace()False>>>freecodecamp.istitle()False>>>freecodecamp.isupper()False>>>freecodecamp.lower()'freecodecamp'>>>freecodecamp.lstrip("f")'reeCodeCamp'>>>freecodecamp.rstrip("p")'freeCodeCam'>>>freecodecamp.replace("e","a")'fraaCodaCamp'>>>freecodecamp.split("C")['free','ode','amp']>>>freecodecamp.swapcase()'FREEcODEcAMP'>>>freecodecamp.title()'Freecodecamp'>>>freecodecamp.upper()'FREECODECAMP'
To learn more about Python methods, I would recommend readingthis article from the Python documentation.
💡Tip: All string methods return copies of the string. They do not modify the string because strings are immutable in Python.
Booleans in Python
Boolean values areTrue
andFalse
in Python. They must start with an uppercase letter to be recognized as a boolean value.
For example:
>>>type(True)<class 'bool'>>>>type(False)<class 'bool'>
If we write them in lowercase, we will get an error:
>>>type(true)Traceback (most recent call last): File"<pyshell#92>", line1,in <module> type(true)NameError: name'true'isnot defined>>>type(false)Traceback (most recent call last): File"<pyshell#93>", line1,in <module> type(false)NameError: name'false'isnot defined
Lists in Python
Now that we've covered the basic data types in Python, let's start covering the built-in data structures. First, we have lists.
To define a list, we use square brackets[]
with the elements separated by a comma.
💡 Tip: It's recommended to add a space after each comma to make the code more readable.
For example, here we have examples of lists:
[1,2,3,4,5]
["a","b","c","d"]
[3.4,2.4,2.6,3.5]
Lists can contain values of different data types, so this would be a valid list in Python:
[1,"Emily",3.4]
We can also assign a list to a variable:
my_list = [1,2,3,4,5]
letters = ["a","b","c","d"]
Nested Lists
Lists can contain values of any data type, even other lists. These inner lists are callednested lists.
[[1,2,3], [4,5,6]]
In this example,[1, 2, 3]
and[4, 5, 6]
are nested lists.
Here we have other valid examples:
[["a","b","c"], ["d","e","f"], ["g","h","i"]]
[1, [2,3,4], [5,6,7],3.4]
We can access the nested lists using their corresponding index:
>>>my_list = [[1,2,3], [4,5,6]]>>>my_list[0][1,2,3]>>>my_list[1][4,5,6]
Nested lists could be used to represent, for example, the structure of a simple 2D game board where each number could represent a different element or tile:
# Sample Board where:# 0 = Empty tile# 1 = Coin# 2 = Enemy# 3 = Goalboard = [[0,0,1], [0,2,0], [1,0,3]]
List Length
We can use thelen()
function to get the length of a list (the number of elements it contains).
For example:
>>>my_list = [1,2,3,4]>>>len(my_list)4
Update a Value in a List
We can update the value at a particular index with this syntax:
<list_variable>[<index>] = <value>
For example:
>>>letters = ["a","b","c","d"]>>>letters[0] ="z">>>letters['z','b','c','d']
Add a Value to a List
We can add a new value to the end of a list with the.append()
method.
For example:
>>>my_list = [1,2,3,4]>>>my_list.append(5)>>>my_list[1,2,3,4,5]
Remove a Value from a List
We can remove a value from a list with the.remove()
method.
For example:
>>>my_list = [1,2,3,4]>>>my_list.remove(3)>>>my_list[1,2,4]
💡Tip: This will only remove the first occurrence of the element. For example, if we try to remove the number 3 from a list that has two number 3s, the second number will not be removed:
>>>my_list = [1,2,3,3,4]>>>my_list.remove(3)>>>my_list[1,2,3,4]
List Indexing
We can index a list just like we index strings, with indices that start from0
:
>>>letters = ["a","b","c","d"]>>>letters[0]'a'>>>letters[1]'b'>>>letters[2]'c'>>>letters[3]'d'
List Slicing
We can also get a slice of a list using the same syntax that we used with strings and we can omit the parameters to use their default values. Now, instead of adding characters to the slice, we will be adding the elements of the list.
<list_variable>[start:stop:step]
For example:
>>>my_list = ["a","b","c","d","e","f","g","h","i"]>>>my_list[2:6:2]['c','e']>>>my_list[2:8]['c','d','e','f','g','h']>>>my_list[1:10]['b','c','d','e','f','g','h','i']>>>my_list[4:8:2]['e','g']>>>my_list[::-1]['i','h','g','f','e','d','c','b','a']>>>my_list[::-2]['i','g','e','c','a']>>>my_list[8:1:-1]['i','h','g','f','e','d','c']
List Methods
Python also has list methods already implemented to help us perform common list operations. Here are some examples of the most commonly used list methods:
>>>my_list = [1,2,3,3,4]>>>my_list.append(5)>>>my_list[1,2,3,3,4,5]>>>my_list.extend([6,7,8])>>>my_list[1,2,3,3,4,5,6,7,8]>>>my_list.insert(2,15)>>>my_list[1,2,15,3,3,4,5,6,7,8,2,2]>>>my_list.remove(2)>>>my_list[1,15,3,3,4,5,6,7,8,2,2]>>>my_list.pop()2>>>my_list.index(6)6>>>my_list.count(2)1>>>my_list.sort()>>>my_list[1,2,3,3,4,5,6,7,8,15]>>>my_list.reverse()>>>my_list[15,8,7,6,5,4,3,3,2,1]>>>my_list.clear()>>>my_list[]
To learn more about list methods, I would recommend readingthis article from the Python documentation.
Here's an interactive scrim to help you learn more about lists in Python:
Tuples in Python
To define a tuple in Python, we use parentheses()
and separate the elements with a comma. It is recommended to add a space after each comma to make the code more readable.
(1,2,3,4,5)
("a","b","c","d")
(3.4,2.4,2.6,3.5)
We can assign tuples to variables:
my_tuple = (1,2,3,4,5)
Tuple Indexing
We can access each element of a tuple with its corresponding index:
>>>my_tuple = (1,2,3,4)>>>my_tuple[0]1>>>my_tuple[1]2>>>my_tuple[2]3>>>my_tuple[3]4
We can also use negative indices:
>>>my_tuple = (1,2,3,4)>>>my_tuple[-1]4>>>my_tuple[-2]3>>>my_tuple[-3]2>>>my_tuple[-4]1
Tuple Length
To find the length of a tuple, we use thelen()
function, passing the tuple as argument:
>>>my_tuple = (1,2,3,4)>>>len(my_tuple)4
Nested Tuples
Tuples can contain values of any data type, even lists and other tuples. These inner tuples are callednested tuples.
([1,2,3], (4,5,6))
In this example, we have a nested tuple(4, 5, 6)
and a list. You can access these nested data structures with their corresponding index.
For example:
>>>my_tuple = ([1,2,3], (4,5,6))>>>my_tuple[0][1,2,3]>>>my_tuple[1](4,5,6)
Tuple Slicing
We can slice a tuple just like we sliced lists and strings. The same principle and rules apply.
This is the general syntax:
<tuple_variable>[start:stop:step]
For example:
>>>my_tuple = (4,5,6,7,8,9,10)>>>my_tuple[3:8](7,8,9,10)>>>my_tuple[2:9:2](6,8,10)>>>my_tuple[:8](4,5,6,7,8,9,10)>>>my_tuple[:6](4,5,6,7,8,9)>>>my_tuple[:4](4,5,6,7)>>>my_tuple[3:](7,8,9,10)>>>my_tuple[2:5:2](6,8)>>>my_tuple[::2](4,6,8,10)>>>my_tuple[::-1](10,9,8,7,6,5,4)>>>my_tuple[4:1:-1](8,7,6)
Tuple Methods
There are two built-in tuple methods in Python:
>>>my_tuple = (4,4,5,6,6,7,8,9,10)>>>my_tuple.count(6)2>>>my_tuple.index(7)5
💡Tip: tuples are immutable. They cannot be modified, so we can't add, update, or remove elements from the tuple. If we need to do so, then we need to create a new copy of the tuple.
Tuple Assignment
In Python, we have a really cool feature called Tuple Assignment. With this type of assignment, we can assign values to multiple variables on the same line.
The values are assigned to their corresponding variables in the order that they appear. For example, ina, b = 1, 2
the value1
is assigned to the variablea
and the value2
is assigned to the variableb
.
For example:
# Tuple Assignment>>>a, b =1,2>>>a1>>>b2
💡 Tip: Tuple assignment is commonly used to swap the values of two variables:
>>>a =1>>>b =2# Swap the values>>>a, b = b, a>>>a2>>>b1
Dictionaries in Python
Now let's start diving into dictionaries. This built-in data structure lets us create pairs of values where one value is associated with another one.
To define a dictionary in Python, we use curly brackets{}
with the key-value pairs separated by a comma.
The key is separated from the value with a colon:
, like this:
{"a":1,"b":2,"c";3}
You can assign the dictionary to a variable:
my_dict = {"a":1,"b":2,"c";3}
The keys of a dictionary must be of an immutable data type. For example, they can be strings, numbers, or tuples but not lists since lists are mutable.
- Strings:
{"City 1": 456, "City 2": 577, "City 3": 678}
- Numbers:
{1: "Move Left", 2: "Move Right", 3: "Move Up", 4: "Move Down"}
- Tuples:
{(0, 0): "Start", (2, 4): "Goal"}
The values of a dictionary can be of any data type, so we can assign strings, numbers, lists, tuple, sets, and even other dictionaries as the values. Here we have some examples:
{"product_id":4556,"ingredients": ["tomato","cheese","mushrooms"],"price":10.67}
{"product_id":4556,"ingredients": ("tomato","cheese","mushrooms"),"price":10.67}
{"id":567,"name":"Emily","grades": {"Mathematics":80,"Biology":74,"English":97}}
Dictionary Length
To get the number of key-value pairs, we use thelen()
function:
>>>my_dict = {"a":1,"b":2,"c":3,"d":4}>>>len(my_dict)4
Get a Value in a Dictionary
To get a value in a dictionary, we use its key with this syntax:
<variable_with_dictionary>[<key>]
This expression will be replaced by the value that corresponds to the key.
For example:
my_dict = {"a":1,"b":2,"c":3,"d":4}print(my_dict["a"])
The output is the value associated to"a"
:
1
Update a Value in a Dictionary
To update the value associated with an existing key, we use the same syntax but now we add an assignment operator and the value:
<variable_with_dictionary>[<key>] = <value>
For example:
>>> my_dict = {"a":1,"b":2,"c":3,"d":4}>>> my_dict["b"] =6
Now the dictionary is:
{'a':1,'b':6,'c':3,'d':4}
Add a Key-Value Pair to a Dictionary
The keys of a dictionary have to be unique. To add a new key-value pair we use the same syntax that we use to update a value, but now the key has to be new.
<variable_with_dictionary>[<new_key>] = <value>
For example:
>>>my_dict = {"a":1,"b":2,"c":3,"d":4}>>>my_dict["e"] =5
Now the dictionary has a new key-value pair:
{'a':1,'b':2,'c':3,'d':4,'e':5}
Delete a Key-Value Pair in a Dictionary
To delete a key-value pair, we use thedel
statement:
del <dictionary_variable>[<key>]
For example:
>>>my_dict = {"a":1,"b":2,"c":3,"d":4}>>>del my_dict["c"]
Now the dictionary is:
{'a':1,'b':2,'d':4}
Dictionary Methods
These are some examples of the most commonly used dictionary methods:
>>>my_dict = {"a":1,"b":2,"c":3,"d":4}>>>my_dict.get("c")3>>>my_dict.items()dict_items([('a',1), ('b',2), ('c',3), ('d',4)])>>>my_dict.keys()dict_keys(['a','b','c','d'])>>>my_dict.pop("d")4>>>my_dict.popitem()('c',3)>>>my_dict.setdefault("a",15)1>>>my_dict{'a':1,'b':2}>>>my_dict.setdefault("f",25)25>>>my_dict{'a':1,'b':2,'f':25}>>>my_dict.update({"c":3,"d":4,"e":5})>>>my_dict.values()dict_values([1,2,25,3,4,5])>>>my_dict.clear()>>>my_dict{}
To learn more about dictionary methods, I recommendreading this article from the documentation.
And here's an interactive scrim to help you learn more about data types in Python:
🔸 Python Operators
Great. Now you know the syntax of the basic data types and built-in data structures in Python, so let's start diving into operators in Python. They are essential to perform operations and to form expressions.
Arithmetic Operators in Python
These operators are:
Addition: +
>>>5 +611>>>0 +66>>>3.4 +5.79.1>>>"Hello" +", " +"World"'Hello, World'>>>True +False1
💡Tip: The last two examples are curious, right? This operator behaves differently based on the data type of the operands.
When they are strings, this operator concatenates the strings and when they are Boolean values, it performs a particular operation.
In Python,True
is equivalent to1
andFalse
is equivalent to0
. This is why the result is1 + 0 = 1
Subtraction: -
>>>5 -6-1>>>10 -37>>>5 -6-1>>>4.5 -5.6 -2.3-3.3999999999999995>>>4.5 -7-2.5>>>-7.8 -6.2-14.0
Multiplication: *
>>>5 *630>>>6 *742>>>10 *1001000>>>4 *00>>>3.4 *6.823.119999999999997>>>4 * (-6)-24>>>(-6) * (-8)48>>>"Hello" *4'HelloHelloHelloHello'>>>"Hello" *0''>>>"Hello" *-1''
💡 Tip: you can "multiply" a string by an integer to repeat the string a given number of times.
Exponentiation: **
>>>6 **81679616>>>5 **225>>>4 **01>>>16 ** (1/2)4.0>>>16 ** (0.5)4.0>>>125 ** (1/3)4.999999999999999>>>4.5 **2.331.7971929089206>>>3 ** (-1)0.3333333333333333
Division: /
>>>25 /55.0>>>3 /60.5>>>0 /50.0>>>2467 /46730.5279263856195163>>>1 /20.5>>>4.5 /3.51.2857142857142858>>>6 /70.8571428571428571>>>-3 /-40.75>>>3 /-4-0.75>>>-3 /4-0.75
💡Tip: this operator returns afloat
as the result, even if the decimal part is.0
If you try to divide by0
, you will get aZeroDivisionError
:
>>>5 /0Traceback (most recent call last): File"<pyshell#109>", line1,in <module>5 /0ZeroDivisionError: division by zero
Integer Division: //
This operator returns an integer if the operands are integers. If they are floats, the result will be a float with.0
as the decimal part because it truncates the decimal part.
>>>5 //60>>>8 //24>>>-4 //-50>>>-5 //8-1>>>0 //50>>>156773 //356440
Modulo: %
>>>1 %51>>>2 %52>>>3 %53>>>4 %54>>>5 %50>>>5 %85>>>3 %10>>>15 %30>>>17 %81>>>2568 %40>>>245 %155>>>0 %60>>>3.5 %2.41.1>>>6.7 %-7.8-1.0999999999999996>>>2.3 %7.52.3
Comparison Operators
These operators are:
- Greater than:
>
- Greater than or equal to:
>=
- Less than:
<
- Less than or equal to:
<=
- Equal to:
==
- Not Equal to:
!=
These comparison operators make expressions that evaluate to eitherTrue
orFalse
. Here we have are some examples:
>>>5 >6False>>>10 >8True>>>8 >8False>>>8 >=5True>>>8 >=8True>>>5 <6True>>>10 <8False>>>8 <8False>>>8 <=5False>>>8 <=8True>>>8 <=10True>>>56 ==56True>>>56 ==78False>>>34 !=59True>>>67 !=67False
We can also use them to compare strings based on their alphabetical order:
>>>"Hello" >"World"False>>>"Hello" >="World"False>>>"Hello" <"World"True>>>"Hello" <="World"True>>>"Hello" =="World"False>>>"Hello" !="World"True
We typically use them to compare the values of two or more variables:
>>>a =1>>>b =2>>>a < bTrue>>>a <= bTrue>>>a > bFalse>>>a >= bFalse>>>a == bFalse>>>a != bTrue
💡Tip: notice that the comparison operator is==
while the assignment operator is=
. Their effect is different.==
returnsTrue
orFalse
while=
assigns a value to a variable.
Comparison Operator Chaining
In Python, we can use something called "comparison operator chaining" in which we chain the comparison operators to make more than one comparison more concisely.
For example, this checks ifa
is less thanb
and ifb
is less thanc
:
a < b < c
Here we have some examples:
>>> a =1>>> b =2>>> c =3>>> a < b < cTrue>>> a > b > cFalse>>> a <= b <= cTrue>>> a >= b >= cFalse>>> a >= b > cFalse>>> a <= b < cTrue
Logical Operators
There are three logical operators in Python:and
,or
, andnot
. Each one of these operators has its own truth table and they are essential to work with conditionals.
Theand
operator:
>>>TrueandTrueTrue>>>TrueandFalseFalse>>>FalseandTrueFalse>>>FalseandFalseFalse
Theor
operator:
>>>TrueorTrueTrue>>>TrueorFalseTrue>>>FalseorTrueTrue>>>FalseorFalseFalse
Thenot
operator:
>>>notTrueFalse>>>notFalseTrue
These operator are used to form more complex expressions that combine different operators and variables.
For example:
>>>a =6>>>b =3>>>a <6or b >2True>>>a >=3and b >=1True>>>(a + b) ==9and b >1True>>>((a %3) <2)and ((a + b) ==3)False
Assignment Operators
Assignment operators are used to assign a value to a variable.
They are:=
,+=
,-=
,*=
,%=
,/=
,//=
,**=
- The
=
operator assigns the value to the variable. - The other operators perform an operation with the current value of the variable and the new value and assigns the result to the same variable.
For example:
>>>x =3>>>x3>>>x +=15>>>x18>>>x -=2>>>x16>>>x *=2>>>x32>>>x %=5>>>x2>>>x /=1>>>x2.0>>>x //=2>>>x1.0>>>x **=5>>>x1.0
💡Tips: these operators perform bitwise operations before assigning the result to the variable:&=
,|=
,^=
,>>=
,<<=
.
Membership Operators
You can check if an element is in a sequence or not with the operators:in
andnot in
. The result will be eitherTrue
orFalse
.
For example:
>>>5in [1,2,3,4,5]True>>>8in [1,2,3,4,5]False>>>5in (1,2,3,4,5)True>>>8in (1,2,3,4,5)False>>>"a"in {"a":1,"b":2}True>>>"c"in {"a":1,"b":2}False>>>"h"in"Hello"False>>>"H"in"Hello"True>>>5notin [1,2,3,4,5]False>>>8notin (1,2,3,4,5)True>>>"a"notin {"a":1,"b":2}False>>>"c"notin {"a":1,"b":2}True>>>"h"notin"Hello"True>>>"H"notin"Hello"False
We typically use them with variables that store sequences, like in this example:
>>>message ="Hello, World!">>>"e"in messageTrue
🔹 Conditionals in Python
Now let's see how we can write conditionals to make certain parts of our code run (or not) based on whether a condition isTrue
orFalse
.
if
statements in Python
This is the syntax of a basicif
statement:
if <condition>:<code>
If the condition isTrue
, the code will run. Else, if it'sFalse
, the code will not run.
💡 Tip: there is a colon (:
) at the end of the first line and the code is indented. This is essential in Python to make the code belong to the conditional.
Here we have some examples:
False Condition
x =5if x >9: print("Hello, World!")
The condition isx > 9
and the code isprint("Hello, World!")
.
In this case, the condition isFalse
, so there is no output.
True Condition
Here we have another example. Now the condition isTrue
:
color ="Blue"if color =="Blue": print("This is my favorite color")
The output is:
"This is my favorite color"
Code After the Conditional
Here we have an example with code that runs after the conditional has been completed. Notice that the last line is not indented, which means that it doesn't belong to the conditional.
x =5if x >9: print("Hello!")print("End")
In this example, the conditionx > 9
isFalse
, so the first print statement doesn't run but the last print statement runs because it is not part of the conditional, so the output is:
End
However, if the condition isTrue
, like in this example:
x =15if x >9: print("Hello!")print("End")
The output will be:
Hello!End
Examples of Conditionals
This is another example of a conditional:
favorite_season ="Summer"if favorite_season =="Summer": print("That is my favorite season too!")
In this case, the output will be:
Thatis my favorite season too!
But if we change the value offavorite_season
:
favorite_season ="Winter"if favorite_season =="Summer": print("That is my favorite season too!")
There will be no output because the condition will beFalse
.
if/else
statements in Python
We can add anelse
clause to the conditional if we need to specify what should happen when the condition isFalse
.
This is the general syntax:
if <condition>: <code>else: <code>
💡 Tip: notice that the two code blocks are indented (if
andelse
). This is essential for Python to be able to differentiate between the code that belongs to the main program and the code that belongs to the conditional.
Let's see an example with theelse
clause:
True Condition
x =15if x >9: print("Hello!")else: print("Bye!")print("End")
The output is:
Hello!End
When the condition of theif
clause isTrue
, this clause runs. Theelse
clause doesn't run.
False Condition
Now theelse
clause runs because the condition isFalse
.
x =5if x >9: print("Hello!")else: print("Bye!")print("End")
Now the output is:
Bye!End
if/elif/else
statements in Python
To customize our conditionals even further, we can add one or moreelif
clauses to check and handle multiple conditions. Only the code of the first condition that evaluates toTrue
will run.
💡 Tip:elif
has to be written afterif
and beforeelse
.
First Condition True
x =5if x <9: print("Hello!")elif x <15: print("It's great to see you")else: print("Bye!")print("End")
We have two conditionsx < 9
andx < 15
. Only the code block from the first condition that isTrue
from top to bottom will be executed.
In this case, the output is:
Hello!End
Because the first condition isTrue
:x < 9
.
Second Condition True
If the first condition isFalse
, then the second condition will be checked.
In this example, the first conditionx < 9
isFalse
but the second conditionx < 15
isTrue
, so the code that belongs to this clause will run.
x =13if x <9: print("Hello!")elif x <15: print("It's great to see you")else: print("Bye!")print("End")
The output is:
It's great to see youEnd
All Conditions are False
If all conditions allFalse
, then theelse
clause will run:
x =25if x <9: print("Hello!")elif x <15: print("It's great to see you")else: print("Bye!")print("End")
The output will be:
Bye!End
Multiple elif Clauses
We can add as manyelif
clauses as needed. This is an example of a conditional with twoelif
clauses:
if favorite_season =="Winter": print("That is my favorite season too")elif favorite_season =="Summer": print("Summer is amazing")elif favorite_season =="Spring": print("I love spring")else: print("Fall is my mom's favorite season")
Each condition will be checked and only the code block of the first condition that evaluates toTrue
will run. If none of them areTrue
, theelse
clause will run.
Here's an interactive scrim to help you learn more about conditionals in Python:
🔸 For Loops in Python
Now you know how to write conditionals in Python, so let's start diving into loops. For loops are amazing programming structures that you can use to repeat a code block a specific number of times.
This is the basic syntax to write a for loop in Python:
for <loop_variable>in <iterable>:<code>
The iterable can be a list, tuple, dictionary, string, the sequence returned by range, a file, or any other type of iterable in Python. We will start withrange()
.
Therange()
function in Python
This function returns a sequence of integers that we can use to determine how many iterations (repetitions) of the loop will be completed. The loop will complete one iteration per integer.
💡 Tip: Each integer is assigned to the loop variable one at a time per iteration.
This is the general syntax to write a for loop withrange()
:
for <loop_variable>in range(<start>, <stop>, <step>): <code>
As you can see, the range function has three parameters:
start
: where the sequence of integers will start. By default, it's0
.stop
: where the sequence of integers will stop (without including this value).step
: the value that will be added to each element to get the next element in the sequence. By default, it's1
.
You can pass 1, 2, or 3 arguments torange()
:
- With 1 argument, the value is assigned to the
stop
parameter and the default values for the other two parameters are used. - With 2 arguments, the values are assigned to the
start
andstop
parameters and the default value forstep
is used. - With 3 arguments, the values are assigned to the
start
,stop
, andstep
parameters (in order).
Here we have some examples withone parameter:
for iin range(5): print(i)
Output:
01234
💡Tip: the loop variable is updated automatically.
>>>for jin range(15): print(j *2)
Output:
0246810121416182022242628
In the example below, we repeat a string as many times as indicated by the value of the loop variable:
>>>for numin range(8): print("Hello" * num)
Output:
HelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHello
We can also use for loops with built-in data structures such as lists:
>>>my_list = ["a","b","c","d"]>>>for iin range(len(my_list)): print(my_list[i])
Output:
abcd
💡Tip: when you userange(len(<seq>))
, you get a sequence of numbers that goes from0
up tolen(<seq>)-1
. This represents the sequence of valid indices.
These are some examples withtwo parameters:
>>>for iin range(2,10): print(i)
Output:
23456789
Code:
>>>for jin range(2,5): print("Python" * j)
Output:
PythonPythonPythonPythonPythonPythonPythonPythonPython
Code:
>>>my_list = ["a","b","c","d"]>>>for iin range(2, len(my_list)): print(my_list[i])
Output:
cd
Code:
>>>my_list = ["a","b","c","d"]>>>for iin range(2, len(my_list)-1): my_list[i] *= i
Now the list is:['a', 'b', 'cc', 'd']
These are some examples withthree parameters:
>>>for iin range(3,16,2): print(i)
Output:
3579111315
Code:
>>>for jin range(10,5,-1): print(j)
Output:
109876
Code:
>>>my_list = ["a","b","c","d","e","f","g"]>>>for iin range(len(my_list)-1,2,-1): print(my_list[i])
Output:
gfed
How to Iterate over Iterables in Python
We can iterate directly over iterables such as lists, tuples, dictionaries, strings, and files using for loops. We will get each one of their elements one at a time per iteration. This is very helpful to work with them directly.
Let's see some examples:
Iterate Over a String
If we iterate over a string, its characters will be assigned to the loop variable one by one (including spaces and symbols).
>>>message ="Hello, World!">>>for charin message: print(char)Hello,World!
We can also iterate over modified copies of the string by calling a string method where we specify the iterable in the for loop. This will assign the copy of the string as the iterable that will be used for the iterations, like this:
>>>word ="Hello">>>for charin word.lower():# calling the string method print(char)hello
>>>word ="Hello">>>for charin word.upper():# calling the string method print(char)HELLO
Iterate Over Lists and Tuples
>>>my_list = [2,3,4,5]>>>for numin my_list: print(num)
The output is:
2345
Code:
>>>my_list = (2,3,4,5)>>>for numin my_list:if num %2 ==0: print("Even")else: print("Odd")
Output:
EvenOddEvenOdd
Iterate Over the Keys, Values, and Key-Value Pairs of Dictionaries
We can iterate over the keys, values, and key-value pairs of a dictionary by calling specific dictionary methods. Let's see how.
Toiterate over thekeys, we write:
for <var>in <dictionary_variable>: <code>
We just write the name of the variable that stores the dictionary as the iterable.
💡 Tip: you can also write<dictionary_variable>.keys()
but writing the name of the variable directly is more concise and it works exactly the same.
For example:
>>>my_dict = {"a":1,"b":2,"c":3}>>>for keyin my_dict: print(key)abc
💡 Tip: you can assign any valid name to the loop variable.
Toiterate over thevalues, we use:
for <var>in <dictionary_variable>.values(): <code>
For example:
>>>my_dict = {"a":1,"b":2,"c":3}>>>for valuein my_dict.values(): print(value)123
Toiterate over thekey-value pairs, we use:
for <key>, <value>in <dictionary_variable>.items(): <code>
💡Tip: we are defining two loop variables because we want to assign the key and the value to variables that we can use in the loop.
>>>my_dict = {"a":1,"b":2,"c":3}>>>for key, valuein my_dict.items(): print(key, value)a1b2c3
If we define only one loop variable, this variable will contain a tuple with the key-value pair:
>>>my_dict = {"a":1,"b":2,"c":3}>>>for pairin my_dict.items(): print(pair)('a',1)('b',2)('c',3)
Break and Continue in Python
Now you know how to iterate over sequences in Python. We also have loop control statements to customize what happens when the loop runs:break
andcontinue
.
The Break Statement
Thebreak
statement is used to stop the loop immediately.
When abreak
statement is found, the loop stops and the program returns to its normal execution beyond the loop.
In the example below, we stop the loop when an even element is found.
>>>my_list = [1,2,3,4,5]>>>for elemin my_list:if elem %2 ==0: print("Even:", elem) print("break")breakelse: print("Odd:", elem)Odd:1Even:2break
The Continue Statement
Thecontinue
statement is used to skip the rest of the current iteration.
When it is found during the execution of the loop, the current iteration stops and a new one begins with the updated value of the loop variable.
In the example below, we skip the current iteration if the element is even and we only print the value if the element is odd:
>>>my_list = [1,2,3,4,5]>>>for elemin my_list:if elem %2 ==0: print("continue")continue print("Odd:", elem)Odd:1continueOdd:3continueOdd:5
The zip() function in Python
zip()
is an amazing built-in function that we can use in Python to iterate over multiple sequences at once, getting their corresponding elements in each iteration.
We just need to pass the sequences as arguments to thezip()
function and use this result in the loop.
For example:
>>>my_list1 = [1,2,3,4]>>>my_list2 = [5,6,7,8]>>>for elem1, elem2in zip(my_list1, my_list2): print(elem1, elem2)15263748
The enumerate() Function in Python
You can also keep track of a counter while the loop runs with theenum()
function. It is commonly used to iterate over a sequence and get the corresponding index.
💡 Tip: By default, the counter starts at0
.
For example:
>>>my_list = [5,6,7,8]>>>for i, elemin enumerate(my_list): print(i, elem)05162738
>>>word ="Hello">>>for i, charin enumerate(word): print(i, char)0 H1 e2 l3 l4 o
If you start the counter from0
, you can use the index and the current value in the same iteration to modify the sequence:
>>>my_list = [5,6,7,8]>>>for index, numin enumerate(my_list): my_list[index] = num *3>>>my_list[15,18,21,24]
You can start the counter from a different number by passing a second argument toenumerate()
:
>>>word ="Hello">>>for i, charin enumerate(word,2): print(i, char)2 H3 e4 l5 l6 o
The else Clause
For loops also have anelse
clause. You can add this clause to the loop if you want to run a specific block of code when the loop completes all its iterations without finding thebreak
statement.
💡 Tip: ifbreak
is found, theelse
clause doesn't run and ifbreak
is not found, theelse
clause runs.
In the example below, we try to find an element greater than 6 in the list. That element is not found, sobreak
doesn't run and theelse
clause runs.
my_list = [1,2,3,4,5]for elemin my_list:if elem >6: print("Found")breakelse: print("Not Found")
The output is:
Not Found
However, if thebreak
statement runs, theelse
clause doesn't run. We can see this in the example below:
my_list = [1,2,3,4,5,8]# Now the list has the value 8for elemin my_list:if elem >6: print("Found")breakelse: print("Not Found")
The output is:
Found
🔹 While Loops in Python
While loops are similar to for loops in that they let us repeat a block of code. The difference is that while loops run while a condition isTrue
.
In a while loop, we define the condition, not the number of iterations. The loop stops when the condition isFalse
.
This is the general syntax of a while loop:
while <condition>: <code>
💡Tip: in while loops, you must update the variables that are part of the condition to make sure that the condition will eventually becomeFalse
.
For example:
>>>x =6>>>while x <15: print(x) x +=167891011121314
>>>x =4>>>while x >=0: print("Hello" * x) x -=1HelloHelloHelloHelloHelloHelloHelloHelloHelloHello
>>>num =5>>>while num >=1: print("*" * num) num -=2*********
Break and Continue
We can also usebreak
andcontinue
with while loops and they both work exactly the same:
break
stops the while loop immediately.continue
stops the current iteration and starts the next one.
For example:
>>>x =5>>>while x <15:if x %2 ==0: print("Even:", x)break print(x) x +=15Even:6
>>>x =5>>>while x <15:if x %2 ==0: x +=1continue print("Odd:", x) x +=1Odd:5Odd:7Odd:9Odd:11Odd:13
Theelse
Clause
We can also add anelse
clause to a while loop. Ifbreak
is found, theelse
clause doesn't run but if thebreak
statement is not found, theelse
clause runs.
In the example below, thebreak
statement is not found because none of the numbers are even before the condition becomesFalse
, so theelse
clause runs.
x =5while x <15:if x %2 ==0: print("Even number found")break print(x) x +=2else: print("All numbers were odd")
This is the output:
5791113All numbers were odd
But in this version of the example, thebreak
statement is found and theelse
clause doesn't run:
x =5while x <15:if x %2 ==0: print("Even number found")break print(x) x +=1 # Now we are incrementing the value by1else: print("All numbers were odd")
The output is:
5Even number found
Infinite While Loops
When we write and work with while loops, we can have something called an "infinite loop." If the condition is neverFalse
, the loop will never stop without external intervention.
This usually happens when the variables in the condition are not updated properly during the execution of the loop.
💡 Tip: you must make the necessary updates to these variables to make sure that the condition will eventually evaluate toFalse
.
For example:
>>>x =5>>>while x >2: print(x)555555555...# The output continues indefinitely
💡Tip: to stop this process, typeCTRL + C
. You should see aKeyboardInterrupt
message.
🔸 Nested Loops in Python
We can write for loops within for loops and while loops within while loops. These inner loops are called nested loops.
💡Tip: the inner loop runs for each iteration of the outer loop.
Nested For Loops in Python
>>>for iin range(3):for jin range(2): print(i, j)000110112021
If we add print statements, we can see what is happening behind the scenes:
>>>for iin range(3): print("===> Outer Loop") print(f"i ={i}")for jin range(2): print("Inner Loop") print(f"j ={j}")===> Outer Loopi =0Inner Loopj =0Inner Loopj =1===> Outer Loopi =1Inner Loopj =0Inner Loopj =1===> Outer Loopi =2Inner Loopj =0Inner Loopj =1
The inner loop completes two iterations per iteration of the outer loop. The loop variables are updated when a new iteration starts.
This is another example:
>>>num_rows =5>>>for iin range(5):for num_colsin range(num_rows-i): print("*", end="") print()***************
Nested While Loops in Python
Here we have an example of nested while loops. In this case, we have to update the variables that are part of each condition to guarantee that the loops will stop.
>>>i =5>>>while i >0: j =0while j <2: print(i, j) j +=1 i -=150514041303120211011
💡Tip: we can also have for loops within while loops and while loops within for loops.
🔹 Functions in Python
In Python, we can define functions to make our code reusable, more readable, and organized. This is the basic syntax of a Python function:
def <function_name>(<param1>, <param2>, ...): <code>
💡 Tip: a function can have zero, one, or multiple parameters.
Function with No Parameters in Python
A function with no parameters has an empty pair of parentheses after its name in the function definition. For example:
defprint_pattern(): size =4for iin range(size): print("*" * size)
This is the output when we call the function:
>>>print_pattern()****************
💡 Tip: You have to write an empty pair of parentheses after the name of the function to call it.
Function with One Parameter in Python
A function with one or more parameters has a list of parameters surrounded by parentheses after its name in the function definition:
defwelcome_student(name): print(f"Hi,{name}! Welcome to class.")
When we call the function, we just need to pass one value as argument and that value will be replaced where we use the parameter in the function definition:
>>>welcome_student("Nora")Hi, Nora! Welcome toclass.
Here we have another example – a function that prints a pattern made with asterisks. You have to specify how many rows you want to print:
defprint_pattern(num_rows):for iin range(num_rows):for num_colsin range(num_rows-i): print("*", end="") print()
You can see the different outputs for different values ofnum_rows
:
>>> print_pattern(3)******>>> print_pattern(5)***************>>> print_pattern(8)************************************
Functions with Two or More Parameters in Python
To define two or more parameters, we just separate them with a comma:
def print_sum(a, b): print(a + b)
Now when we call the function, we must pass two arguments:
>>>print_sum(4,5)9>>>print_sum(8,9)17>>>print_sum(0,0)0>>>print_sum(3,5)8
We can adapt the function that we just saw with one parameter to work with two parameters and print a pattern with a customized character:
defprint_pattern(num_rows, char):for iin range(num_rows):for num_colsin range(num_rows-i): print(char, end="") print()
You can see the output with the customized character is that we call the function passing the two arguments:
>>> print_pattern(5,"A")AAAAAAAAAAAAAAA>>> print_pattern(8,"%")%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%>>> print_pattern(10,"#")#######################################################
How to Return a Value in Python
Awesome. Now you know how to define a function, so let's see how you can work with return statements.
We will often need to return a value from a function. We can do this with thereturn
statement in Python. We just need to write this in the function definition:
return <value_to_return>
💡 Tip: the function stops immediately whenreturn
is found and the value is returned.
Here we have an example:
defget_rectangle_area(length, width):return length * width
Now we can call the function and assign the result to a variable because the result is returned by the function:
>>>area = get_rectangle_area(4,5)>>>area20
We can also usereturn
with a conditional to return a value based on whether a condition isTrue
orFalse
.
In this example, the function returns the first even element found in the sequence:
defget_first_even(seq):for elemin seq:if elem %2 ==0:return elemelse:returnNone
If we call the function, we can see the expected results:
>>>value1 = get_first_even([2,3,4,5])>>>value12
>>>value2 = get_first_even([3,5,7,9])>>>print(value2)None
💡Tip: if a function doesn't have areturn
statement or doesn't find one during its execution, it returnsNone
by default.
TheStyle Guide for Python Code recommends using return statements consistently. It mentions that we should:
Be consistent in return statements. Either all return statements in a function should return an expression, or none of them should. If any return statement returns an expression, any return statements where no value is returned should explicitly state this as return None, and an explicit return statement should be present at the end of the function (if reachable)
Default Arguments in Python
We can assign default arguments for the parameters of our function. To do this, we just need to write<parameter>=<value>
in the list of parameters.
💡 Tip: TheStyle Guide for Python Code mentions that we shouldn't "use spaces around the = sign when used to indicate a keyword argument."
In this example, we assign the default value 5 to the parameterb
. If we omit this value when we call the function, the default value will be used.
def print_product(a, b=5): print(a * b)
If we call the function without this argument, you can see the output:
>>>print_product(4)20
We confirm that the default argument 5 was used in the operation.
But we can also assign a custom value forb
by passing a second argument:
>>>print_product(3,4)12
💡Tip: parameters with default arguments have to be defined at the end of the list of parameters. Else, you will see this error:SyntaxError: non-default argument follows default argument
.
Here we have another example with the function that we wrote to print a pattern. We assign the default value"*"
to thechar
parameter.
def print_pattern(num_rows, char="*"):for iin range(num_rows):for num_colsin range(num_rows-i): print(char, end="") print()
Now we have the option to use the default value or customize it:
>>>print_pattern(5)***************>>>print_pattern(6,"&")&&&&&&&&&&&&&&&&&&&&&
Here's an interactive scrim to help you learn more about functions in Python:
🔸 Recursion in Python
A recursive function is a function that calls itself. These functions have a base case that stops the recursive process and a recursive case that continues the recursive process by making another recursive call.
Here we have some examples in Python:
deffactorial(n):if n ==0or n ==1:return1else:return n * factorial(n-1)
deffibonacci(n):if n ==0or n ==1:return nelse:return fibonacci(n-1) + fibonacci(n-2)
deffind_power(a, b):if b ==0:return1else:return a * find_power(a, b-1)
🔹 Exception Handling in Python
An error or unexpected event that that occurs while a program is running is called anexception. Thanks to the elements that we will see in just a moment, we can avoid terminating the program abruptly when this occurs.
Let's see the types of exceptions in Python and how we can handle them.
Common Exceptions in Python
This is a list of common exceptions in Python and why they occur:
- ZeroDivisionError: raised when the second argument of a division or modulo operation is zero.
>>>5 /0Traceback (most recent call last): File"<pyshell#0>", line1,in <module>5 /0ZeroDivisionError: division by zero>>>7 //0Traceback (most recent call last): File"<pyshell#1>", line1,in <module>7 //0ZeroDivisionError: integer divisionor modulo by zero>>>8 %0Traceback (most recent call last): File"<pyshell#2>", line1,in <module>8 %0ZeroDivisionError: integer divisionor modulo by zero
- IndexError: raised when we try to use an invalid index to access an element of a sequence.
>>>my_list = [3,4,5,6]>>>my_list[15]Traceback (most recent call last): File"<pyshell#4>", line1,in <module> my_list[15]IndexError: list index out of range
- KeyError: raised when we try to access a key-value pair that doesn't exist because the key is not in the dictionary.
>>>my_dict = {"a":1,"b":2,"c":3}>>>my_dict["d"]Traceback (most recent call last): File"<pyshell#6>", line1,in <module> my_dict["d"]KeyError:'d'
- NameError: raised when we use a variable that has not been defined previously.
>>>bTraceback (most recent call last): File"<pyshell#8>", line1,in <module> bNameError: name'b'isnot defined
- RecursionError: raised when the interpreter detects that the maximum recursion depth is exceeded. This usually occurs when the process never reaches the base case.
In the example below, we will get aRecursionError
. Thefactorial
function is implemented recursively but the argument passed to the recursive call isn
instead ofn-1
. Unless the value is already0
or1
, the base case will not be reached because the argument is not being decremented, so the process will continue and we will get this error.
>>>deffactorial(n):if n ==0or n ==1:return1else:return n * factorial(n)>>>factorial(5)Traceback (most recent call last): File"<pyshell#6>", line1,in <module> factorial(5) File"<pyshell#5>", line5,in factorialreturn n * factorial(n) File"<pyshell#5>", line5,in factorialreturn n * factorial(n) File"<pyshell#5>", line5,in factorialreturn n * factorial(n) [Previous line repeated1021 more times] File"<pyshell#5>", line2,in factorialif n ==0or n ==1:RecursionError: maximum recursion depth exceededin comparison
💡Tip: to learn more about these exceptions, I recommend readingthis article from the documentation.
try
/except
in Python
We can use try/except in Python to catch the exceptions when they occur and handle them appropriately. This way, the program can terminate appropriately or even recover from the exception.
This is the basic syntax:
try: <code_that_may_raise_an_exception>except: <code_to_handle_the_exception_if_it_occurs>
For example, if we take user input to access an element in a list, the input might not be a valid index, so an exception could be raised:
index = int(input("Enter the index: "))try: my_list = [1,2,3,4] print(my_list[index])except: print("Please enter a valid index.")
If we enter an invalid value like 15, the output will be:
Please enter a valid index.
Because theexcept
clause runs. However, if the value is valid, the code intry
will run as expected.
Here we have another example:
a = int(input("Enter a: "))b = int(input("Enter b: "))try: division = a / b print(division)except: print("Please enter valid values.")
The output is:
Enter a:5Enter b:0Please enter valid values.
How to Catch a Specific Type of Exception in Python
Instead of catching and handling all possible exceptions that could occur in thetry
clause, we could catch and handle a specific type of exception. We just need to specify the type of the exception after theexcept
keyword:
try: <code_that_may_raise_an_exception>except <exception_type>: <code_to_handle_an_exception_if_it_occurs>
For example:
index = int(input("Enter the index: "))try: my_list = [1,2,3,4] print(my_list[index])except IndexError:# specify the type print("Please enter a valid index.")
a = int(input("Enter a: "))b = int(input("Enter b: "))try: division = a / b print(division)except ZeroDivisionError:# specify the type print("Please enter valid values.")
How to Assign a Name to the Exception Object in Python
We can specify a name for the exception object by assigning it to a variable that we can use in theexcept
clause. This will let us access its description and attributes.
We only need to addas <name>
, like this:
try: <code_that_may_raise_an_exception>except <exception_type>as <name>: <code_to_handle_an_exception_if_it_occurs>
For example:
index = int(input("Enter the index: "))try: my_list = [1,2,3,4] print(my_list[index])except IndexErroras e: print("Exception raised:", e)
This is the output if we enter15
as the index:
Enter the index:15Exception raised: list index outof range
This is another example:
a = int(input("Enter a: "))b = int(input("Enter b: "))try: division = a / b print(division)except ZeroDivisionErroras err: print("Please enter valid values.", err)
This is the output if we enter the value0
forb
:
Please enter valid values. division by zero
try
/except
/else
in Python
We can add anelse
clause to this structure afterexcept
if we want to choose what happens when no exceptions occur during the execution of thetry
clause:
try: <code_that_may_raise_an_exception>except: <code_to_handle_an_exception_if_it_occurs>else: <code_that_only_runs_if_no_exception_in_try>
For example:
a = int(input("Enter a: "))b = int(input("Enter b: "))try: division = a / b print(division)except ZeroDivisionErroras err: print("Please enter valid values.", err)else: print("Both values were valid.")
If we enter the values5
and0
fora
andb
respectively, the output is:
Please enter valid values. division by zero
But if both values are valid, for example5
and4
fora
andb
respectively, theelse
clause runs aftertry
is completed and we see:
1.25Both values were valid.
try
/except
/else
/finally
in Python
We can also add afinally
clause if we need to run code that should always run, even if an exception is raised intry
.
For example:
a = int(input("Enter a: "))b = int(input("Enter b: "))try: division = a / b print(division)except ZeroDivisionErroras err: print("Please enter valid values.", err)else: print("Both values were valid.")finally: print("Finally!")
If both values are valid, the output is the result of the division and:
Both values were valid.Finally!
And if an exception is raised becauseb
is0
, we see:
Please enter valid values. division by zeroFinally!
Thefinally
clause always runs.
💡 Tip: this clause can be used, for example, to close files even if the code throws an exception.
🔸 Object-Oriented Programming in Python
In Object-Oriented Programming (OOP), we define classes that act as blueprints to create objects in Python with attributes and methods (functionality associated with the objects).
This is a general syntax to define a class:
class <ClassName>: <class_attribute_name>= <value> def __init__(self,<param1>, <param2>, ...): self.<attr1> = <param1> self.<attr2> = <param2> . . . # As many attributes as needed def <method_name>(self, <param1>, ...): <code> # As many methods as needed
💡 Tip:self
refers to an instance of the class (an object created with the class blueprint).
As you can see, a class can have many different elements so let's analyze them in detail:
Class Header
The first line of the class definition has theclass
keyword and the name of the class:
classDog:
classHouse:
classBall:
💡 Tip: If the class inherits attributes and methods from another class, we will see the name of the class within parentheses:
classPoodle(Dog):
classTruck(Vehicle):
classMom(FamilyMember):
In Python, we write class name in Upper Camel Case (also known as Pascal Case), in which each word starts with an uppercase letter. For example:FamilyMember
__init__
and instance attributes
We are going to use the class to create object in Python, just like we build real houses from blueprints.
The objects will have attributes that we define in the class. Usually, we initialize these attributes in__init__
. This is a method that runs when we create an instance of the class.
This is the general syntax:
def__init__(self, <parameter1>, <parameter2>, ...): self.<attribute1> = <parameter1># Instance attribute self.<attribute2> = <parameter2># Instance attribute . . .# As many instance attributes as needed
We specify as many parameters as needed to customize the values of the attributes of the object that will be created.
Here is an example of aDog
class with this method:
classDog:def__init__(self, name, age): self.name = name self.age = age
💡Tip: notice the double leading and trailing underscore in the name__init__
.
How to Create an Instance
To create an instance ofDog
, we need to specify the name and age of the dog instance to assign these values to the attributes:
my_dog = Dog("Nora",10)
Great. Now we have our instance ready to be used in the program.
Some classes will not require any arguments to create an instance. In that case, we just write empty parentheses. For example:
classCircle:def__init__(self):self.radius=1
To create an instance:
>>>my_circle = Circle()
💡Tip:self
is like a parameter that acts "behind the scenes", so even if you see it in the method definition, you shouldn't consider it when you pass the arguments.
Default Arguments
We can also assign default values for the attributes and give the option to the user if they would like to customize the value.
In this case, we would write<attribute>=<value>
in the list of parameters.
This is an example:
classCircle:def__init__(self,radius=1): self.radius = radius
Now we can create aCircle
instance with the default value for the radius by omitting the value or customize it by passing a value:
# Default value>>>my_circle1 = Circle()# Customized value>>>my_circle2 = Circle(5)
How to Get an Instance Attribute
To access an instance attribute, we use this syntax:
<object_variable>.<attribute>
For example:
# Class definition>>>classDog:def__init__(self, name, age): self.name = name self.age = age# Create instance>>>my_dog = Dog("Nora",10)# Get attributes>>>my_dog.name'Nora'>>>my_dog.age10
How to Update an Instance Attribute
To update an instance attribute, we use this syntax:
<object_variable>.<attribute> =<new_value>
For example:
>>>classDog:def__init__(self, name, age): self.name = name self.age = age>>>my_dog = Dog("Nora",10)>>>my_dog.name'Nora'# Update the attribute>>>my_dog.name ="Norita">>>my_dog.name'Norita'
How to Remove an Instance Attribute
To remove an instance attribute, we use this syntax:
del <object_variable>.<attribute>
For example:
>>>classDog:def__init__(self, name, age): self.name = name self.age = age>>>my_dog = Dog("Nora",10)>>>my_dog.name'Nora'# Delete this attribute>>>del my_dog.name>>>my_dog.nameTraceback (most recent call last): File"<pyshell#77>", line1,in <module> my_dog.nameAttributeError:'Dog' object has no attribute'name'
How to Delete an Instance
Similarly, we can delete an instance usingdel
:
>>>classDog:def__init__(self,name,age):self.name= name self.age = age>>> my_dog = Dog("Nora",10)>>> my_dog.name'Nora'# Delete the instance>>> del my_dog>>> my_dogTraceback (most recent call last): File"<pyshell#79>", line1,in <module> my_dogNameError: name'my_dog' is not defined
Public vs. Non-Public Attributes in Python
In Python, we don't have access modifiers to functionally restrict access to the instance attributes, so we rely on naming conventions to specify this.
For example, by adding a leading underscore, we can signal to other developers that an attribute is meant to be non-public.
For example:
classDog:def__init__(self, name, age): self.name = name# Public attribute self._age = age# Non-Public attribute
The Python documentation mentions:
Use one leading underscore only for non-public methods and instance variables.
Always decide whether a class's methods and instance variables (collectively: "attributes") should be public or non-public. If in doubt, choose non-public; it's easier to make it public later than to make a public attribute non-public.
Non-public attributes are those that are not intended to be used by third parties; you make no guarantees that non-public attributes won't change or even be removed. -source
However, as the documentation also mentions:
We don't use the term "private" here, since no attribute is really private in Python (without a generally unnecessary amount of work). -source
💡 Tip: technically, we can still access and modify the attribute if we add the leading underscore to its name, but we shouldn't.
Class Attributes in Python
Class attributes are shared by all instances of the class. They all have access to this attribute and they will also be affected by any changes made to these attributes.
classDog:# Class attributes kingdom ="Animalia" species ="Canis lupus"def__init__(self, name, age): self.name = name self.age = age
💡 Tip: usually, they are written before the__init__
method.
How to Get a Class Attribute
To get the value of a class attribute, we use this syntax:
<class_name>.<attribute>
For example:
>>>classDog:kingdom="Animalia" def __init__(self, name, age): self.name = name self.age = age>>> Dog.kingdom'Animalia'
💡 Tip: You can use this syntax within the class as well.
How to Update a Class Attribute
To update a class attribute, we use this syntax:
<class_name>.<attribute> =<value>
For example:
>>>classDog: kingdom ="Animalia"def__init__(self, name, age): self.name = name self.age = age>>>Dog.kingdom'Animalia'>>>Dog.kingdom ="New Kingdom">>>Dog.kingdom'New Kingdom'
How to Delete a Class Attribute
We usedel
to delete a class attribute. For example:
>>>classDog: kingdom ="Animalia"def__init__(self, name, age): self.name = name self.age = age>>>Dog.kingdom'Animalia'# Delete class attribute>>>del Dog.kingdom>>>Dog.kingdomTraceback (most recent call last): File"<pyshell#88>", line1,in <module> Dog.kingdomAttributeError: type object'Dog' has no attribute'kingdom'
How to Define Methods
Methods represent the functionality of the instances of the class.
💡 Tip: Instance methods can work with the attributes of the instance that is calling the method if we writeself.<attribute>
in the method definition.
This is the basic syntax of a method in a class. They are usually located below__init__
:
class <ClassName>:# Class attributes# __init__def <method_name>(self, <param1>, ...): <code>
They may have zero, one, or more parameters if needed (just like functions!) but instance methods must always haveself
as the first parameter.
For example, here is abark
method with no parameters (in addition toself
):
classDog:def__init__(self, name, age): self.name = name self.age = agedefbark(self): print(f"woof-woof. I'm{self.name}")
To call this method, we use this syntax:
<object_variable>.<method>(<arguments>)
For example:
# Create the instance>>>my_dog = Dog("Nora",10)# Call the method>>>my_dog.bark()woof-woof. I'm Nora
Here we have aPlayer
class with anincrement_speed
method with one parameter:
classPlayer:def__init__(self, name): self.name = name self.speed =50defincrement_speed(self, value): self.speed += value
To call the method:
# Create instance >>> my_player = Player("Nora")# Check initial speed to see the change>>> my_player.speed50# Increment the speed>>> my_player.increment_speed(5)# Confirm the change>>> my_player.speed55
💡Tip: to add more parameters, just separate them with a comma. It is recommended to add a space after the comma.
Properties, Getters and Setters in Python
Getters and setters are methods that we can define to get and set the value of an instance attribute, respectively. They work as intermediaries to "protect" the attributes from direct changes.
In Python, we typically use properties instead of getters and setters. Let's see how we can use them.
To define a property, we write a method with this syntax:
@propertydef <property_name>(self):return self.<attribute>
This method will act as a getter, so it will be called when we try to access the value of the attribute.
Now, we may also want to define a setter:
@<property_name>.setterdef <property_name>(self, <param>): self.<attribute> = <param>
And a deleter to delete the attribute:
@<property_name>.deleterdef <property_name>(self): del self.<attribute>
💡 Tip: you can write any code that you need in these methods to get, set, and delete an attribute. It is recommended to keep them as simple as possible.
This is an example:
classDog:def__init__(self, name): self._name = name @propertydefname(self):return self._name @name.setterdefname(self, new_name): self._name = new_name @name.deleterdefname(self):del self._name
If we add descriptive print statements, we can see that they are called when we perform their operation:
>>>classDog:def__init__(self, name): self._name = name @propertydefname(self): print("Calling getter")return self._name @name.setterdefname(self, new_name): print("Calling setter") self._name = new_name @name.deleterdefname(self): print("Calling deleter")del self._name>>>my_dog = Dog("Nora")>>>my_dog.nameCalling getter'Nora'>>>my_dog.name ="Norita"Calling setter>>>my_dog.nameCalling getter'Norita'>>>del my_dog.nameCalling deleter
🔹 How to Work with Files in Python
Working with files is very important to create powerful programs. Let's see how you can do this in Python.
How to Read Files in Python
In Python, it's recommended to use awith
statement to work with files because it opens them only while we need them and it closes them automatically when the process is completed.
To read a file, we use this syntax:
with open("<file_path>")as <file_var>: <code>
We can also specify that we want to open the file in read mode with an"r"
:
with open("<file_path>","r")as <file_var>: <code>
But this is already the default mode to open a file, so we can omit it like in the first example.
This is an example:
with open("famous_quotes.txt")as file:for linein file: print(line)
or...
with open("famous_quotes.txt","r")as file:for linein file: print(line)
💡 Tip: that's right! We can iterate over the lines of the file using a for loop. The file path can be relative to the Python script that we are running or it can be an absolute path.
How to Write to a File in Python
There are two ways to write to a file. You can either replace the entire content of the file before adding the new content, or append to the existing content.
with open("<file_path>","w")as <file_var>: <code>
To replace the content completely, we use the"w"
mode, so we pass this string as the second argument toopen()
. We call the.write()
method on the file object passing the content that we want to write as argument.
For example:
words = ["Amazing","Green","Python","Code"]with open("famous_quotes.txt","w")as file:for wordin words: file.write(word +"\n")
When you run the program, a new file will be created if it doesn't exist already in the path that we specified.
This will be the content of the file:
AmazingGreenPythonCode
How to Append to a File in Python
However, if you want to append the content, then you need to use the"a"
mode:
with open("<file_path>","a")as <file_var>:<code>
For example:
words = ["Amazing","Green","Python","Code"]with open("famous_quotes.txt","a")as file:for wordin words: file.write(word +"\n")
This small change will keep the existing content of the file and it will add the new content to the end.
If we run the program again, these strings will be added to the end of the file:
AmazingGreenPythonCodeAmazingGreenPythonCode
How to Delete a File in Python
To delete a file with our script, we can use theos
module. It is recommended to check with a conditional if the file exists before calling theremove()
function from this module:
import osif os.path.exists("<file_path>"): os.remove("<file_path>")else: <code>
For example:
import osif os.path.exists("famous_quotes.txt"): os.remove("famous_quotes.txt")else: print("This file doesn't exist")
You might have noticed the first line that saysimport os
. This is an import statement. Let's see why they are helpful and how you can work with them.
🔸 Import Statements in Python
Organizing your code into multiple files as your program grows in size and complexity is good practice. But we need to find a way to combine these files to make the program work correctly, and that is exactly what import statements do.
By writing an import statement, we can import a module (a file that contains Python definitions and statements) into another file.
These are various alternatives for import statements:
First Alternative:
import <module_name>
For example:
import math
💡Tip:math
is a built-in Python module.
If we use this import statement, we will need to add the name of the module before the name of the function or element that we are referring to in our code:
>>>import math>>>math.sqrt(25)5.0
We explicitly mention in our code the module that the element belongs to.
Second Alternative:
import <module>as <new_name>
For example:
import mathas m
In our code, we can use the new name that we assigned instead of the original name of the module:
>>>import mathas m>>>m.sqrt(25)5.0
Third Alternative:
from <module_name>import <element>
For example:
from mathimport sqrt
With this import statement, we can call the function directly without specifiying the name of the module:
>>>from mathimport sqrt>>> sqrt(25)5.0
Fourth Alternative:
from <module_name>import <element>as <new_name>
For example:
from mathimport sqrtas square_root
With this import statement, we can assign a new name to the element imported from the module:
>>>from mathimport sqrtas square_root>>>square_root(25)5.0
Fifth Alternative:
from <module_name>import *
This statement imports all the elements of the module and you can refer to them directly by their name without specifying the name of the module.
For example:
>>>from mathimport *>>>sqrt(25)5.0>>>factorial(5)120>>>floor(4.6)4>>>gcd(5,8)1
💡Tip: this type of import statement can make it more difficult for us to know which elements belong to which module, particularly when we are importing elements from multiple modules.
According to theStyle Guide for Python Code:
Wildcard imports (from import *) should be avoided, as they make it unclear which names are present in the namespace, confusing both readers and many automated tools.
🔹 List and Dictionary Comprehension in Python
A really nice feature of Python that you should know about is list and dictionary comprehension. This is just a way to create lists and dictionaries more compactly.
List Comprehension in Python
The syntax used to define list comprehensions usually follows one of these four patterns:
[<value_to_include> for <var> in <sequence>]
[<value_to_include> for <var1> in <sequence1> for <var2> in <sequence2>]
[<value_to_include> for <var> in <sequence> if <condition>]
[<value> for <var1> in <sequence1> for <var2> in <sequence2> if <condition>]
💡 Tip: you should only use them when they do not make your code more difficult to read and understand.
Here we have some examples:
>>>[ifor iin range(4,15)][4,5,6,7,8,9,10,11,12,13,14]>>>[chr(i)for iin range(67,80)]['C','D','E','F','G','H','I','J','K','L','M','N','O']>>>[i**3for iin range(2,5)][8,27,64]>>>[i + jfor iin range(5,8)for jin range(3,6)][8,9,10,9,10,11,10,11,12]>>>[kfor kin range(3,35)if k %2 ==0][4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34]>>>[i * jfor iin range(2,6)for jin range(3,7)if i % j ==0][9,16,25]
List Comprehensions vs. Generator Expressions in Python
List comprehensions are defined with square brackets[]
. This is different from generator expressions, which are defined with parentheses()
. They look similar but they are quite different. Let's see why.
- List comprehensions generate the entire sequence at once and store it in memory.
- Generator expressions yield the elements one at a time when they are requested.
We can check this with thesys
module. In the example below, you can see that their size in memory is very different:
>>>import sys>>> sys.getsizeof([ifor iin range(500)])2132>>> sys.getsizeof((ifor iin range(500)))56
We can use generator expressions to iterate in a for loop and get the elements one at a time. But if we need to store the elements in a list, then we should use list comprehension.
Dictionary Comprehension in Python
Now let's dive into dictionary comprehension. The basic syntax that we need to use to define a dictionary comprehension is:
{<key_value>: <value> for <var> in <sequence>}
{<key_value>: <value>for <var>in <sequence>if <condition>}
Here we have some examples of dictionary comprehension:
>>> {num: num**3for numin range(3,15)}{3:27,4:64,5:125,6:216,7:343,8:512,9:729,10:1000,11:1331,12:1728,13:2197,14:2744}>>> {x: x + yfor xin range(4,8)for yin range(3,7)}{4:10,5:11,6:12,7:13}
This is an example with a conditional where we take an existing dictionary and create a new dictionary with only the students who earned a passing grade greater than or equal to 60:
>>> grades = {"Nora":78,"Gino":100,"Talina":56,"Elizabeth":45,"Lulu":67}>>> approved_students = {student: gradefor (student, grade)in grades.items()if grade >=60}>>> approved_students{'Nora':78,'Gino':100,'Lulu':67}
I reallyhope you liked this article and found it helpful. Now you know how to write and work with the most important elements of Python.
⭐Subscribe to my YouTube channel and follow me onTwitter to find more coding tutorials and tips. Check out my online coursePython Exercises for Beginners: Solve 100+ Coding Challenges

I'm a software developer and technical writer. I love teaching and learning the intricacies of the amazing world of programming.
If you read this far, thank the author to show them you care.
Learn to code for free. freeCodeCamp's open source curriculum has helped more than 40,000 people get jobs as developers.Get started