1. Skip to content

1. Python Cheat Sheet

This cheat sheet provides an exhaustive overview of the Python programming language, covering essential syntax, data structures, functions, modules, and best practices for efficient development. It aims to be a one-stop reference for common tasks.

1.1 Getting Started

1.1.1 Installation

Check if Python is already installed:

python --version
python3 --version

Install Python using a package manager (e.g., apt, brew, choco) or from the official website:

1.1.2 Running Python Code

Interactive Mode:

python
python3

Run a Python Script:

python my_script.py
python3 my_script.py

1.2 Basic Syntax

1.2.1 Comments

# This is a single-line comment

"""
This is a multi-line comment
"""

1.2.2 Variables

x = 10
name = "Alice"
is_active = True

1.2.3 Data Types

  • int: Integer
  • float: Floating-point number
  • str: String
  • bool: Boolean (True/False)
  • list: List
  • tuple: Tuple
  • dict: Dictionary
  • set: Set
  • NoneType: None

1.2.4 Operators

Arithmetic:

  • +: Addition
  • -: Subtraction
  • *: Multiplication
  • /: Division
  • //: Floor division
  • %: Modulus
  • **: Exponentiation

Comparison:

  • ==: Equal to
  • !=: Not equal to
  • >: Greater than
  • <: Less than
  • >=: Greater than or equal to
  • <=: Less than or equal to

Logical:

  • and: Logical AND
  • or: Logical OR
  • not: Logical NOT

Assignment:

  • =: Assignment
  • +=, -=, *=, /=, //=, %=, **=: Compound assignment

Identity:

  • is: Tests if two variables refer to the same object
  • is not: Tests if two variables do not refer to the same object

Membership:

  • in: Tests if a value is a member of a sequence
  • not in: Tests if a value is not a member of a sequence

Bitwise:

  • &: Bitwise AND
  • |: Bitwise OR
  • ^: Bitwise XOR
  • ~: Bitwise NOT
  • <<: Left shift
  • >>: Right shift

1.2.5 Control Flow

If Statement:

x = 10
if x > 0:
    print("Positive")
elif x == 0:
    print("Zero")
else:
    print("Negative")

For Loop:

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

While Loop:

i = 0
while i < 5:
    print(i)
    i += 1

Break and Continue:

for i in range(10):
    if i == 3:
        break  # Exit the loop
    if i == 1:
        continue  # Skip to the next iteration
    print(i)

Try-Except Block:

try:
    result = 10 / 0
except ZeroDivisionError:
    print("Cannot divide by zero")
finally:
    print("This will always execute")

1.2.6 Functions

Defining a Function:

def greet(name="World"):
    """This function greets the person passed in as a parameter.
    If no parameter is passed, it greets the world."""
    print(f"Hello, {name}!")

greet("Alice")
greet()

Function Arguments:

  • Positional arguments
  • Keyword arguments
  • Default arguments
  • *args: Variable-length positional arguments (as a tuple)
  • **kwargs: Variable-length keyword arguments (as a dictionary)
def my_function(a, b=2, *args, **kwargs):
    print(f"a: {a}, b: {b}, args: {args}, kwargs: {kwargs}")

my_function(1, 2, 3, 4, name="Alice", age=30)

Lambda Functions:

square = lambda x: x ** 2
print(square(5))

1.2.7 Data Structures

Lists:

my_list = [1, 2, "hello", True]
my_list.append(5)
my_list.insert(2, "new")
my_list.remove(2)
my_list.pop(1)
print(my_list[0])
print(my_list[-1])
print(my_list[1:3])

Tuples:

my_tuple = (1, 2, "hello")
print(my_tuple[0])

Dictionaries:

my_dict = {"name": "Alice", "age": 30}
my_dict["city"] = "New York"
print(my_dict["name"])
print(my_dict.get("age"))
print(my_dict.keys())
print(my_dict.values())
print(my_dict.items())

Sets:

my_set = {1, 2, 3, 4}
my_set.add(5)
my_set.remove(2)
print(my_set)

1.2.8 List Comprehensions

numbers = [1, 2, 3, 4, 5]
squares = [x ** 2 for x in numbers]
even_squares = [x ** 2 for x in numbers if x % 2 == 0]

1.2.9 Dictionary Comprehensions

numbers = [1, 2, 3, 4, 5]
square_dict = {x: x ** 2 for x in numbers}

1.2.10 Set Comprehensions

