Python for Absolute Beginners

This course is designed to take you from a complete beginner to a competent Python programmer. It is divided into 10 modules, each focusing on a specific topic and providing practical examples to help you understand the concepts better.

  1. πŸ”πŸ Module 1: Introduction to Python Programming: Get to know what Python is, why it's popular, and how you can use our online Python editor and console to write and run Python code.

  2. πŸ“˜πŸ”’ Module 2: Python Basics: Dive into Python basics, such as data types and operators. Get your hands dirty with plenty of coding examples.

  3. πŸ“¦πŸ“š Module 3: Data Structures: Learn about the core data structures in Python - lists, tuples, dictionaries, and sets.

  4. πŸ…°οΈπŸ”‘ Module 4: Variables: Understand what variables are, how to create them, and how they are used in Python.

  5. ⭕️❓ Module 5: Conditional Statements and Looping: Learn how to control the flow of your Python program using conditional statements (if, elif, else) and loops (for, while). Also get introduced to break, continue, and pass statements.

  6. πŸ”„πŸ“Œ Module 6: Functions: Discover the power of functions in Python, including defining and calling functions, understanding function arguments, and using lambda functions with map, filter, and reduce.

  7. πŸ§©πŸ”— Module 7: Object Oriented Programming (OOP): Understand the OOP paradigm in Python, including classes, objects, initializers, inheritance, polymorphism, encapsulation, and magic or dunder methods.

  8. πŸ’¬πŸ–¨οΈ Module 8: Strings and The Print Function: Dive deeper into Python's string data type and understand the power of the print function.

  9. πŸ“‚πŸ–₯️ Module 9: What We Have Not Covered: Understand some important topics that were not covered in the course, such as modules, file handling, and GUI programming.

  10. πŸŽ“βž‘οΈ Module 10: Conclusion and How to Proceed: Summarize what you've learned and understand how to continue your Python programming journey.

Each module builds upon the knowledge gained in the previous one, and you'll be writing code right from the start. Remember, the best way to learn to code is by coding!


You're encouraged to experiment and practice as much as possible, and don't forget to have fun along the way. Welcome to Python programming!


πŸ”πŸ Module 1: Introduction to Python Programming

1.1 Introduction to Python

Python is an interpreted, high-level, and general-purpose programming language. It was created by Guido van Rossum and first released in 1991. Python's design philosophy emphasizes code readability with its notable use of significant indentation.

Python is a versatile language that is used in a variety of applications, ranging from simple scripts, web development, game development, data analysis, machine learning, AI, scientific computing, and more. Companies such as Google, NASA, and Netflix use Python in their tech stack due to its simplicity and the wide variety of libraries available.

1.2 Setting up your Python Environment

Don't worry about installing Python on your computer just yet. While reading this tutorial, you can run your Python code directly on our website. We have a built-in Python editor that lets you write, edit, and run Python code. So, for all the code examples in this tutorial, you can just press the "Edit" buttom in the top right corner. You can also use the deticated Python Scratch Area (We recommend opening it in a new tab or browser window).

Moreover, our Python Scratch Area also includes a Python interpreter console. This can can also be very handy when you just want to try something out.

However, if you wish to install Python on your own computer for offline use or other projects, please refer to this Installation Guide.

1.3 Python Environment: Interactive and Script Mode

Python can be used in two modes:

  1. Interactive Mode: It functions like a simple calculator. You can type a Python expression, and the interpreter evaluates it immediately and displays the result. Our Python Scratch Area's "Python Console" acts as an interactive Python interpreter.

  2. Script Mode: In script mode, you write your code in a file which is then run by the Python interpreter. In this mode, the code is not executed immediately. You can write a complete program, save it, and then run it. The scratch area can be used to run the code in the editor in script mode (just press the run button).

1.4 Your First Python Program

Let's dive in and write your first Python program.

print("Hello, world!")
print("Hello, world!")

Run this program! You should see the words "Hello, world!" printed on your screen. This is a traditional first program for many languages. The print() function in Python outputs the text or variable placed within the parentheses.

Modify the program to write something else! Congratulations! You've just written and run your first Python program.

In the next module, we'll explore the basic elements of Python like syntax, data types, and operators. Happy coding!

πŸ“˜πŸ”’ Module 2: Python Basics

Python programming, much like dancing, is all about the right steps (syntax), understanding your partner (data types), and knowing when to take the lead (operators). But don't worry, even if you've got two left feet, you'll still be able to master Python!

2.1 Understanding Python Syntax

Python is quite polite and likes a neat and clean conversations (code). That's why it insists on proper indentation. Unlike some other languages, which rely on punctuation marks like {}, Python uses indentation to define a block of code.

Try this in the Python Scratch Area:

if 5 > 2:
    print("Five is indeed greater than two!")
    print("This is another line in the same block as the previous line.")
if 5 > 2:
    print("Five is indeed greater than two!")
    print("This is another line in the same block as the previous line.")

Python appreciates your neatness and rewards you with "Five is indeed greater than two!" If you don't indent it properly, Python will get confused and you'll get an error. Remember, in Python, indentation isn't just about looking prettyβ€”it's a must!

2.2 Python Data Types

In Python, we have various types of data. Let's get our hands dirty and play around with these different data types in the Python Scratch Area:

# Integer
print(42)
print(type(42))

# Float
print(3.14159)
print(type(3.14159))

# String
print("Hello, Python!")
print(type("Hello, Python!"))

# Boolean
print(True)
print(type(True))

# NoneType
print(None)
print(type(None))
# Integer
print(42)
print(type(42))

# Float
print(3.14159)
print(type(3.14159))

# String
print("Hello, Python!")
print(type("Hello, Python!"))

# Boolean
print(True)
print(type(True))

# NoneType
print(None)
print(type(None))

