Python Essentials: A Speedy Introduction
Tags: python, machinelearning, ai, beginners
Published: 2024-06-25 14:51:02

Are you ready to dive into the exciting world of Artificial Intelligence and Machine Learning but need a quick introduction to Python first? This crash course is here to help! In this article, we'll cover the basics of Python programming to get you up to speed quickly. Whether you're new to programming or just need a refresher, this guide will provide the essential knowledge you need to start coding confidently. Let's get started!


# Chapter 1: Python Syntax and Basics

In this chapter, we'll quickly cover Python's syntax and foundational concepts. This will serve as a concise refresher to familiarize you with Python's unique features.

## Code Structure
Python uses indentation to define blocks of code, unlike languages like JavaScript which use braces. Consistent indentation is crucial as it directly impacts the program's flow. Here's a quick example:


```python
def greet(name):
    if name:
        print(f"Hello, {name}!")
    else:
        print("Hello, world!")

```

## Variables and Data Types

Python is dynamically typed, meaning you don't need to declare the type of a variable when you create one. The basic data types in Python include:

* **Strings**: Defined with single ('...') or double ("...") quotes.
* **Integers**: No special syntax required, e.g., 5.
* **Floats**: Use a point to denote decimal, e.g., 5.0.
* **Booleans**: Written as True or False.

Example


```python
name = "Alice"
age = 30
is_registered = True #capitalized boolean in python

```

## Collections

- **Lists**: Ordered and mutable collection, e.g., numbers = [1, 2, 3].
- **Dictionaries**: Key-value pairs, e.g., person = {"name": "Alice", "age": 30}.
- **Sets**: Unordered collection of unique elements, e.g., unique_numbers = {1, 2, 3}.
- **Tuples**: Ordered and immutable collection, e.g., point = (1, 2).

## List Comprehensions
List comprehensions provide a concise way to create lists:



```python
squares = [x**2 for x in range(10)]
print(squares)
```

    [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]


## Functions

Defining functions in Python uses the def keyword. You can specify default values for parameters, which makes them optional during calls:


```python
def greet(name, greeting="Hello"):
    print(f"{greeting}, {name}!")

greet("Alice")  # Uses the default greeting
greet("Bob", "Howdy")  # Uses a custom greeting

```

This chapter sets the foundation for understanding how Python code is structured and executed. Up next, we will explore control structures to manage the flow of your Python programs.







# Chapter 2: Control Structures

Python's control structures allow you to direct the flow of your program's execution through conditional statements and loops. This section will refresh your understanding of these constructs.

## If, Elif, and Else
Conditional statements in Python are straightforward. The if statement evaluates a condition and executes a block of code if the condition is true. You can extend this logic with elif (else if) and else:


```python
age = 25
if age < 18:
    print("You are a minor.")
elif age < 65:
    print("You are an adult.")
else:
    print("You are a senior.")

```

Python evaluates conditions until one is true, then skips the rest, known as short-circuiting.



## Loops

Python provides for and while loops for iterating over sequences or executing a block of code repeatedly under a condition.

**For Loops:** Used for iterating over a sequence (like a list, tuple, or string).


```python
for number in range(5):  # range(5) generates numbers from 0 to 4
    print(number)
```

**While Loops:** Execute as long as a condition is true.


```python
count = 0
while count < 5:
    print(count)
    count += 1
```

Control within loops can be managed with break (to exit the loop) and continue (to skip the current iteration and continue with the next one):




```python
for number in range(10):
    if number == 3:
        continue  # Skip the print statement for number 3
    if number == 8:
        break  # Exit the loop when number is 8
    print(number)
```

## Iterators and Generators

Python uses iterators for looping. You can create your own iterator by implementing __iter__() and __next__() methods or using generator functions.

- Generators: Use yield to generate a sequence of values. Generators are useful when you want to iterate over a sequence without storing the entire sequence in memory.



```python
def countdown(num):
    while num > 0:
        yield num
        num -= 1

for i in countdown(5):
    print(i)

```

This chapter covers the basic control structures in Python. You'll find these essential for creating conditional logic and managing looping in your Python programs. Next, we'll dive into more Pythonic techniques and features to help you write cleaner and more efficient code.