numbers = [1, 2, 2, 3, 4, 4, 5]
unique_squares = {x ** 2 for x in numbers}

1.2.11 Generators

def my_generator(n):
    for i in range(n):
        yield i ** 2

for value in my_generator(5):
    print(value)

1.3 Modules and Packages

1.3.1 Importing Modules

import math
print(math.sqrt(16))

import datetime
now = datetime.datetime.now()
print(now)

from collections import Counter

1.3.2 Creating Modules

Create a file named my_module.py:

def my_function():
    print("Hello from my_module!")

my_variable = 10

Import and use the module:

import my_module

my_module.my_function()
print(my_module.my_variable)

1.3.3 Packages

Create a directory named my_package with an __init__.py file inside.

Create modules inside the package (e.g., my_package/module1.py, my_package/module2.py).

Import and use the package:

import my_package.module1
from my_package import module2

my_package.module1.my_function()
module2.another_function()

1.4 File I/O

1.4.1 Reading from a File

with open("my_file.txt", "r") as f:
    content = f.read()
    print(content)

1.4.2 Writing to a File

with open("my_file.txt", "w") as f:
    f.write("Hello, file!")

1.4.3 Appending to a File

with open("my_file.txt", "a") as f:
    f.write("\nAppending to the file.")

1.4.4 Reading Lines from a File

with open("my_file.txt", "r") as f:
    for line in f:
        print(line.strip())

1.5 String Formatting

1.5.1 f-strings (Python 3.6+)

name = "Alice"
age = 30
print(f"My name is {name} and I am {age} years old.")

1.5.2 str.format()

name = "Alice"
age = 30
print("My name is {} and I am {} years old.".format(name, age))

1.5.3 % Formatting

name = "Alice"
age = 30
print("My name is %s and I am %d years old." % (name, age))

1.6 Regular Expressions

1.6.1 Importing the re Module

import re

1.6.2 Common Functions

  • re.search(pattern, string): Searches for a pattern in a string.
  • re.match(pattern, string): Matches a pattern at the beginning of a string.
  • re.findall(pattern, string): Finds all occurrences of a pattern.
  • re.sub(pattern, replacement, string): Replaces occurrences of a pattern.
  • re.split(pattern, string): Splits a string by a pattern.

1.6.3 Example

import re

text = "The quick brown fox jumps over the lazy dog."
pattern = r"\b\w{5}\b"  # Matches 5-letter words

matches = re.findall(pattern, text)
print(matches)  # Output: ['quick', 'brown', 'jumps']

1.7 Date and Time

1.7.1 Importing the datetime Module

import datetime

1.7.2 Common Functions

  • datetime.datetime.now(): Returns the current date and time.
  • datetime.date.today(): Returns the current date.
  • datetime.datetime(year, month, day, hour, minute, second): Creates a datetime object.
  • datetime.timedelta(days, seconds, microseconds): Represents a duration.
  • datetime.strftime(format): Formats a datetime object as a string.
  • datetime.strptime(date_string, format): Parses a string into a datetime object.

1.7.3 Example

import datetime

now = datetime.datetime.now()
print(now)

formatted_date = now.strftime("%Y-%m-%d %H:%M:%S")
print(formatted_date)

parsed_date = datetime.datetime.strptime("2025-02-08 10:30:00", "%Y-%m-%d %H:%M:%S")
print(parsed_date)

1.8 JSON Processing

1.8.1 Importing the json Module

import json

1.8.2 Common Functions

  • json.dumps(object): Serializes a Python object to a JSON string.
  • json.loads(json_string): Deserializes a JSON string to a Python object.
  • json.dump(object, file): Serializes a Python object to a JSON file.
  • json.load(file): Deserializes a JSON file to a Python object.

1.8.3 Example

import json

data = {"name": "Alice", "age": 30}
json_string = json.dumps(data)
print(json_string)

parsed_data = json.loads(json_string)
print(parsed_data["name"])

1.9 Working with CSV Files

1.9.1 Importing the csv Module

import csv

1.9.2 Reading CSV Files

with open('my_data.csv', 'r') as file:
    reader = csv.reader(file)
    for row in reader:
        print(row)

1.9.3 Writing CSV Files

data = [['Name', 'Age', 'City'],
        ['Alice', 30, 'New York'],
        ['Bob', 25, 'Paris']]

with open('output.csv', 'w', newline='') as file:
    writer = csv.writer(file)
    writer.writerows(data)