You'll see that Python correctly identifies each type. Python knows its data types like a fish knows water!

2.3 Operators in Python

Operators are the life of the party in Python. They help you perform all kinds of operations on your data.

But enough of theory. Let's test some operators in the Python Scratch Area:

# Arithmetic operators
print("Arithmetic operators:")
print(20 + 42)       # addition
print(42 - 20)       # subtraction
print(20 * 42)       # multiplication
print(42 / 2)        # division
print(42 // 2)       # floor division
print(42 % 20)       # modulo
print(2 ** 3)        # exponentiation

# Comparison operators
print("\nComparison operators:")
print(42 == 42)      # equals
print(42 != 20)      # not equal
print(42 > 20)       # greater than
print(42 < 20)       # less than
print(42 >= 20)      # greater than or equal to
print(42 <= 20)      # less than or equal to

# Assignment operators
print("\nAssignment operators:")
x = 42
print(x)             # assignment
x += 2
print(x)             # addition assignment
x -= 2
print(x)             # subtraction assignment

# Logical operators
print("\nLogical operators:")
print(True and False)
print(True or False)
print(not False)

# Membership operators
print("\nMembership operators:")
print(1 in [1, 2, 3])
print(4 not in [1, 2, 3])

# Identity operators
n42 = 42
n41 = 41
print("\nIdentity operators:")
print(n42 is n42)
print(n41 is not n42)
# Arithmetic operators
print("Arithmetic operators:")
print(20 + 42)       # addition
print(42 - 20)       # subtraction
print(20 * 42)       # multiplication
print(42 / 2)        # division
print(42 // 2)       # floor division
print(42 % 20)       # modulo
print(2 ** 3)        # exponentiation

# Comparison operators
print("\nComparison operators:")
print(42 == 42)      # equals
print(42 != 20)      # not equal
print(42 > 20)       # greater than
print(42 < 20)       # less than
print(42 >= 20)      # greater than or equal to
print(42 <= 20)      # less than or equal to

# Assignment operators
print("\nAssignment operators:")
x = 42
print(x)             # assignment
x += 2
print(x)             # addition assignment
x -= 2
print(x)             # subtraction assignment

# Logical operators
print("\nLogical operators:")
print(True and False)
print(True or False)
print(not False)

# Membership operators
print("\nMembership operators:")
print(1 in [1, 2, 3])
print(4 not in [1, 2, 3])

# Identity operators
n42 = 42
n41 = 41
print("\nIdentity operators:")
print(n42 is n42)
print(n41 is not n42)

Experiment with code above, make mistakes, learn from them, and above all, have fun!

In the next module, we'll introduce you to Python's dance troupe, also known as Data Structures. So, grab a snack (an integer or a string, perhaps), take a break, and brace yourself for the next exciting chapter!

Remember, programming should be fun. If you're not having fun, you're not doing it right. So keep coding and keep experimenting. Until next time!

πŸ“¦πŸ“š Module 3: Data Structures in Python

Data structures in Python are like containers that store and organize your data. They come in different shapes and sizes, with each one having its own special features.

3.1 Lists

A list in Python is a collection of items that are ordered and changeable. Lists allow duplicate items and are created by placing items, separated by commas, inside square brackets [].

Let's create a list in the Python Scratch Area:

fruits = ["apple", "banana", "cherry"]
print(fruits)
# Accessing an item in the list
# Remember, Python is zero-indexed
print(fruits[0])
print(fruits[2])
# Pick out a range of items from the list
# The first index is inclusive, the second is exclusive
# So, this will print the first two items
print(fruits[0:2])
fruits = ["apple", "banana", "cherry"]
print(fruits)
# Accessing an item in the list
# Remember, Python is zero-indexed
print(fruits[0])
print(fruits[2])
# Pick out a range of items from the list
# The first index is inclusive, the second is exclusive
# So, this will print the first two items
print(fruits[0:2])

List Methods

Python provides several useful methods that you can use on lists.

fruits = ["apple", "banana", "cherry"]
# Adding an item to the list
fruits.append("orange")
print(fruits)

# Removing an item from the list
fruits.remove("banana")
print(fruits)

# Remove the last item from the list and return it
last_item = fruits.pop()
print(last_item)
print(fruits)

# Add back the item that was removed
fruits.append(last_item)

# Sorting the list
fruits.sort()
print(fruits)
fruits = ["apple", "banana", "cherry"]
# Adding an item to the list
fruits.append("orange")
print(fruits)

# Removing an item from the list
fruits.remove("banana")
print(fruits)

# Remove the last item from the list and return it
last_item = fruits.pop()
print(last_item)
print(fruits)

# Add back the item that was removed
fruits.append(last_item)

# Sorting the list
fruits.sort()
print(fruits)

List Comprehension

List comprehension is a feature of Python that allows you to create a new list from an existing one in a single, readable line of code.

# Create a list of the first ten square numbers
squares = [x**2 for x in range(1, 11)]
print(squares)
# Create a list of the first ten square numbers
squares = [x**2 for x in range(1, 11)]
print(squares)

One can also use list comprehension to filter the elements of a list.

# Create a list of the first ten positive numbers
# that are divisible by two
squares = [x for x in range(1, 11) if x % 2 == 0]
print(squares)
# Create a list of the first ten positive numbers
# that are divisible by two
squares = [x for x in range(1, 11) if x % 2 == 0]
print(squares)

3.2 Tuples

A tuple, like a list, is an ordered collection of items. However, tuples are unchangeable, meaning that you cannot add, remove, or change items after the tuple is created.

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

Use tuples when you want a list of items that cannot be changed. Lists can not be used as keys in dictionaries, but tuples can. We will learn more about dictionaries in the next module.

3.3 Dictionaries

A dictionary is an unordered collection of items. Each item in a dictionary is stored as a key-value pair.

car = {
  "brand": "Ford",
  "model": "Mustang",
  "year": 1964
}
print(car)
# Accessing a value using its key
print(car["model"])
# Accessing all the keys in the dictionary
print(car.keys())
# Accessing all the values in the dictionary
print(car.values())
# Accessing all the key-value pairs in the dictionary
print(car.items())
# Get item with key "model" and return "None" if it doesn't exist
print(car.get("model"))
# Get item with key "year" and crash if it doesn't exist
print(car["year"])

# Here is a dictionary with tuples as keys (keys need to be hashable which
# means that not all objects can be used as keys)
d = {
  (1, 2): 3,
  (4, 5): 6
}
car = {
  "brand": "Ford",
  "model": "Mustang",
  "year": 1964
}
print(car)
# Accessing a value using its key
print(car["model"])
# Accessing all the keys in the dictionary
print(car.keys())
# Accessing all the values in the dictionary
print(car.values())
# Accessing all the key-value pairs in the dictionary
print(car.items())
# Get item with key "model" and return "None" if it doesn't exist
print(car.get("model"))
# Get item with key "year" and crash if it doesn't exist
print(car["year"])

# Here is a dictionary with tuples as keys (keys need to be hashable which
# means that not all objects can be used as keys)
d = {
  (1, 2): 3,
  (4, 5): 6
}

Dictionary Modification

Dictionaries have their own set of methods for manipulating the data they contain.

car = {
  "brand": "Ford",
  "model": "Mustang",
  "year": 1964
}
# Changing the value of a key
car["year"] = 2020
print(car)

# Adding a new key-value pair
car["color"] = "red"
print(car)
car = {
  "brand": "Ford",
  "model": "Mustang",
  "year": 1964
}
# Changing the value of a key
car["year"] = 2020
print(car)

# Adding a new key-value pair
car["color"] = "red"
print(car)

Dictionary Comprehension

Like lists, dictionaries also support comprehension to create new dictionaries.

# Create a dictionary where the keys are numbers from 1 to 5 and the values are their squares
squares = {x: x**2 for x in range(1, 6)}
print(squares)
# Create a dictionary where the keys are numbers from 1 to 5 and the values are their squares
squares = {x: x**2 for x in range(1, 6)}
print(squares)

3.4 Sets

A set is an unordered collection of items that does not allow duplicates. It is useful when you want to store multiple items in a single variable, and you are not interested in their order, index, or duplicates.

fruits = {"apple", "banana", "cherry", "apple"}
print(fruits)  # Duplicates will be removed
fruits = {"apple", "banana", "cherry", "apple"}
print(fruits)  # Duplicates will be removed

Set Methods

Sets offer several methods to perform common set operations.

fruits = {"apple", "banana", "cherry", "apple"}
# Add an item to the set
fruits.add("orange")
print(fruits)

# Remove an item from the set
fruits.remove("apple")
print(fruits)

# Check if an item is in the set
print("banana" in fruits)
fruits = {"apple", "banana", "cherry", "apple"}
# Add an item to the set
fruits.add("orange")
print(fruits)

# Remove an item from the set
fruits.remove("apple")
print(fruits)

# Check if an item is in the set
print("banana" in fruits)

Set Operations

Sets support operations like union, intersection, difference, and symmetric difference.

A = {1, 2, 3}
B = {2, 3, 4}

print(A.union(B))                 # {1, 2, 3, 4}
print(A.intersection(B))          # {2, 3}
print(A.difference(B))            # {1}
print(A.symmetric_difference(B))  # {1, 4}
A = {1, 2, 3}
B = {2, 3, 4}

print(A.union(B))                 # {1, 2, 3, 4}
print(A.intersection(B))          # {2, 3}
print(A.difference(B))            # {1}
print(A.symmetric_difference(B))  # {1, 4}

3.5 Further Reading: Python Documentation

Python has a robust set of built-in methods that you can perform on different types. Each data type in Python has a set of methods that are specific to it. If you're curious to delve deeper and explore more about these methods, Python's official documentation is your best source of information.

  1. List methods: Python's lists come packed with a multitude of methods to add, remove, or manipulate items. You can find detailed explanations, along with examples, in the Python documentation for list methods.

  2. Tuple methods: While tuples are immutable, Python does provide a couple of useful methods that you can use with tuples. Check the Python documentation for tuple methods to learn more.

  3. Dictionary methods: Dictionaries in Python come with a variety of handy methods that make it easier for you to access, change, or manipulate dictionary data. Detailed information on these methods can be found in the Python documentation for dictionary methods.

  4. Set methods: Sets in Python have a rich set of methods to perform common mathematical set operations and more. You can find more about these methods in the Python documentation for set methods.

Remember, the Python documentation is a rich resource, don't hesitate to use it whenever you're in doubt or just curious. Happy coding!

3.6 Module Conclusion

Python's data structures are versatile and powerful. Take time to practice with these examples and try to create your own. Understanding these data structures is key to becoming proficient in Python. Happy coding!

πŸ…°οΈπŸ”‘ Module 4: Understanding Variables in Python

Variables are like labels attached to values. They allow us to store, manipulate, and retrieve data in our programs. In this module, we'll get acquainted with these vital elements in Python.

4.1 What is a Variable?

Think of a variable as a box that can hold a value. You can put something in the box, look inside to see what's there, or even replace the contents with something else. In Python, creating a variable is as easy as giving it a name and assigning it a value using the = sign.

# Creating variables
greeting = "Hello, Python!"
number = 42
pi_value = 3.14159
# Creating variables
greeting = "Hello, Python!"
number = 42
pi_value = 3.14159

You can now use these variable names in your code to access their values.

greeting = "Hello, Python!"
number = 42
pi_value = 3.14159
# Printing the variables
print(greeting)
print(number)
print(pi_value)
greeting = "Hello, Python!"
number = 42
pi_value = 3.14159
# Printing the variables
print(greeting)
print(number)
print(pi_value)

4.2 Rules for Variable Names

While you have a lot of freedom in choosing variable names, there are a few rules you need to follow:

  1. Variable names must start with a letter or an underscore: _my_var, my_var are valid, 1my_var is not.
  2. The remainder of your variable name may consist of letters, numbers, and underscores: my_var1 is valid.
  3. Variable names are case-sensitive: my_var, my_Var, and MY_VAR are each a different variable.

A good practice is to give your variables informative names that reflect the data they store.

4.3 Changing Variable Values

One of the key features of variables is that their values can be changed. Let's say we want to change the value of number from 42 to 23. We can simply assign a new value to number:

number = 42
print(number)  # Outputs: 42
number = 23
print(number)  # Outputs: 23
number = 42
print(number)  # Outputs: 42
number = 23
print(number)  # Outputs: 23

As you can see, number now holds the value 23, not 42. Python always keeps track of the latest value that a variable was assigned.

4.4 Different Data Types

In Python, variables can hold different types of data. We've already seen strings (greeting = "Hello, Python!") and numbers (number = 42, pi_value = 3.14159). Let's revisit our data structures, but this time we'll store them in variables:

# List
my_list = [1, 2, 3]
print(my_list)

# Tuple
my_tuple = (1, 2, 3)
print(my_tuple)

# Dictionary
my_dict = {"one": 1, "two": 2, "three": 3}
print(my_dict)

# Set
my_set = {1, 2, 3, 1, 2}
print(my_set)  # Outputs: {1, 2, 3}, because sets remove duplicates
# List
my_list = [1, 2, 3]
print(my_list)

# Tuple
my_tuple = (1, 2, 3)
print(my_tuple)

# Dictionary
my_dict = {"one": 1, "two": 2, "three": 3}
print(my_dict)

# Set
my_set = {1, 2, 3, 1, 2}
print(my_set)  # Outputs: {1, 2, 3}, because sets remove duplicates

4.5 Module Conclusion

Congratulations, you've just dipped your toes into one of the most essential parts of Python programming! Get comfortable with variables, as they will be your faithful companions on this coding journey. Remember, practice makes perfect. Happy coding!

⭕️❓ Module 5: Conditional Statements and Looping in Python

Imagine you're at a pizza party. You're in line, waiting your turn to get a slice. If there's still pizza when you get to the front, you'll take a slice. If they only have olives (and who likes olives?), you'll pass. If they're out of pizza, you'll go home. This decision-making is similar to how programs work. In this module, we'll explore how to make our Python programs make decisions and repeat actions.

5.1 Conditional Statements: If, Elif, Else

The if, elif, and else statements in Python allow our program to make decisions.

pizza = "available"

if pizza == "available":
    print("I'm getting a slice!")
else:
    print("No pizza, I'm going home.")
pizza = "available"

if pizza == "available":
    print("I'm getting a slice!")
else:
    print("No pizza, I'm going home.")

Sometimes, you have more than two possible paths. That's where elif (short for "else if") comes into play:

pizza = "only olives"

if pizza == "available":
    print("I'm getting a slice!")
elif pizza == "only olives":
    print("I'll pass. I don't like olives.")
else:
    print("No pizza, I'm going home.")
pizza = "only olives"

if pizza == "available":
    print("I'm getting a slice!")
elif pizza == "only olives":
    print("I'll pass. I don't like olives.")
else:
    print("No pizza, I'm going home.")

You can also skip the else part altogether:

pizza = "only olives"
if pizza == "available":
    print("I'm getting a slice!")

print("Let's go home.")
pizza = "only olives"
if pizza == "available":
    print("I'm getting a slice!")

print("Let's go home.")

5.2 Looping: For and While Loops

When you want to repeat an action in Python, for and while loops come to the rescue.

A for loop in Python is used to iterate over a sequence (like a list, tuple, or string) or other iterable objects:

# Printing each fruit in a list
fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
    print(fruit)
# Printing each fruit in a list
fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
    print(fruit)

A while loop in Python is used to repeatedly execute a block of statements as long as the given condition is true:

# Eating pizza while there's still some left
slices = 5
while slices > 0:
    print("I'm eating a slice!")
    slices -= 1  # This is the same as slices = slices - 1
# Eating pizza while there's still some left
slices = 5
while slices > 0:
    print("I'm eating a slice!")
    slices -= 1  # This is the same as slices = slices - 1

Break, Continue, and Pass

break, continue, and pass are statements you can use in your loops for more control.

  • break is used to exit the loop prematurely:
for number in range(1, 11):  # This generates numbers from 1 to 10
    if number == 5:
        break
    print(number)
for number in range(1, 11):  # This generates numbers from 1 to 10
    if number == 5:
        break
    print(number)
  • continue is used to skip the rest of the loop for the current iteration and move on to the next:
for number in range(1, 11):
    if number == 5:
        continue
    print(number)
for number in range(1, 11):
    if number == 5:
        continue
    print(number)
  • pass is a placeholder and does nothing. It's used when a statement is required syntactically, but you don't want any command or code to execute:
for number in range(1, 11):
    if number == 5:
        pass  # We'll decide what to do about 5 later
    print(number)
for number in range(1, 11):
    if number == 5:
        pass  # We'll decide what to do about 5 later
    print(number)

That's it! You're now equipped with the power to control the flow of your Python programs. Like a boss at a pizza party, you can now make decisions and perform actions repeatedly. Happy coding!

πŸ”„πŸ“Œ Module 6: Functions in Python

6.1 Defining a Function

In Python, a function is a reusable block of code that performs a specific task. Functions help organize your code, make it more readable, and save you from writing the same lines of code again and again.

To define a function, we use the def keyword, followed by a function name, parentheses (), and a colon :. The function's code block is indented under the definition.

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

Once you've defined a function, you can call it by using its name followed by parentheses:

greet()  # Outputs: Hello, Python!
greet()  # Outputs: Hello, Python!

There are two types of functions in Python: built-in functions, like print(), len(), type(), etc., and user-defined functions, which are functions that you define yourself, like our greet() function above.

Functions can also return a result that you can use later in your code. This is done by using the return keyword:

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

result = add_two_numbers(3, 5)
print(result)  # Outputs: 8
def add_two_numbers(a, b):
    return a + b

result = add_two_numbers(3, 5)
print(result)  # Outputs: 8

In this case, the add_two_numbers() function adds two numbers and returns the result.

6.2 Function Arguments

Functions become even more powerful when you can pass data to them. This data is called an argument, and it can be of any data type.

Required Arguments

Required arguments are arguments that need to be passed to a function in the correct positional order.

def greet(name):
    print("Hello, " + name + "!")

greet("Python")  # Outputs: Hello, Python!
def greet(name):
    print("Hello, " + name + "!")

greet("Python")  # Outputs: Hello, Python!

Keyword Arguments

Keyword arguments are related to the function call. When you use keyword arguments in a function call, the caller identifies the arguments by the parameter name.

def describe_pet(animal, name):
    print("I have a " + animal + " named " + name + ".")

describe_pet(name="Python", animal="snake")  # Outputs: I have a snake named Python.
def describe_pet(animal, name):
    print("I have a " + animal + " named " + name + ".")

describe_pet(name="Python", animal="snake")  # Outputs: I have a snake named Python.

Default Arguments

Default arguments are arguments that assume a default value if a value is not provided in the function call.

def describe_pet(name, animal="dog"):
    print("I have a " + animal + " named " + name + ".")

describe_pet(name="Rover")  # Outputs: I have a dog named Rover.
def describe_pet(name, animal="dog"):
    print("I have a " + animal + " named " + name + ".")

describe_pet(name="Rover")  # Outputs: I have a dog named Rover.

Variable-length Arguments

Sometimes, we may need to process a function for more arguments than specified while defining the function. These arguments are called variable-length arguments.

def add_numbers(*args):
    return sum(args)

print(add_numbers(1, 2, 3, 4, 5))  # Outputs: 15
def add_numbers(*args):
    return sum(args)

print(add_numbers(1, 2, 3, 4, 5))  # Outputs: 15

6.3 Lambda Functions, Map, Filter, Reduce, and List Comprehensions

Lambda Functions

Lambda functions are small, anonymous functions that are defined with the lambda keyword, rather than def.

square = lambda x: x ** 2
print(square(5))  # Outputs: 25
square = lambda x: x ** 2
print(square(5))  # Outputs: 25

Map and List Comprehensions

The map function applies a given function to each item of an iterable and returns a list of the results.

numbers = [1, 2, 3, 4, 5]
squares = map(lambda x: x ** 2, numbers)
print(list(squares))  # Outputs: [1, 4, 9, 16, 25]
numbers = [1, 2, 3, 4, 5]
squares = map(lambda x: x ** 2, numbers)
print(list(squares))  # Outputs: [1, 4, 9, 16, 25]

The same operation can be achieved using list comprehensions, a more 'Pythonic' way of transforming lists:

numbers = [1, 2, 3, 4, 5]
squares = [x ** 2 for x in numbers]
print(squares)  # Outputs: [1, 4, 9, 16, 25]
numbers = [1, 2, 3, 4, 5]
squares = [x ** 2 for x in numbers]
print(squares)  # Outputs: [1, 4, 9, 16, 25]

Filter and List Comprehensions

The filter function constructs a list from elements of an iterable for which a function returns true.

numbers = [1, 2, 3, 4, 5]
even_numbers = filter(lambda x: x % 2 == 0, numbers)
print(list(even_numbers))  # Outputs: [2, 4]
numbers = [1, 2, 3, 4, 5]
even_numbers = filter(lambda x: x % 2 == 0, numbers)
print(list(even_numbers))  # Outputs: [2, 4]

Just like with map, list comprehensions can also be used to filter lists:

numbers = [1, 2, 3, 4, 5]
even_numbers = [x for x in numbers if x % 2 == 0]
print(even_numbers)  # Outputs: [2, 4]
numbers = [1, 2, 3, 4, 5]
even_numbers = [x for x in numbers if x % 2 == 0]
print(even_numbers)  # Outputs: [2, 4]

Reduce

The reduce function applies a function of two arguments cumulatively to the items of an iterable in a way that it reduces the iterable to a single output. This function is part of the functools module.

from functools import reduce

numbers = [1, 2, 3, 4, 5]
product = reduce(lambda x, y: x * y, numbers)
print(product)  # Outputs: 120
from functools import reduce

numbers = [1, 2, 3, 4, 5]
product = reduce(lambda x, y: x * y, numbers)
print(product)  # Outputs: 120

Lambda functions, map, filter, reduce, and list comprehensions are all useful tools to help you manipulate lists and other iterables. Experiment with them and see which methods you prefer.

6.4 Understanding nonlocal and global keywords

Python provides two keywords nonlocal and global to manage the scope of variables. These keywords are used when you want to assign a value to a variable defined in the nearest enclosing scope that is not global, or in the global scope, respectively.

nonlocal Keyword

The nonlocal keyword is used in a nested function to state that a variable refers to a variable of the nearest enclosing scope that is not global.

Let's look at an example:

def outer_function():
    x = 10
    def inner_function():
        nonlocal x  # This is the nonlocal variable
        x = 20
        print("Inner function: x =", x)

    inner_function()
    print("Outer function: x =", x)

outer_function()
def outer_function():
    x = 10
    def inner_function():
        nonlocal x  # This is the nonlocal variable
        x = 20
        print("Inner function: x =", x)

    inner_function()
    print("Outer function: x =", x)

outer_function()

In this example, when we call outer_function(), the inner_function is also executed. Even though x is defined in the outer function, because we use the nonlocal keyword in the inner function, the value of x is changed both inside the inner function and in the outer function. Don't forget to experiment with the code above until you are sure you understand what nonlocal do. What happens if you comment out the line with nonlocal? Does x in the inner scope refer to another variable in that case?

global Keyword

The global keyword is used to define a variable inside a function to be of global scope. That means, this variable can be accessed and modified from anywhere in the program, both inside and outside of the function.

Here's an example:

x = 10

def my_function():
    global x  # This is the global variable
    x = 20
    print("Function: x =", x)

my_function()
print("Global: x =", x)
x = 10

def my_function():
    global x  # This is the global variable
    x = 20
    print("Function: x =", x)

my_function()
print("Global: x =", x)

In this example, x is a global variable. When we call my_function(), the global keyword is used to indicate that x in the function refers to the global x. Therefore, when x is changed inside the function, it also changes the global x.

Remember, the use of global should be minimized as it often make programs harder to understand. It's often better to avoid that keyword by structuring your code differently. However, there are scenarios where global variables are the right choice. Don't forget to experiment with the code above until you fully understand what global does.


πŸ§©πŸ”— Module 7: Object-Oriented Programming (OOP) in Python

Welcome to the realm of Object-Oriented Programming (OOP)! OOP is a way of programming that focuses on using objects and classes to design and build applications. It can be a bit complex, especially for beginners, but don't worry, we'll guide you through it!

7.1 Introduction to OOP: Classes, Objects, and Initializers

Classes and Objects

In Python, everything is an object, and each object is an instance of a class. A class can be thought of as a blueprint for creating objects. Let's define a simple class:

class Dog:
    def bark(self):
        print("Woof!")
class Dog:
    def bark(self):
        print("Woof!")

In this code, Dog is a class, and bark is a method that belongs to this class. To use the class, we create an object (or an instance) of this class:

class Dog:
    def bark(self):
        print("Woof!")

my_dog = Dog()
my_dog.bark()  # Outputs: Woof!
class Dog:
    def bark(self):
        print("Woof!")

my_dog = Dog()
my_dog.bark()  # Outputs: Woof!

Initializers

The __init__ method is a special method that Python calls when it creates an object. We can use this method to set the initial state of the object:

class Dog:
    def __init__(self, name):
        self.name = name

    def bark(self):
        print(f"Woof! My name is {self.name}.")

my_dog = Dog("Fido")
my_dog.bark()  # Outputs: Woof! My name is Fido.
class Dog:
    def __init__(self, name):
        self.name = name

    def bark(self):
        print(f"Woof! My name is {self.name}.")

my_dog = Dog("Fido")
my_dog.bark()  # Outputs: Woof! My name is Fido.

In the example above, name is an attribute of the Dog class, and self is a reference to the instance of the class.

7.2 Inheritance, Polymorphism, Encapsulation

Inheritance

Inheritance allows us to define a class that inherits all the methods and properties from another class. The class that is being inherited from is called the parent class, and the class that inherits is called the child class.

class Animal:
    def __init__(self, name):
        self.name = name

class Dog(Animal):
    def bark(self):
        print(f"Woof! My name is {self.name}.")

my_dog = Dog("Fido")
my_dog.bark()  # Outputs: Woof! My name is Fido.
class Animal:
    def __init__(self, name):
        self.name = name

class Dog(Animal):
    def bark(self):
        print(f"Woof! My name is {self.name}.")

my_dog = Dog("Fido")
my_dog.bark()  # Outputs: Woof! My name is Fido.

Polymorphism

Polymorphism allows us to use a single type entity (method, operator, or object) to represent different types in different scenarios.

class Animal:
    def __init__(self, name):
        self.name = name
    def emit_sound(self):
        print("Generic animal sound.")

class Dog(Animal):
    def bark(self):
        print(f"Woof! My name is {self.name}.")
    def emit_sound(self):
        print("Woof!")

class Cat(Animal):
    def purr(self):
        print(f"Purr! My name is {self.name}.")
    def emit_sound(self):
        print("Meow!")

def pet_animal(animal):
    if isinstance(animal, Dog):
        animal.bark()
    elif isinstance(animal, Cat):
        animal.purr()
    print(f"Emit sound:")
    animal.emit_sound()
        

my_dog = Dog("Fido")
my_cat = Cat("Whiskers")
pet_animal(my_dog)  # Outputs: Woof! My name is Fido.
pet_animal(my_cat)  # Outputs: Purr! My name is Whiskers.
class Animal:
    def __init__(self, name):
        self.name = name
    def emit_sound(self):
        print("Generic animal sound.")

class Dog(Animal):
    def bark(self):
        print(f"Woof! My name is {self.name}.")
    def emit_sound(self):
        print("Woof!")

class Cat(Animal):
    def purr(self):
        print(f"Purr! My name is {self.name}.")
    def emit_sound(self):
        print("Meow!")

def pet_animal(animal):
    if isinstance(animal, Dog):
        animal.bark()
    elif isinstance(animal, Cat):
        animal.purr()
    print(f"Emit sound:")
    animal.emit_sound()
        

my_dog = Dog("Fido")
my_cat = Cat("Whiskers")
pet_animal(my_dog)  # Outputs: Woof! My name is Fido.
pet_animal(my_cat)  # Outputs: Purr! My name is Whiskers.

Encapsulation

Encapsulation is the practice of keeping fields within a class private. This means that the fields can only be manipulated through methods of their class.

class Animal:
    def __init__(self, name):
        self._name = name

    @property
    def name(self):
        return self._name

    @name.setter
    def name(self, name):
        if not isinstance(name, str):
            raise ValueError("Name must be a string.")
        self._name = name

animal = Animal("Fido")
print(animal.name)  # Outputs: Fido

animal.name = "Bella"
print(animal.name)  # Outputs: Bella

animal.name = 123  # Raises: ValueError: Name must be a string.
class Animal:
    def __init__(self, name):
        self._name = name

    @property
    def name(self):
        return self._name

    @name.setter
    def name(self, name):
        if not isinstance(name, str):
            raise ValueError("Name must be a string.")
        self._name = name

animal = Animal("Fido")
print(animal.name)  # Outputs: Fido

animal.name = "Bella"
print(animal.name)  # Outputs: Bella

animal.name = 123  # Raises: ValueError: Name must be a string.

In the example above, the @property decorator allows us to access the private _name attribute through a getter method, and the @name.setter decorator allows us to change the _name attribute value through a setter method. A python convention is to prefix variables that should be accessed only from within an instance of a class with _. We call such variables private fields.

7.3 Special Methods: Magic Methods or Dunder Methods

In Python, special methods are a way to add "magic" to your classes. They're always surrounded by double underscores (hence the nickname "dunder" methods). You've already seen one of these special methods, __init__.

Here's an example of the __str__ method, which allows us to define a string representation for the object:

class Dog:
    def __init__(self, name):
        self.name = name

    def __str__(self):
        return f"This is a dog named {self.name}."

my_dog = Dog("Fido")
print(my_dog)  # Outputs: This is a dog named Fido.
class Dog:
    def __init__(self, name):
        self.name = name

    def __str__(self):
        return f"This is a dog named {self.name}."

my_dog = Dog("Fido")
print(my_dog)  # Outputs: This is a dog named Fido.

This is a great example of a dunder method in action. When we try to print our Dog object, Python will call the __str__ method to see how it should represent the object as a string.

Here's another example with __len__:

class Team:
    # The initializer method
    def __init__(self, members):
        self.members = members

    # For len(team) (returns the number of team members)
    def __len__(self):
        return len(self.members)
    
    # For iterating over the team object in a for loop
    def __iter__(self):
        return iter(self.members)
        
    # Accessing a member by using the index
    # e.g. team[0] to get the first member
    def __getitem__(self, i):
        return self.members[i]
    
    # Changing a member by using the index
    # e.g. team[0] = "Alice" to change the first member to "Alice"
    def __setitem__(self, i, member):
        self.members[i] = member
    
    def __str__(self):
        return f"Team {len(self)} members: {', '.join(self)}"

my_team = Team(["Alice", "Bob", "Charlie"])
print(len(my_team))  # Outputs: 3
print(my_team[0])  # Outputs: Alice
my_team[0] = "Alice 2.0"
print(my_team[0])  # Outputs: Alice 2.0
print("My team:")
for member in my_team:
    print(member)
class Team:
    # The initializer method
    def __init__(self, members):
        self.members = members

    # For len(team) (returns the number of team members)
    def __len__(self):
        return len(self.members)
    
    # For iterating over the team object in a for loop
    def __iter__(self):
        return iter(self.members)
        
    # Accessing a member by using the index
    # e.g. team[0] to get the first member
    def __getitem__(self, i):
        return self.members[i]
    
    # Changing a member by using the index
    # e.g. team[0] = "Alice" to change the first member to "Alice"
    def __setitem__(self, i, member):
        self.members[i] = member
    
    def __str__(self):
        return f"Team {len(self)} members: {', '.join(self)}"

my_team = Team(["Alice", "Bob", "Charlie"])
print(len(my_team))  # Outputs: 3
print(my_team[0])  # Outputs: Alice
my_team[0] = "Alice 2.0"
print(my_team[0])  # Outputs: Alice 2.0
print("My team:")
for member in my_team:
    print(member)

In this case, when we use the built-in len function on our Team object, Python will call the __len__ method.

There are many other dunder methods that you can use to add functionality to your classes, such as __add__, __eq__, and others. You can find a comprehensive list of these methods in the Python docs.

And there you have it! The basics of Object-Oriented Programming in Python. As always, practice is key, so don't forget to create some classes and experiment with objects in your Scratch Area!

πŸ’¬πŸ–¨οΈ Module 8: Deep Dive into Strings and the Print Function

In previous modules, we've met the string data type and the print() function briefly. In this module, we're going to take a closer look at strings and the print() function. Buckle up!

8.1 Strings

Strings are sequences of characters and they can be defined using either single quotes ' or double quotes ".

greeting = "Hello, World!"
print(greeting)  # Outputs: Hello, World!
greeting = "Hello, World!"
print(greeting)  # Outputs: Hello, World!

You can also define a multi-line string using triple quotes ''' or """:

haiku = """
An old silent pond...
A frog jumps into the pondβ€”
Splash! Silence again.
"""
print(haiku)
haiku = """
An old silent pond...
A frog jumps into the pondβ€”
Splash! Silence again.
"""
print(haiku)

String Concatenation

You can concatenate, or add together, strings using the + operator:

greeting = "Hello, " + "World!"
print(greeting)  # Outputs: Hello, World!
greeting = "Hello, " + "World!"
print(greeting)  # Outputs: Hello, World!

Format Strings (f-strings)

In Python 3.6 and above, you can use f-strings to embed expressions inside string literals. The syntax is to start the string with the letter "f" or "F" before the opening quote.

name = "Alice"
greeting = f"Hello, {name}!"
print(greeting)  # Outputs: Hello, Alice!
# f-strings works for multi-line strings too
haiku = f"""
An old silent pond...
A {name} jumps into the pondβ€”
Splash! Silence again.
"""
print(haiku)
name = "Alice"
greeting = f"Hello, {name}!"
print(greeting)  # Outputs: Hello, Alice!
# f-strings works for multi-line strings too
haiku = f"""
An old silent pond...
A {name} jumps into the pondβ€”
Splash! Silence again.
"""
print(haiku)

In the example above, {name} is a placeholder that gets replaced with the value of the name variable. You can put any Python expression inside the curly braces and it will be evaluated and converted to a string.

8.2 The Print Function

The print() function outputs the specified message to the screen. The message can be a string, or any other object, and the object will be converted into a string before being written to the screen.

print("Hello, World!")  # Outputs: Hello, World!
print("Hello, World!")  # Outputs: Hello, World!

By default, print() adds a newline character ('\n') at the end of the line. If you don't want this, you can set the end parameter to an empty string:

print("Hello, ", end="")
print("World!")  # Outputs: Hello, World!
print("Hello, ", end="")
print("World!")  # Outputs: Hello, World!

The print() function can also take multiple arguments, and it will print them all, separated by a space:

print("Hello,", "World!")  # Outputs: Hello, World!
print("Hello,", "World!")  # Outputs: Hello, World!

The separator between the arguments can be changed by setting the sep parameter:

print("Hello,", "World!", sep="***")  # Outputs: Hello,***World!
print("Hello,", "World!", sep="***")  # Outputs: Hello,***World!

And that concludes our dive into strings and the print() function. Be sure to experiment with these in your Scratch Area and explore all the interesting things you can do with them!

πŸ“‚πŸ–₯️ Module 9: What We Have Not Covered

In this course, we've covered many of the foundational aspects of Python programming. You've learned about data types, variables, functions, conditional statements, loops, and object-oriented programming among other things. With these concepts, you can already write powerful and complex Python programs. However, Python is a versatile and extensive language, and there's always more to learn!

Here are a few important topics that we didn't have the time to cover in this course:

Modules

In Python, a module is a file containing Python definitions and statements. The file name is the module name with the suffix .py added. You can use any Python source file as a module by executing an import statement in some other Python source file. This is a large topic, and you can read more about it in the Python docs.

File Handling

Python provides in-built functions for creating, writing, reading, and closing files. This is an incredibly useful feature for any programmer, allowing your programs to interact with your filesystem. Here's a brief example of how to write to a file:

# Open a file for writing and create it
# if it doesn't exist
with open("myfile.txt", "w") as f:
    f.write("Hello, file!")
# Read the contents of the file
with open("myfile.txt", "r") as f:
    print(f.read())
# Open a file for writing and create it
# if it doesn't exist
with open("myfile.txt", "w") as f:
    f.write("Hello, file!")
# Read the contents of the file
with open("myfile.txt", "r") as f:
    print(f.read())

There's a lot more to it, so you can learn more from the Python docs.

GUI Programming

While most of our examples have been in the command line, Python also supports Graphical User Interfaces (GUI). You can build desktop applications with user-friendly interfaces. Python has a variety of libraries for creating GUIs, such as Tkinter, PyQt, and others. You can find more information about Tkinter, the standard Python interface to the Tk GUI toolkit, in the Python docs.


These are just a few of the many topics in Python we didn't cover. Others include database connectivity, threading, testing, and web scraping, just to name a few. Python is a world full of possibilities, and we've just scratched the surface.

However, remember that what you've learned in this course forms the backbone of Python programming. The skills and knowledge you've acquired are transferable to these other areas. So don't stop now! Continue exploring, coding, and having fun with Python.

Remember, the official Python documentation is an extensive resource where you can learn more about the language's many features. Happy coding!

πŸŽ“βž‘οΈ Module 10: Conclusion and How to Proceed

Congratulations! You've reached the end of this introductory Python course. Give yourself a pat on the back, because you've done something amazing. You have taken the first steps on a fascinating journey into the world of Python programming.

In this course, you've learned about Python's basic data types, variables, conditional statements, loops, functions, and object-oriented programming. You've been introduced to the different data structures Python offers, such as lists, tuples, dictionaries, and sets. You've learned about the importance of indentation in Python, discovered how to work with strings, and experienced the power of Python's print() function. In essence, you've established a solid foundation for your Python programming journey.

So, how can you proceed from here?

  1. Continue Experimenting: Programming, like any skill, is something that improves with practice. Keep experimenting with the concepts you've learned. The Scratch Area on this site is a great place to practice. Try writing different kinds of Python scripts and see what happens. Be curious, explore, make mistakes, and learn.

  2. Start Writing Your Own Programs: Think about a simple problem or task you'd like to automate, and try to write a Python program that does it. It doesn't have to be complex. It could be as simple as a program that calculates your age in days, or something more complex like a simple game. The key is to start building things.

  3. Solve Programming Problems: A fantastic way to improve your programming skills is by solving problems. Head over to the problems section of this website. Start with the easy problems and gradually take on more challenging ones as your confidence and skills grow.

  4. Keep Learning: The world of Python is vast and constantly evolving. There's always more to learn. Use the resources available to you. The Internet is filled with tutorials, documentation, and forums where you can expand your knowledge and get help when you're stuck. The official Python documentation is a particularly good resource. AI chatbots like ChatGPT can also be helpful in providing explanations and answering queries.

Python is not just a programming language. It's a tool that can open doors to many exciting opportunities. Whether you're interested in web development, data science, artificial intelligence, or simply automating tasks, Python is a versatile language that can help you achieve your goals.

This is not the end of your Python journey, but rather the beginning. Keep exploring, keep coding, and most importantly, keep having fun. Good luck on your journey, and happy coding!