## Chapter 3: Pythonic Techniques
This chapter delves into more sophisticated Pythonic techniques, enabling you to write cleaner, more efficient, and more Python-specific code. These techniques leverage Python's unique capabilities and idiomatic practices.

## Unpacking
Unpacking allows you to assign values from a list or tuple to variables in a single statement, improving readability and conciseness.


```python
a, b, c = [1, 2, 3]
print(a, b, c)  # Outputs: 1 2 3

# Star expressions for capturing excess items
first, *middle, last = [1, 2, 3, 4, 5]
print(first, middle, last)  # Outputs: 1 [2, 3, 4] 5

```

## Lambda Functions

Lambda functions are small anonymous functions defined with the lambda keyword. They are best used for short, simple functions.



```python
# A simple lambda to add two numbers
add = lambda x, y: x + y
print(add(5, 3))  # Outputs: 8

# Often used in functions like map() and filter()
squares = list(map(lambda x: x**2, range(10)))
print(squares)  # Outputs: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

```

## Map and Filter
The map and filter functions are functional programming tools that apply a function to each item in an iterable (like a list) and return an iterable.

map(): Applies a function to each item in an iterable.
filter(): Extracts elements from an iterable for which a function returns True.


```python
# Using map to square numbers
nums = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x**2, nums))

# Using filter to find even numbers
evens = list(filter(lambda x: x % 2 == 0, nums))

```

When compared to list comprehensions, map() and filter() can be preferable for their readability and expressive power with small lambda functions. However, list comprehensions are often clearer and more Pythonic when the operation is straightforward.

This chapter introduces you to writing Python in a way that is not just correct but also stylistically Pythonic, embracing the language's philosophy of readability and simplicity. By using these advanced features, you can make your code more modular, reusable, and expressive. Up next, we'll cover file handling and exception management to ensure your programs are robust and professional.

# Chapter 4: File Handling and Exception Management

In Python, managing files and handling exceptions are critical for creating robust applications. This chapter covers the essentials of these areas, focusing on best practices and Pythonic approaches.

## File Handling
Python simplifies file operations with built-in functions and methods. The with statement ensures that files are properly closed after their suite finishes, even if an exception is raised.




```python
# Reading from a file
with open('example.txt', 'r') as file:
    content = file.read()
    print(content)

# Writing to a file
with open('output.txt', 'w') as file:
    file.write("Hello, Python!\n")

```

For reading and writing files, Python offers methods like read(), readline(), readlines(), write(), and writelines(), allowing you to handle different file sizes and content types efficiently.

## Exception Handling

Proper error and exception handling is essential for writing reliable and user-friendly programs. Python uses try, except, else, and finally blocks to handle exceptions.




```python
try:
    # Try to do something that might raise an exception
    result = 10 / 0
except ZeroDivisionError:
    # Handle specific exceptions
    print("Divided by zero!")
else:
    # Execute if no exceptions
    print("Division successful!", result)
finally:
    # Always executed
    print("Cleaning up, if needed.")

```

Use specific exception types in except blocks to catch and handle different error conditions appropriately. This not only helps in debugging but also allows the program to continue or fail gracefully.

## Context Managers
For more complex resource management, Python provides context managers that allow you to allocate and release resources precisely when you want. The with statement is commonly used with file handling, as shown above, but can also be used with other resources like network connections or locking mechanisms.


```python
from contextlib import contextmanager

@contextmanager
def managed_file(name):
    try:
        f = open(name, 'w')
        yield f
    finally:
        f.close()

# Usage
with managed_file('hello.txt') as f:
    f.write('hello, world!')

```

This chapter ensures that you are equipped to handle file I/O operations and exceptions in your Python applications effectively, contributing to their reliability and maintainability. Next, we will explore modules, packages, and Python's environment management tools.








# Chapter 5: Modules and Packages
This chapter focuses on the organization and reusability of code in Python through modules and packages. Understanding how to create, import, and manage modules and packages is key for developing maintainable and scalable Python applications.

## Importing Modules
Python's modules are simply Python files with .py extensions containing Python code that can be reused in other Python scripts.





```python
# Importing a whole module
import math
print(math.sqrt(16))  # Outputs: 4.0

# Importing specific functions
from math import sqrt
print(sqrt(16))  # Outputs: 4.0

# Using alias for modules
import numpy as np
array = np.array([1, 2, 3])

```