1.9.4 Reading CSV Files as Dictionaries

import csv

with open('my_data.csv', mode='r') as csv_file:
    csv_reader = csv.DictReader(csv_file)
    for row in csv_reader:
        print(row['Name'], row['Age'], row['City'])

1.9.5 Writing CSV Files from Dictionaries

import csv

fieldnames = ['Name', 'Age', 'City']
data = [
    {'Name': 'Alice', 'Age': 30, 'City': 'New York'},
    {'Name': 'Bob', 'Age': 25, 'City': 'Paris'}
]

with open('output.csv', mode='w', newline='') as csv_file:
    writer = csv.DictWriter(csv_file, fieldnames=fieldnames)

    writer.writeheader()
    writer.writerows(data)

1.10 Working with OS

1.10.1 Importing the os Module

import os

1.10.2 Common Functions

  • os.getcwd(): Returns the current working directory.
  • os.chdir(path): Changes the current working directory.
  • os.listdir(path): Returns a list of files and directories in a directory.
  • os.mkdir(path): Creates a directory.
  • os.makedirs(path): Creates a directory and any necessary parent directories.
  • os.remove(path): Removes a file.
  • os.rmdir(path): Removes a directory.
  • os.path.join(path1, path2, ...): Joins path components.
  • os.path.exists(path): Checks if a path exists.
  • os.path.isfile(path): Checks if a path is a file.
  • os.path.isdir(path): Checks if a path is a directory.
  • os.path.splitext(path): Splits a path into filename and extension.

1.10.3 Example

import os

current_directory = os.getcwd()
print(current_directory)

new_path = os.path.join(current_directory, "my_folder")
if not os.path.exists(new_path):
    os.makedirs(new_path)

1.11 Working with Collections

1.11.1 Importing the collections Module

import collections

1.11.2 Common Data Structures

  • Counter: Counts the frequency of items in a sequence.
  • defaultdict: A dictionary that provides a default value for missing keys.
  • namedtuple: Creates named tuples.
  • deque: A double-ended queue.

1.11.3 Example

from collections import Counter, defaultdict, namedtuple

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

# defaultdict
my_dict = defaultdict(int)
my_dict["a"] += 1
print(my_dict["a"])
print(my_dict["b"])

# namedtuple
Point = namedtuple("Point", ["x", "y"])
p = Point(10, 20)
print(p.x, p.y)

1.12 Working with Itertools

1.12.1 Importing the itertools Module

import itertools

1.12.2 Common Functions

  • itertools.count(start, step): Returns an infinite iterator that produces consecutive integers.
  • itertools.cycle(iterable): Returns an infinite iterator that cycles through the elements of an iterable.
  • itertools.repeat(object, times): Returns an iterator that produces the same object a specified number of times.
  • itertools.chain(*iterables): Chains multiple iterables together into a single iterator.
  • itertools.combinations(iterable, r): Returns all possible combinations of length r from the elements of an iterable.
  • itertools.permutations(iterable, r): Returns all possible permutations of length r from the elements of an iterable.
  • itertools.product(*iterables): Returns the Cartesian product of multiple iterables.
  • itertools.groupby(iterable, key): Groups consecutive elements of an iterable based on a key function.

1.12.3 Example

import itertools

# Count
for i in itertools.count(start=10, step=2):
    if i > 20:
        break
    print(i)

# Cycle
count = 0
for item in itertools.cycle(['A', 'B', 'C']):
    if count > 5:
        break
    print(item)
    count += 1

# Combinations
for combo in itertools.combinations([1, 2, 3, 4], 2):
    print(combo)

1.13 Working with functools

1.13.1 Importing the functools Module

import functools

1.13.2 Common Functions

  • functools.partial(func, *args, **kwargs): Creates a new function with some of the arguments of the original function pre-filled.
  • functools.lru_cache(maxsize=128): Decorator that caches the results of a function call.
  • functools.reduce(function, iterable[, initializer]): Apply function of two arguments cumulatively to the items of iterable, from left to right, so as to reduce the iterable to a single value.

1.13.3 Example

import functools

def power(base, exponent):
    return base ** exponent

square = functools.partial(power, exponent=2)
cube = functools.partial(power, exponent=3)

print(square(5))  # Output: 25
print(cube(2))    # Output: 8

@functools.lru_cache(maxsize=None)
def fibonacci(n):
    if n < 2:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

print(fibonacci(10))

1.14 Concurrency and Parallelism

