In the previous tutorial, I gave a brief introduction of what Python is about and how popular it’s getting in Data Science. If you’ve missed out on it, I strongly recommend you quickly go through it before this tutorial.
In today’s tutorial, we will learn about some fundamental concepts behind the Python programming language such as Python data types along with some examples. You will also learn about Loops with Python, Condition statements, Functions, Little notes (comments), Classes, and Error handling.
Introduction into Python
Assuming you’ve gone through the previous tutorial, you are now familiar with how Python is a Popular language for Data Science. Let’s start with a legendary welcome introduction into programming, which I’m sure everyone has written about before.
So open up a new file, name it python_tutorial.py, type in this code snippet and execute your code.
1 2 3 | print("Hello World") # ----- output ----- # Hello World |
If you are coming with experience from other programming languages like C, C++, Java, you would have noticed you will not have to write the main function or class before getting any output displayed.
Data Types in Python
When programming, the basic building blocks are it’s data types. These data types define the type of the variable, or what a value should contain. Since Python is a dynamically typed language, these data types tend to change based on its value. So the interpreter understands what data type to use during execution. Which, of course, doesn’t happen in other programming languages.
The Data types I have mentioned includes:
- Integers (int): Whole numbers like 10, 12, 50
- Float (float): Number with a decimal point: 5.5, 45.3, 75.5
- String (str): An ordered sequence of character: “Welcome”, “NeuraSpike”, “Python.”
- Lists (list): Ordered sequence of objects: [“David”, 13, “NeuraSpike”, 55.5]
- Dictionaries (dict): Unordered key and value pairs: {“Name” : “David”, “Company” : “NeuraSpike”}
- Tuples (tup): Ordered immutable sequence of objects: (“NeuraSpike”, 2020, “Python”, 185.5)
- Sets (set): Unordered collection of unique objects: {“NeuraSpike”, “Python”}
- Booleans (bool): Logical values either True or False
Variables in Python
If it’s your first time learning about programming, you might be wondering what variables are. What is the purpose of them? Why do we use them?
1 2 3 4 | brand = "NeuraSpike" print(brand) # ----- output ----- # NeuraSpike |
You could think of variables as a place you can store values. For example, the example shows how the blog name “NeuraSpike” is allocated to the variable name brand. When you print the variable brand, you will get the value assigned, “NeuraSpike.”
Some rules you should be aware of variable names are:
There are no spaces in variable names; we use “_” instead
1 2 3 4 5 6 7 8 9 10 11 | # Get an error brand name = "NeuraSpike" print(brand name) # ----- output ----- # SyntaxError: invalid syntax # Executes successfully brand_name = "NeuraSpike" print(brand_name) # ----- output ----- # NeuraSpike |
Variables names cannot start with numbers
1 2 3 4 | # Get an error 2020_brand_name = "NeuraSpike" # ----- output ----- # SyntaxError: invalid token |
Consist of names alpha-numeric characters (A-Z, a-z, 0-9) or underscore ( _ )
1 2 3 4 5 6 7 8 | author_name = "David Praise Chukwuma Kalu" print(author_name) BLOG_NAME = "NeuraSpike" print(BLOG_NAME) # ----- output ----- # David Praise Chukwuma Kalu # NeuraSpike |
Variable names are case sensitive. As an illustration: the variable brand is different from BRAND
1 2 3 4 5 6 7 8 | brand = "NeuraSpike version 1" print(brand) BRAND = "NeuraSpike version 2" print(BRAND) # ----- output ----- # NeuraSpike version 1 # NeuraSpike version 2 |
Strings in Python
Let’s say we are given a string, and our job is to convert the whole string assigned to a variable into uppercase or lowercase. How can we do that? With Python we can easily perform this operation in a single line of code:
1 2 3 4 5 6 7 8 9 10 11 12 | # convert brand name to lowercase brand_lowercase = "NeuraSpike" brand_lowercase = brand_lowercase.lower() print(brand_lowercase) # convert brand name to uppercase brand_uppercase = "NeuraSpike" brand_uppercase = brand_uppercase.upper() print(brand_uppercase) # ----- output ----- # neuraspike # NEURASPIKE |
Occasionally while working with either strings or other types of data structures like lists, tuples, array, dictionaries, etc. We might want to check the length and this can be done using the len() predefined function.
1 2 3 4 5 | # get the length of a given string brand = "NeuraSpike" print(len(brand)) # ----- output ----- # 10 |
A question for you is what if we want to grab the first letter in our variable name called brand? We can accomplish this using a process called indexing which we will explore more in-depth with a tutorial related to NumPy.
1 2 3 4 5 | # get first letter brand = "NeuraSpike" print(brand[0]) # ----- output ----- # N |
We can also get the last character in our string:
1 2 3 4 5 6 7 8 9 | # get last letter brand = "NeuraSpike" print(brand[-1]) # another way using len() print(brand[len(brand)-1]) # ----- output ----- # e # e |
To extract the section “eura” from the variable brand (“eura” also coincidentally carries the meaning justice in Greek):
1 2 3 4 | brand = "NeuraSpike" print(brand[1:5]) # ----- output ----- # eura |
Let’s say we want to join two different strings together or concatenate two strings. Python lets us perform this operation by using the add operator (+).
1 2 3 4 5 6 7 | # string concatenation brand = "NeuraSpike" message = " appreciates you in sharing this tutorial" text = brand + message print(text) # ----- output ----- # NeuraSpike appreciates you in sharing this tutorial |
Usually, you might have to break a large string into smaller chunks or strings based on a given separator at some point.
Note: this is the opposite of concatenation we have seen above, which adds two strings together.
1 2 3 4 5 6 | # dividing a string based on a given separator (" ") empty space brand = "Neura Spike" brand = brand.split(' ') print(brand) # ----- output ----- # ['Neura', 'Spike'] |
It’s vital to know how to check each variable name’s data type using the predefined function called type.
1 2 3 4 5 6 7 8 9 10 11 12 | brand = "NeuraSpike" print(type(brand)) current_year = 2020 print(type(current_year)) height = 190.5 print(type(height)) # ----- output ----- # <class 'str'> # <class 'int'> # <class 'float'> |
Once you execute the script, you will surely get different results.
List in Python
Now that we have seen how we can manipulate strings, let’s experiment on working with lists. It’s also similar to a data structure called arrays from other programming languages for example Java, in which we can store a bunch of things inside it like Strings and Integers.
1 2 3 4 5 6 7 | letter = "a" letter_b = "b" letter_c = "c" letters = ["a", "b", "c"] print(letters) # ----- output ----- # ['a', 'b', 'c'] |
Instead of creating multiple variables for different letters of the same type, we can rewrite the process by defining a list and put all these values inside one container of the same type.
1 2 3 | print(len(letters)) # ----- output ----- # 3 |
To get the list size, we can use the len() function, which returns the total number of items stored in our list.
Once you print out the list letters, you will get the output:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | # get the first element in a list print(letters[0]) # grab the last element in a list print(letters[len(letters)-1]) print(letters[-1]) # ----- output ----- # a # c # c # added letter 'd' and 'e' letters.append("d") letters.append("e") print(letters) # ----- output ----- # ['a', 'b', 'c', 'd', 'e'] |
Now, what if we want to add another value, letter “d” and “e” to the list without having the define another list with the same values [‘a’, ‘b’, ‘c’]. We can use the predefined function .append() to add values to our list.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | # delete letter 'e' letters.pop() # or letters.pop(-1) # can also be done like this # letters.remove('e') print(letters) # ----- output ----- # ['a', 'b', 'c', 'd'] # delete letter 'a' letters.pop(0) # specify the index # can also be done like this # letters.remove('a') print(letters) # <--['b', 'c', 'd'] # ----- output ----- # ['a', 'b', 'c', 'd'] # ['b', 'c', 'd'] |
Now we know how to add values. What if we want to delete certain elements within the list? Using the .pop() predefined function, we can easily remove certain values added to the list. For example using .pop() or .pop(-1) “last element” / .pop(0) “first element” function removes either the last or first element by specifying the index within the parenthesis.
Note: we can decide on any element we desire.
1 2 3 4 5 | numbers = [10, 5, 9, 4, 8, 3, 7, 2, 6, 1, 5] numbers.sort() print(numbers) # ------------- output ------------- # [1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10] |
We can also sort a list using the .sort() predefined method. Let’s create an unsorted list to see how it works.
1 2 3 4 | alpha_numeric = [10, 5, 'a', 'b'] alpha_numeric.sort() # ---------------------------- output ---------------------------- # TypeError: '<' not supported between instances of 'str' and 'int' |
It’s also important to know when using the .sort() predefined function; we cannot sort a list that contains both string (‘str’) and integers (‘int’). We will certainly get an error message (‘TypeError’) on the output console. We will see how we can resolve these error messages to avoid disrupting our program during execution time.
Dictionary in Python
Dictionaries in Python are an unordered data structure written with curly brackets and store key and value pairs.
Creating a dictionary of a person will look like this:
1 2 3 4 5 | person = { "name" : "David Praise", "title" : "Founder", "brand" : "NeuraSpike" } |
If we want to get a specific value, for example, the name, title, and brand, we can easily do it like this:
1 2 3 | print(person['name']) # <-- David Praise print(person['title']) # <-- Founder print(person['brand']) # <-- NeuraSpike |
In the example, the keys are the “name,” “title,” and “brand” we can access these values with the .keys() predefined function.
1 | print(person.keys()) # <-- dict_keys(['name', 'title', 'brand']) |
We can also extract all the values using the .values() predefined function.
1 2 3 | print(person.values()) # ------ output ------- # dict_values(['David Praise', 'Founder', 'NeuraSpike']) |
We can easily remove all items from the dictionary using the predefined clear() function.
1 2 | person.clear() print(person) # <-- {} |
Take away points from Python Dictionaries:
- The keys must be unique and cannot have duplicates.
1 2 3 4 5 6 7 8 9 | person = { "name" : "David Praise", "name" : "Sharry", "title" : "Founder", "brand" : "NeuraSpike" } print(person) # ------------- output ---------------- # {'brand': 'NeuraSpike', 'name': 'Sharry', 'title': 'Founder'} |
For example, having two keys with the same keys “name” assigned with “David Praise,” and another name is given a value “Sharry.” Once you print the output, it’s different.
Note: David Praise no longer exists in the person dictionary created. Suppose you are using an intelligent Integrated development environment like PyCharm. You will surely get a warning about having duplicate keys. Make sure you check out the PyCharm Community version developed by Intellij.
The values can be any data type mentioned above, such as Strings, Integers, Lists, and yes, even dictionaries.
Sets in Python
1 2 3 4 5 | number_list = [10, 30, 50, 10] print(number_list) # <-- [10, 30, 50, 10] number_set = {10, 30, 50, 10} print(number_set) # <-- {10, 50, 30} |
It’s important to know when working with sets, duplicates values are not allowed, and the elements order changes. Unlike lists, we could have a variety of values, and the order remains the same; however, using sets, that’s not possible.
1 2 3 4 5 | # intersection between two sets letter_a = {"A", "X", "Y"} letter_b = {"A", "B", "C"} union = letter_a | letter_b print(f"Union: {union}") # <-- Union: {'X', 'B', 'Y', 'A', 'C'} |
We could also take the union between two sets: all the elements in set a and all the elements in set b.
1 2 | intersection = letter_a & letter_b print(f"Intersection: {intersection}") # <-- Intersection: {'A'} |
We could also take the intersection, which is the elements the two sets have in common.
1 2 | different = letter_a - letter_b print(f"Difference: {different}") # <-- Difference: {'X', 'Y'} |
And the difference between two sets, written letter_a – letter_b, is the set of all elements in letter_a that are not elements of letter_b.
1 2 3 4 5 6 7 | # contains duplicate values numbers = [5, 10, 10, 2] print(numbers) # <-- [1, 2, 2, 3, 4, 5] # convert list into a set numbers = set(numbers) print(numbers) # <-- {1, 2, 3, 4, 5} |
We can also convert a list into a set if we are not interested in duplicate values.
If you’ve enjoyed the tutorial up until now, you should click on the “Click to Tweet Button” below to share on twitter. 😉
Check out a simple walkthrough with Python tutorial Share on XTuples in Python
Tuples are a collection of objects which are ordered and immutable. Unlike lists, you can’t change a value once it’s already defined.
1 2 3 4 | people = ("David", "Praise", "Kalu") print(people[0]) # <-- David print(people[1]) # <-- Praise print(people[2]) # <-- Kalu |
When working with lists, we can modify the values inside of it. However, when working with tuples, that’s not possible.
1 2 3 | people[0] = "Sharry" # ------ output ------- # TypeError: 'tuple' object does not support item assignment |
If and Else Statement
When you are making applications with any programming language, you will perform many decisions, and that’s when using condition statements comes into great use. These conditional statements I’ve mentioned allows us to execute a section of our code when a specific condition is satisfied.
It’s crucial to know these conditional statements are coupled with logical conditions from mathematics like:
- Greater than: a > b
- Greater than or equal to: a >= b
- Equals: a == b
- Not Equals: a != b
- Less than: a < b
- Less than or equal to: a <= b
Let’s write a piece of code using these logical conditions. Here we have the value 20 stored in a variable age, and we are checking if the age(20) is greater than the value 18.
It’s also vital to use indentation in Python to indicate a block of code to get your code compiled and executed successfully.
After the if statement, I used indentation then the print statement (“Legal to drive”) in the snippet. It belongs to the if statement if the age is greater than 18. Otherwise, the else statement if the age happens to be strictly less than 18.
1 2 3 4 5 6 7 | age = 20 if age >= 18: # is legal print("Legal to drive") else: # isn't legal print("Not yet legal to drive") # ----- output ----- # Legal to drive |
Another example could be to check if a number is positive, negative, or zero. Here we used the elif (read as “else if”) statement, which runs when the condition within the if statement doesn’t hold.
1 2 3 4 5 6 7 8 9 10 11 | number = 0 if number > 0: # number is positive print(f"{number} is positive") elif number == 0: # number is zero print(f"{number} is zero") else: # number is negative print(f"{number} is negative") # ----- output ----- # 0 is zero |
Another case could be having a nested if statement meaning another if statement clause within an existing if statement to check if a person is of legal age to drive when the number is positive.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | number = 2 age = 20 if number > 0: # number is positive print(f"{number} is positive") if age >= 18: # can drive print("Legal to drive") else: # can't drive print("Not legal to drive") elif number == 0: # number is zero print(f"{number} is zero") else: # number is negative print(f"{number} is negative") # ----- output ----- # 2 is positive # Legal to drive |
Another type of a conditional expression is called the Ternary Operator. This operator lets us test a condition in a single line of code, replacing a multiline if-else seen above to avoid having a compact code.
1 2 3 4 5 6 | age = 20 # check if a person is legal to drive or not output = "Legal to drive" if age >= 18 else "Not yet legal to drive" print(output) # ----- output ----- # Legal to drive |
Note: I only advise you to use this only if you have a simple one-liner. However, avoid having these types if the decision you have to make is complex, to make your code more readable.
For loops in Python
Using loops in Python allows us to iterate through tuples, lists, dictionaries, sets, or any data structure available. For more in-depth knowledge of data structures, be sure to visit this site.
1 2 3 | for number in range(0,10): print(number) # output <-- 0 1 2 3 4 5 6 7 8 9 |
Using the range() function, we can create a sequence of numbers, starting from 0 by default, and increments by 1(by default), and stopping before a specific number since we start counting from 0 by default, only if not specified differently.
1 2 3 4 | result = 0 for value in range(0,10): result = result + value print(f"Total sum: {result}") # <-- Total sum: 45 |
We can also sum all the numbers from 0 up until 9 using a for loop, instead of manually writing print(0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8+ 9).
1 2 3 4 5 6 7 8 | # print all even numbers (start, stop, step) for even_number in range(2, 10, 2): print(even_number) # ----- output ----- # 2 # 4 # 6 # 8 |
Using the for loop, we can start from 2 instead of 0 by default, incrementing by 2 and stop before 10.
1 2 3 4 | number_list = [] for value in range(0, 10): number_list.append(value) print(number_list) # <-- [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] |
Using a for loop, we can also decide to populate an empty list, with values from 0 up until 9.
1 2 | number_list = [ value for value in range(0, 10)] print(number_list) # <-- [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] |
In the above example, we have used over 4 lines of code to populate an empty list. However, we can do this in 2 lines by writing a for loop within an existing list. Then once executed, the values are being populated right inside of the empty list created.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | person = { "name" : "David Praise", "title" : "Founder", "brand" : "NeuraSpike" } for key, value in person.items(): print(f"Key:{key} Value:{value}") # ----- output ----- # Key:name Value:David Praise # Key:title Value:Founder # Key:brand Value:NeuraSpike print(person.items()) # <-- dict_items([('name', 'David Praise'), # ('title', 'Founder'), ('brand', 'NeuraSpike')]) |
From the previous example mentioned above, we can also iterate through a dictionary using a for loop. It’s important to know we specify a key and value index after calling the person.items() predefined function, which returns an array of key and value pairs. You may even print out person.item() on your console to see the result.
While Loops in Python
The while loop is another primitive loop command apart from the for loop. However, it works a bit differently. With this loop, we can execute a set of statements as long as a specific condition is true.
1 2 3 4 5 6 | number = 0 while number <= 5: # is condition satisfied print(f"{number}") # ----- output ----- # prints out 0 infinitely |
If we decided to run the statement, this is known as an infinite statement. Meaning it has no stopping condition because the condition statement is always true (number is always less than 5).
1 2 3 4 5 6 7 8 9 10 11 12 | number = 0 while number <= 5: # is condition satisfied print(f"{number}") number = number + 1 # increment the value # ----- output ------- # 0 # 1 # 2 # 3 # 4 # 5 |
On the other hand, if we decided to increment the value number by one after each iteration, once the condition is not satisfied (number 6 is less than 5), this is False. Right there is our stopping condition.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | number = 0 while number <= 5: # is condition satisfied print(f"{number}") number = number + 1 # increment the value else: print("Finished the while loop") # ----- output ------- # 0 # 1 # 2 # 3 # 4 # 5 # Finished the while loop |
We can also decide to add the else statement right after the while loop, and once the while statement isn’t true, the else statement is then executed.
Break and Continue in Python
You will undoubtedly use two keywords: the break and continue statement when working with both the while and for loops. Let’s see an example of working with the break keyword.
1 2 3 4 5 6 7 8 9 10 11 | number = 0 while number <= 5: # is condition satisfied if number == 3: break print(f"{number}") number = number + 1 # increment the value # ----- output ------- # 0 # 1 # 2 |
As the value stored in the number variable increases by 1 after each iteration, once the value equals 3, the break statement terminates the loop.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | number = 0 while number <= 5: # is condition satisfied number = number + 1 # increment the value if number == 3: continue print(f"{number}") # ----- output ------- # 0 # 1 # 2 # 4 # 5 # 6 |
Using the continue statement, once the number equals 3 the print statement and any other instructions below are ignored. Also, looking at the output, you will notice the number 3 isn’t printed out.
Functions in Python
One great benefit of writing functions within your code is avoiding to duplicate code. This reduces a complicated program into smaller and more manageable chunks, which reduces our program’s overall complexity.
1 2 3 4 5 6 7 | def add(number_1, number_2): # returns the sum of two numbers return number_1 + number_2 num_1 = 2 num_2 = 2 output = add(num_1, num_2) # called the function print(f"Sum of {num_1} + {num_2} = {output}") # <-- Sum of 2 + 2 = 4 |
Once written, the block of function is executed once called.
When calling these functions, we can pass data known as parameters into a function that can return data. To define a function in Python, we use the def keyword.
Comments in Python
Another great practice while writing code is adding comments that describe the piece of code and what the functionality is all about. You could also refer to them as little notes for yourself.
Writing comments with Python is very simple. It’s done using the hashtag sign.
1 | # This is how we write a single line comment in Python |
Another type of comment is the multi-line comment used when writing a large text description of code and can be done in this way:
1 2 3 4 5 | """ This is how we write a multi-line comment in Python """ |
Classes and Objects in Python
Classes are vital to understand. A class is a blueprint for creating anything in the real world you can think of that you can represent in code. From this blueprint, we can create one or many objects.
Let’s take for example, a car and a blueprint is the specification of how this car is created. With this class created, we should specify the attributes, which are anything that relates to the car. For example, the year, color, cost, model, make, etc. Let’s see an example with Python.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | class Car: # constructor. How we create this cars def __init__(self, model, price): self.model = model self.price = price # creating a behaviour for the car def driving(self, destination): print(f"{self.model} is driving towards {destination}") # printing objects properly using to string method def __str__(self): return f"Model = {self.model}, Price = {self.price}" |
We also have behaviors that represent what the object we created can do. For example, we can drive the car, turn the steering left or right, make a quick break, or even accelerate.
This is the world of object-oriented programming, which involves creating a bunch of classes and connecting them. It’s also good to know these behaviors can be accessed using the dot notation. Let’s see an example.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | # creating an object from the class Car tesla = Car("Tesla Model S", "$79990") print(tesla) # accessing properties of the class print(f"Model: {tesla.model}") print(f"Price: {tesla.price}") # calling behaviour of the class tesla.driving("846 E 5th Ave. Mt Dora, FL 32757") # ---- output ---- # Model = Tesla Model S, Price = $79990 # Model: Tesla Model S # Price: $79990 # Tesla Model S is driving towards 846 E 5th Ave. Mt Dora, FL 32757 # creating an object from the class Car bmw = Car("Mercedes-Benz S-Class", "$94,250") print(bmw) # accessing properties of the class print(f"Model: {bmw.model}") # <-- Model: Mercedes-Benz S-Class print(f"Price: {bmw.price}") # <-- Price: $94,250 # calling behaviour of the class bmw.driving("846 E 5th Ave. Mt Dora, FL 32757") # ---- output ---- # Model = Mercedes-Benz S-Class, Price = $94,250 # Model: Mercedes-Benz S-Class # Price: $94,250 # Mercedes-Benz S-Class is driving towards 846 E 5th Ave. Mt Dora, FL 32757 |
Handling Errors
If you have written some code up until now, you will have gotten some error messages, which are either:
- Syntax errors: Error in the source code
- Exceptions: Error detected during execution
While coding, most of these exceptions are not taken care of by programs, and Python allows for errors and exceptions to be handled by the program. To do so, we will need to use both the try and except statements, which are:
- Try: Test a block of code for errors
- Except: Handle the Error
- Finally: Executes code regardless of the result of the try-except block.
For example, if we divided a number by zero will get a zero division error:
1 | print(4/0) # <-- ZeroDivisionError: division by zero |
However, we can resolve this by warping the code inside of a try and except block.
1 2 3 4 5 6 7 8 9 10 | try: print(4/ 0) except Exception: print("An exception occurred here") finally: print("Finally block executes regardless of the result") # ---- output --- # An exception occurred here # Finally block executes regardless of the result |
For more information about error handling be sure to visit this site.
As you’ve made it to the end of this tutorial I strongly recommend you visit sites like HackerRank or LeetCode to practice problem solving which will help smoothen and accelerate your learning pace. Finally remember keep practicing. Practicing makes Improvements. Until then, you will hear from me next week.
Conclusion
In this post, you discovered the basic concept behind Python. You have learned about Python Data Types, Variables and String, Lists, Dictionaries, Sets, Tuples, if-else statements, for and while loops, break and continue statement, functions, comments, classes, and objects, and finally handling errors in Python.
Do you have any questions about Python or this post? Leave a comment and ask your question. I’ll do my best to answer.
Further Reading
We have listed some useful resources below if you thirst for more reading.
Articles
- A Simple Walk-through with Pandas for Data Science – Part 1
- Why is Python the most popular language for Data Science
- A Simple Walk-through with NumPy for Data Science
- Data Structures and Algorithms
- Python Tutorial Tutorials Point
- Python Tutorial w3schools
Books
To be notified when this next blog post goes live, be sure to enter your email address in the form!
10 Comments
Your post is well written. Thank you very much for sharing.
It’s my pleasure. Feel free to share among your network.
This is the most comprehensive post i’ve ever read related to Python. Please keep writing more content.
Thank you Mikel.
I love the design on your site also your cheatsheet is well detailed. Thank you.
I’m glad you did.
You have the best content related to Python on the internet. Thank you for sharing. I’m looking up for more of your tutorials.
It’s my Pleasure Nina.
Your content are top notch. Keep on writing more posts related to Python.
Thank you Mina.