When you import a module, Python executes all of the code in the module file.

## Creating Modules
Any Python file can be a module. To create a module, simply save your Python code in a .py file. Other Python scripts can then import this file as a module.


```python
# Example of a simple module, saved as calculator.py

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

def subtract(a, b):
    return a - b

```

You can then use this module in other Python scripts:




```python
from calculator import add, subtract
print(add(5, 3))  # Outputs: 8

```

##Packages

A package is a collection of Python modules under a common directory. For Python to recognize a directory as a package, it must contain a file named __init__.py. The file can be empty but it signifies that the directory contains Python modules.


```python
# Assume the following directory structure:
# mypackage/
#   __init__.py
#   subpackage1/
#       __init__.py
#       module1.py
#   subpackage2/
#       __init__.py
#       module2.py

# Importing from a package
from mypackage.subpackage1 import module1
module1.some_function()

```

## Virtual Environments

Using virtual environments in Python helps manage dependencies for different projects. By creating a virtual environment, you can keep dependencies required by different projects separate from each other.





```python
# Creating a virtual environment
python -m venv myprojectenv

# Activating the virtual environment
# On Windows
myprojectenv\Scripts\activate

# On MacOS/Linux
source myprojectenv/bin/activate

```

This setup ensures that any Python packages installed while the virtual environment is active will only affect this particular environment, helping avoid conflicts between project dependencies.

This chapter provides the tools you need to effectively manage and modularize your Python code, essential for professional, clean, and efficient Python programming. Coming up next, we'll discuss best practices in logging and debugging to enhance the observability and maintainability of your Python applications.


# Chapter 6: Logging and Debugging

Effective logging and debugging are crucial for developing, maintaining, and troubleshooting Python applications. This chapter covers how to utilize Python's built-in logging module and debugging tools to keep your applications running smoothly and efficiently.

## Logging
Python's logging module provides a flexible framework for emitting log messages from Python programs. It is preferable to using print statements because it offers different severity levels and allows you to direct the logs to different outputs.




```python
import logging

# Basic configuration to log to file
logging.basicConfig(filename='app.log', level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

# Different levels of logs
logging.debug('This is a debug message')
logging.info('This is an info message')
logging.warning('This is a warning message')
logging.error('This is an error message')
logging.critical('This is a critical message')

```

### Using Log Levels
Log levels provide a way to categorize the importance of the messages logged by the application:

- **DEBUG**: Detailed information, typically of interest only when diagnosing problems.
- **INFO: Confirmation that things are working as expected.
- **WARNING**: An indication that something unexpected happened, or indicative of some problem in the near future.
- **ERROR**: Due to a more serious problem, the software has not been able to perform some function.
- **CRITICAL**: A serious error, indicating that the program itself may be unable to continue running.

Debugging Tools
When it comes to debugging, Python provides several tools to help identify issues in the code. The most commonly used tool is the Python Debugger (pdb), which allows interactive debugging.


```python
import pdb

# Example usage
def div(a, b):
    pdb.set_trace()
    return a / b

print(div(4, 2))

```

Using pdb, you can step through your code, inspect variables, and evaluate expressions to diagnose and fix issues more effectively.

- **Commands:** list (shows current position in the code), next (executes the next line), continue (continues execution until the next breakpoint), break (adds breakpoints), print (prints a variable), and quit (exits the debugger).

Tips for Effective Debugging

- Start Small: Test small parts of your code as you write them.
- Use Logs: Insert logging statements to report the occurrence of particular events.
- Isolate Problems: When you encounter a bug, narrow down where it could be by using unit tests or dividing the code.

This chapter equips you with essential tools for logging and debugging, helping ensure your Python applications perform as intended and making it easier to maintain and troubleshoot them. In the next chapter, we will explore the broader Python ecosystem, including toolchains and additional libraries that can help streamline your Python development process.








#Chapter 7: Toolchain and Additional Libraries

In this final chapter, we'll explore the broader Python ecosystem, focusing on toolchains for code style enforcement, testing, and some additional libraries that extend Python's capabilities. These tools and libraries can significantly enhance productivity and ensure high-quality software development.