1.14.1 Threads

import threading

def my_task(name):
    print(f"Thread {name}: starting")
    # Perform some work
    print(f"Thread {name}: finishing")

threads = []
for i in range(3):
    t = threading.Thread(target=my_task, args=(i,))
    threads.append(t)
    t.start()

for t in threads:
    t.join()

1.14.2 Processes

import multiprocessing

def my_task(name):
    print(f"Process {name}: starting")
    # Perform some work
    print(f"Process {name}: finishing")

processes = []
for i in range(3):
    p = multiprocessing.Process(target=my_task, args=(i,))
    processes.append(p)
    p.start()

for p in processes:
    p.join()

1.14.3 Asyncio

import asyncio

async def my_coroutine(name):
    print(f"Coroutine {name}: starting")
    await asyncio.sleep(1)
    print(f"Coroutine {name}: finishing")

async def main():
    tasks = [my_coroutine(i) for i in range(3)]
    await asyncio.gather(*tasks)

asyncio.run(main())

1.15 Type Hints

def add(x: int, y: int) -> int:
    return x + y

def greet(name: str) -> str:
    return f"Hello, {name}!"

from typing import List, Tuple, Dict

my_list: List[int] = [1, 2, 3]
my_tuple: Tuple[str, int] = ("Alice", 30)
my_dict: Dict[str, int] = {"a": 1, "b": 2}

1.16 Virtual Environments

1.16.1 Creating a Virtual Environment

python -m venv myenv

1.16.2 Activating a Virtual Environment

On Linux/macOS:

source myenv/bin/activate

On Windows:

myenv\Scripts\activate

1.16.3 Deactivating a Virtual Environment

deactivate

1.17 Testing

1.17.1 Using unittest

import unittest

class MyTestCase(unittest.TestCase):
    def test_addition(self):
        self.assertEqual(1 + 1, 2)

    def test_subtraction(self):
        self.assertNotEqual(5 - 2, 4)

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

1.17.2 Using pytest

Installation:

pip install pytest

Test Example:

# test_my_module.py
def add(x, y):
    return x + y

def test_add():
    assert add(1, 2) == 3
    assert add(-1, 1) == 0

Run tests:

pytest

1.18 Decorators

def my_decorator(func):
    def wrapper(*args, **kwargs):
        print("Before function execution")
        result = func(*args, **kwargs)
        print("After function execution")
        return result
    return wrapper

@my_decorator
def say_hello(name):
    print(f"Hello, {name}!")

say_hello("Alice")

1.19 Context Managers

with open("my_file.txt", "r") as f:
    content = f.read()
    print(content)

# Custom context manager
class MyContextManager:
    def __enter__(self):
        print("Entering the context")
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        print("Exiting the context")
        if exc_type:
            print(f"An exception occurred: {exc_type}")

    def do_something(self):
        print("Doing something in the context")

with MyContextManager() as cm:
    cm.do_something()

1.20 Object-Oriented Programming (OOP)

1.20.1 Classes and Objects

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

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

my_dog = Dog("Buddy", "Golden Retriever")
print(my_dog.name)
my_dog.bark()

1.20.2 Inheritance

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

    def speak(self):
        raise NotImplementedError("Subclass must implement abstract method")

class Dog(Animal):
    def speak(self):
        return "Woof!"

class Cat(Animal):
    def speak(self):
        return "Meow!"

dog = Dog("Buddy")
cat = Cat("Whiskers")
print(dog.speak())
print(cat.speak())

1.20.3 Encapsulation

class MyClass:
    def __init__(self):
        self._protected_variable = 10  # Protected variable (convention)
        self.__private_variable = 20  # Private variable (name mangling)

    def get_private(self): #getter
        return self.__private_variable

    def set_private(self, value): #setter
        if value > 0:
            self.__private_variable = value

obj = MyClass()
print(obj._protected_variable)
# print(obj.__private_variable)  # AttributeError: 'MyClass' object has no attribute '__private_variable'
print(obj.get_private()) # Accessing private variable through a getter method.
obj.set_private(30)
print(obj.get_private())

1.20.4 Polymorphism

class Animal:
    def speak(self):
        raise NotImplementedError("Subclass must implement abstract method")

class Dog(Animal):
    def speak(self):
        return "Woof!"

class Cat(Animal):
    def speak(self):
        return "Meow!"

def animal_sound(animal):
    print(animal.speak())