## PEP 8 and Linters
PEP 8 is the style guide for Python code. Adhering to PEP 8 helps ensure that your Python code is readable and consistent. Python's linters like flake8 or pylint help enforce coding standards and catch potential errors.


```python
# Installing flake8
pip install flake8

# Using flake8
flake8 my_script.py

```

These tools provide feedback on style issues, complexity, and programmatic errors, making them indispensable for maintaining code quality.

Testing
Testing is critical in the development process to ensure your code behaves as expected.

- unittest: Python’s built-in library that allows you to test small units of code independently.


```python
import unittest

class TestMathOperations(unittest.TestCase):
    def test_add(self):
        self.assertEqual(1 + 1, 2)

    def test_subtract(self):
        self.assertEqual(2 - 1, 1)

if __name__ == '__main__':
    unittest.main()

```

- pytest: A more powerful, third-party testing framework with a simpler syntax and more features than unittest.


```python
# Installing pytest
pip install pytest

# Using pytest
pytest

```

## Popular Python Libraries
Several Python libraries can help simplify complex tasks across different domains:

- **Requests**: Simplifies making HTTP requests for web clients.



```python
import requests
response = requests.get('https://api.example.com/data')

```

- **Pandas:** Essential for data analysis and manipulation.



```python
import pandas as pd
data = pd.read_csv('data.csv')

```

- **NumPy:** Provides support for large, multi-dimensional arrays and matrices.



```python
import numpy as np
array = np.array([1, 2, 3])

```

- **Scikit-Learn:** Ideal for implementing machine learning algorithms.



```python
from sklearn.ensemble import RandomForestClassifier
model = RandomForestClassifier()
model.fit(train_data, train_labels)

```

- **Matplotlib**: A plotting library for creating static, interactive, and animated visualizations in Python


```python
import matplotlib.pyplot as plt
plt.plot([1, 2, 3], [4, 5, 6])
plt.show()

```

# Extra Chapter: Python and Object-Oriented Programming

## Introduction to Classes and Objects
In Python, classes are created using the class keyword, and objects are instances of these classes. Here’s a simple example:




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

    def speak(self, sound):
        return f"{self.name} says {sound}"

# Creating an instance of Dog
my_dog = Dog("Rex", 4)
print(my_dog.speak("Woof"))

```

### Attributes and Methods

Attributes are variables associated with a class, and methods are functions defined within a class that operate on its attributes. The __init__ method is a special method called a constructor, used for initializing an instance of the class.

### Inheritance
Python supports inheritance, allowing multiple base classes and thus facilitating complex relationships between objects.




```python
class Cat(Dog):  # Inherits from Dog
    def purr(self):
        return f"{self.name} purrs."

# Usage
my_cat = Cat("Whiskers", 3)
print(my_cat.speak("Meow"))  # Inherited method
print(my_cat.purr())         # New method

```

### Encapsulation
Encapsulation is the bundling of data with the methods that operate on these data. It restricts direct access to some of the object’s components, which can prevent the accidental modification of data:




```python
class Person:
    def __init__(self, name, age):
        self.name = name
        self._age = age  # Leading underscore suggests protected (by convention)

    def get_age(self):
        return self._age

# Direct access to _age is discouraged
john = Person("John", 28)
print(john.get_age())

```

### Polymorphism
Polymorphism allows for the interchangeability of components through a common interface. In Python, it’s more loosely applied, allowing different classes to be used interchangeably if they implement the same methods.




```python
def animal_sound(animal):
    print(animal.speak("Hi there"))

animal_sound(my_dog)
animal_sound(my_cat)

```
---

Congratulations on completing this quick crash course on Python basics! I hope this speedy overview has given you a solid foundation in Python programming, equipping you with the essential skills needed to embark on your AI and ML journey. While this guide covered the fundamentals, there's so much more to learn and explore when implementing practical solutions in the world of Artificial Intelligence and Machine Learning. As you continue to build on these basics, you'll discover the power and versatility of Python in solving complex problems and creating innovative solutions. Stay curious, keep coding, and get ready to transform your ideas into reality with Python!

Notebook version: [https://github.com/mubbashir10/applied_ai/blob/main/Chapter%200%20-%20Python%20basics.ipynb](https://github.com/mubbashir10/applied_ai/blob/main/Chapter%200%20-%20Python%20basics.ipynb
)