dog = Dog("Buddy")
cat = Cat("Whiskers")
animal_sound(dog)
animal_sound(cat)

1.20.5 Class Methods and Static Methods

class MyClass:
    class_variable = 0

    def __init__(self, instance_variable):
        self.instance_variable = instance_variable

    @classmethod
    def increment_class_variable(cls):
        cls.class_variable += 1

    @staticmethod
    def static_method():
        print("This is a static method")

MyClass.increment_class_variable()
print(MyClass.class_variable)
MyClass.static_method()

1.21 Metaclasses

class MyMetaclass(type):
    def __new__(cls, name, bases, attrs):
        attrs['attribute'] = 100
        return super().__new__(cls, name, bases, attrs)

class MyClass(metaclass=MyMetaclass):
    pass

obj = MyClass()
print(obj.attribute)  # Output: 100

1.22 Abstract Base Classes (ABCs)

from abc import ABC, abstractmethod

class MyAbstractClass(ABC):
    @abstractmethod
    def my_method(self):
        pass

class MyConcreteClass(MyAbstractClass):
    def my_method(self):
        print("Implementation of my_method")

# obj = MyAbstractClass()  # TypeError: Can't instantiate abstract class MyAbstractClass with abstract methods my_method
obj = MyConcreteClass()
obj.my_method()

1.23 Exception Handling

try:
    result = 10 / 0
except ZeroDivisionError:
    print("Cannot divide by zero")
except Exception as e:
    print(f"An error occurred: {e}")
else:
    print("No errors occurred")
finally:
    print("This will always execute")

1.23.1 Raising Exceptions

def divide(x, y):
    if y == 0:
        raise ValueError("Cannot divide by zero")
    return x / y

1.23.2 Custom Exceptions

class MyCustomError(Exception):
    pass

def my_function():
    raise MyCustomError("Something went wrong")

1.24 Iterators and Generators

1.24.1 Iterators

my_list = [1, 2, 3]
my_iterator = iter(my_list)
print(next(my_iterator))
print(next(my_iterator))
print(next(my_iterator))

1.24.2 Generators

def my_generator(n):
    for i in range(n):
        yield i ** 2

for value in my_generator(5):
    print(value)

# Generator expression
squares = (x**2 for x in range(5))
for square in squares:
    print(square)

1.25 Decorators

def my_decorator(func):
    def wrapper(*args, **kwargs):
        print("Before function execution")
        result = func(*args, **kwargs)
        print("After function execution")
        return result
    return wrapper

@my_decorator
def say_hello(name):
    print(f"Hello, {name}!")

say_hello("Alice")

1.25.1 Decorators with Arguments

def repeat(num_times):
    def decorator_repeat(func):
        def wrapper(*args, **kwargs):
            for _ in range(num_times):
                result = func(*args, **kwargs)
            return result
        return wrapper
    return decorator_repeat

@repeat(num_times=3)
def greet(name):
    print(f"Hello {name}")

greet("Alice")

1.26 Context Managers

with open("my_file.txt", "r") as f:
    content = f.read()
    print(content)

# Custom context manager
class MyContextManager:
    def __enter__(self):
        print("Entering the context")
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        print("Exiting the context")
        if exc_type:
            print(f"An exception occurred: {exc_type}")

    def do_something(self):
        print("Doing something in the context")

with MyContextManager() as cm:
    cm.do_something()

1.27 Descriptors

class MyDescriptor:
    def __get__(self, instance, owner):
        print(f"Getting: instance={instance}, owner={owner}")
        return instance._value

    def __set__(self, instance, value):
        print(f"Setting: instance={instance}, value={value}")
        instance._value = value

    def __delete__(self, instance):
        print(f"Deleting: instance={instance}")
        del instance._value

class MyClass:
    my_attribute = MyDescriptor()

obj = MyClass()
obj.my_attribute = 10
print(obj.my_attribute)
del obj.my_attribute

1.28 Metaclasses

class MyMetaclass(type):
    def __new__(cls, name, bases, attrs):
        attrs['attribute'] = 100
        return super().__new__(cls, name, bases, attrs)

class MyClass(metaclass=MyMetaclass):
    pass

obj = MyClass()
print(obj.attribute)  # Output: 100

1.29 Abstract Base Classes (ABCs)

from abc import ABC, abstractmethod

class MyAbstractClass(ABC):
    @abstractmethod
    def my_method(self):
        pass

class MyConcreteClass(MyAbstractClass):
    def my_method(self):
        print("Implementation of my_method")

# obj = MyAbstractClass()  # TypeError: Can't instantiate abstract class MyAbstractClass with abstract methods my_method
obj = MyConcreteClass()
obj.my_method()

1.30 Working with Dates and Times

import datetime

now = datetime.datetime.now()
print(now)

today = datetime.date.today()
print(today)

# Creating datetime objects
dt = datetime.datetime(2024, 1, 1, 12, 30, 0)

# Formatting datetime objects
formatted_date = now.strftime("%Y-%m-%d %H:%M:%S")
print(formatted_date)

# Parsing strings into datetime objects
parsed_date = datetime.datetime.strptime("2024-01-01 12:30:00", "%Y-%m-%d %H:%M:%S")
print(parsed_date)

# Time deltas
delta = datetime.timedelta(days=5, hours=3)
new_date = now + delta
print(new_date)

# Working with timezones
import pytz
timezone = pytz.timezone("America/Los_Angeles")
localized_time = timezone.localize(datetime.datetime(2024, 1, 1, 12, 0, 0))
print(localized_time)

1.31 Working with CSV Files

import csv

# Reading CSV files
with open('my_data.csv', 'r') as file:
    reader = csv.reader(file)
    for row in reader:
        print(row)

# Writing CSV files
data = [['Name', 'Age', 'City'],
        ['Alice', 30, 'New York'],
        ['Bob', 25, 'Paris']]

with open('output.csv', 'w', newline='') as file:
    writer = csv.writer(file)
    writer.writerows(data)

# Reading CSV files as dictionaries
with open('my_data.csv', mode='r') as csv_file:
    csv_reader = csv.DictReader(csv_file)
    for row in csv_reader:
        print(row['Name'], row['Age'], row['City'])

# Writing CSV files from dictionaries
fieldnames = ['Name', 'Age', 'City']
data = [
    {'Name': 'Alice', 'Age': 30, 'City': 'New York'},
    {'Name': 'Bob', 'Age': 25, 'City': 'Paris'}
]

with open('output.csv', mode='w', newline='') as csv_file:
    writer = csv.DictWriter(csv_file, fieldnames=fieldnames)

    writer.writeheader()
    writer.writerows(data)

1.32 Working with JSON

import json

# Serializing Python objects to JSON
data = {"name": "Alice", "age": 30, "city": "New York"}
json_string = json.dumps(data, indent=4) # indent for pretty printing
print(json_string)

# Deserializing JSON to Python objects
parsed_data = json.loads(json_string)
print(parsed_data["name"])

# Reading JSON from a file
with open("data.json", "r") as f:
    data = json.load(f)

# Writing JSON to a file
with open("data.json", "w") as f:
    json.dump(data, f, indent=4)

1.33 Working with Regular Expressions

import re

text = "The quick brown fox jumps over the lazy dog."
pattern = r"\b\w{5}\b"  # Matches 5-letter words

# Search for a pattern
match = re.search(pattern, text)
if match:
    print(match.group(0))

# Find all occurrences of a pattern
matches = re.findall(pattern, text)
print(matches)  # Output: ['quick', 'brown', 'jumps']

# Replace occurrences of a pattern
new_text = re.sub(pattern, "five", text)
print(new_text)

# Split a string by a pattern
parts = re.split(r"\s+", text) # Split by whitespace
print(parts)

# Compile a pattern for reuse
compiled_pattern = re.compile(pattern)
matches = compiled_pattern.findall(text)

1.34 Working with OS

import os

# Get the current working directory
current_directory = os.getcwd()
print(current_directory)

# Change the current working directory
os.chdir("/path/to/new/directory")

# List files and directories
files_and_dirs = os.listdir(".")
print(files_and_dirs)

# Create a directory
os.mkdir("my_new_directory")
os.makedirs("path/to/new/directory") # Creates intermediate directories as needed

# Remove a file
os.remove("my_file.txt")

# Remove a directory
os.rmdir("my_empty_directory")
import shutil
shutil.rmtree("my_directory") # Removes a directory and its contents

# Join path components
new_path = os.path.join(current_directory, "my_folder")
print(new_path)

# Check if a path exists
if os.path.exists(new_path):
    print("Path exists")

# Check if a path is a file
if os.path.isfile("my_file.txt"):
    print("It's a file")

# Check if a path is a directory
if os.path.isdir("my_folder"):
    print("It's a directory")

# Get the file extension
filename, extension = os.path.splitext("my_file.txt")
print(extension)

# Get environment variables
print(os.environ.get("HOME"))

1.35 Working with Collections

import collections

# Counter
my_list = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
count = collections.Counter(my_list)
print(count)
print(count.most_common(2))

# defaultdict
my_dict = collections.defaultdict(int)
my_dict["a"] += 1
print(my_dict["a"])
print(my_dict["b"])  # Accessing a missing key returns the default value

# namedtuple
Point = collections.namedtuple("Point", ["x", "y"])
p = Point(10, 20)
print(p.x, p.y)

# deque
my_deque = collections.deque([1, 2, 3])
my_deque.append(4)
my_deque.appendleft(0)
my_deque.pop()
my_deque.popleft()
print(my_deque)

# OrderedDict (less relevant in Python 3.7+ where dicts maintain insertion order)
my_ordered_dict = collections.OrderedDict()
my_ordered_dict['a'] = 1
my_ordered_dict['b'] = 2
my_ordered_dict['c'] = 3
print(my_ordered_dict)

# ChainMap
dict1 = {'a': 1, 'b': 2}
dict2 = {'c': 3, 'd': 4}
chain = collections.ChainMap(dict1, dict2)
print(chain['a'])
print(chain['c'])

1.36 Working with Itertools

import itertools

# Count
for i in itertools.count(start=10, step=2):
    if i > 20:
        break
    print(i)

# Cycle
count = 0
for item in itertools.cycle(['A', 'B', 'C']):
    if count > 5:
        break
    print(item)
    count += 1

# Repeat
for item in itertools.repeat("Hello", 3):
    print(item)

# Chain
list1 = [1, 2, 3]
list2 = [4, 5, 6]
for item in itertools.chain(list1, list2):
    print(item)

# Combinations
for combo in itertools.combinations([1, 2, 3, 4], 2):
    print(combo)

# Permutations
for perm in itertools.permutations([1, 2, 3], 2):
    print(perm)

# Product
for prod in itertools.product([1, 2], ['a', 'b']):
    print(prod)

# Groupby
data = [('A', 1), ('A', 2), ('B', 3), ('B', 4), ('C', 5)]
for key, group in itertools.groupby(data, key=lambda x: x[0]):
    print(key, list(group))

# islice
data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
for item in itertools.islice(data, 2, 7, 2):  # start, stop, step
    print(item)

# starmap
data = [(1, 2), (3, 4), (5, 6)]
for result in itertools.starmap(lambda x, y: x * y, data):
    print(result)

# takewhile
data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
for item in itertools.takewhile(lambda x: x < 5, data):
    print(item)

# dropwhile
for item in itertools.dropwhile(lambda x: x < 5, data):
    print(item)

1.37 Working with Functools

import functools

# partial
def power(base, exponent):
    return base ** exponent

square = functools.partial(power, exponent=2)
cube = functools.partial(power, exponent=3)

print(square(5))  # Output: 25
print(cube(2))    # Output: 8

# lru_cache
@functools.lru_cache(maxsize=None)
def fibonacci(n):
    if n < 2:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

print(fibonacci(10))

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

# wraps
def my_decorator(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        """Wrapper function docstring"""
        print("Before function execution")
        result = func(*args, **kwargs)
        print("After function execution")
        return result
    return wrapper

@my_decorator
def say_hello(name):
    """This function greets the person passed in as a parameter."""
    print(f"Hello, {name}!")

print(say_hello.__name__) # Output: say_hello
print(say_hello.__doc__) # Output: This function greets the person passed in as a parameter.

1.38 Concurrency and Parallelism

1.38.1 Threads

import threading

def my_task(name):
    print(f"Thread {name}: starting")
    # Perform some work
    print(f"Thread {name}: finishing")

threads = []
for i in range(3):
    t = threading.Thread(target=my_task, args=(i,))
    threads.append(t)
    t.start()

for t in threads:
    t.join()

1.38.2 Processes

import multiprocessing

def my_task(name):
    print(f"Process {name}: starting")
    # Perform some work
    print(f"Process {name}: finishing")

processes = []
for i in range(3):
    p = multiprocessing.Process(target=my_task, args=(i,))
    processes.append(p)
    p.start()

for p in processes:
    p.join()

1.38.3 Asyncio

import asyncio

async def my_coroutine(name):
    print(f"Coroutine {name}: starting")
    await asyncio.sleep(1)
    print(f"Coroutine {name}: finishing")

async def main():
    tasks = [my_coroutine(i) for i in range(3)]
    await asyncio.gather(*tasks)

asyncio.run(main())

1.38.4 ThreadPoolExecutor

from concurrent.futures import ThreadPoolExecutor

def task(n):
    print(f"Processing {n}")
    return n * 2

with ThreadPoolExecutor(max_workers=3) as executor:
    results = executor.map(task, range(5))
    for result in results:
        print(result)

1.38.5 ProcessPoolExecutor

from concurrent.futures import ProcessPoolExecutor

def task(n):
    print(f"Processing {n}")
    return n * 2

with ProcessPoolExecutor(max_workers=3) as executor:
    results = executor.map(task, range(5))
    for result in results:
        print(result)

1.39 Type Hints

def add(x: int, y: int) -> int:
    return x + y

def greet(name: str) -> str:
    return f"Hello, {name}!"

from typing import List, Tuple, Dict, Optional, Union, Any

my_list: List[int] = [1, 2, 3]
my_tuple: Tuple[str, int] = ("Alice", 30)
my_dict: Dict[str, int] = {"a": 1, "b": 2}

def process_item(item: Union[str, int]) -> Optional[str]:
    if isinstance(item, str):
        return item.upper()
    elif isinstance(item, int):
        return str(item * 2)
    else:
        return None

def my_function(x: Any) -> None:
    pass

1.40 Virtual Environments

1.40.1 Creating a Virtual Environment

python -m venv myenv

1.40.2 Activating a Virtual Environment

On Linux/macOS:

source myenv/bin/activate

On Windows:

myenv\Scripts\activate

1.40.3 Deactivating a Virtual Environment

deactivate

1.41 Testing

1.41.1 Using unittest

import unittest

class MyTestCase(unittest.TestCase):
    def test_addition(self):
        self.assertEqual(1 + 1, 2)

    def test_subtraction(self):
        self.assertNotEqual(5 - 2, 4)

    def test_raises_exception(self):
        with self.assertRaises(ValueError):
            raise ValueError

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

1.41.2 Using pytest

Installation:

pip install pytest

Test Example:

# test_my_module.py
def add(x, y):
    return x + y

def test_add():
    assert add(1, 2) == 3
    assert add(-1, 1) == 0

Run tests:

pytest

1.42 Logging

import logging

# Basic configuration
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')

# Create a logger
logger = logging.getLogger(__name__)

# Log messages
logger.debug("This is a debug message")
logger.info("This is an info message")
logger.warning("This is a warning message")
logger.error("This is an error message")
logger.critical("This is a critical message")

# Logging to a file
file_handler = logging.FileHandler('my_log.log')
file_handler.setLevel(logging.WARNING)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)

1.43 Debugging

1.43.1 Using pdb (Python Debugger)

import pdb

def my_function(x, y):
    z = x + y
    pdb.set_trace()  # Set a breakpoint
    return z

my_function(1, 2)

1.43.2 Using print() Statements

def my_function(x, y):
    print(f"x: {x}, y: {y}")
    z = x + y
    print(f"z: {z}")
    return z

1.44 Best Practices

  • Use virtual environments to isolate project dependencies.
  • Use meaningful names for variables and functions.
  • Follow the DRY (Don't Repeat Yourself) principle.
  • Write unit tests to ensure code quality.
  • Use a consistent coding style (PEP 8).
  • Document your code.
  • Use a version control system (e.g., Git).
  • Use appropriate data types for your data.
  • Handle exceptions gracefully.
  • Use logging to track events and errors.
  • Use a security linter (e.g., Bandit) to identify potential vulnerabilities.
  • Follow security best practices.
  • Use a linter (like flake8) and formatter (like black) to ensure consistent code style.
  • Use a code coverage tool (like coverage.py) to measure test coverage.
  • Use a static analysis tool (like mypy) to check for type errors.
  • Use a profiler to identify performance bottlenecks.
  • Use a debugger to step through your code and inspect variables.
  • Use a build tool (like setuptools) to package and distribute your code.
  • Use a continuous integration (CI) system to automatically run tests and build your code.
  • Use a continuous deployment (CD) system to automatically deploy your code to production.
  • Use a monitoring tool to track the performance of your application in production.
  • Use a configuration management tool (like Ansible, Chef, or Puppet) to manage your infrastructure.
  • Use a containerization tool like Docker.
  • Use an orchestration tool like Kubernetes.