Sure, I can provide a comprehensive tutorial on programming. We'll cover the basics, intermediate topics, advanced concepts, and architectural aspects. Here's a structured outline: 1. Introduction to o Installing o Writing and running scripts o Basic syntax 2. Basic Concepts o Variables and Data Types o Operators o Control Flow (if, for, while) o Functions o Exception Handling 3. Data Structures o Lists o Tuples o Sets o Dictionaries 4. Modules and Packages o Importing modules o Standard library overview o Creating and using packages 5. File Handling o Reading and writing files o Working with CSV and JSON files 6. Object-Oriented Programming (OOP) o Classes and objects o Inheritance o Polymorphism o Encapsulation 7. Advanced Topics o Decorators o Generators o Context Managers 8. Working with Databases o SQLite o SQLAlchemy 9. Web Development o Flask o Django 10. Data Science and Machine Learning o NumPy o Pandas o Matplotlib o Scikit-learn 11. Architectural Patterns o MVC (Model-View-Controller) o Microservices o RESTful APIs 12. Concurrency and Parallelism o o o Threading Multiprocessing Asyncio Let's start with some basics and gradually move to more advanced topics. Feel free to ask for specific details or examples on any topic. 1. Introduction to Installing : 1. Download the installer from the official website. 2. Run the installer and follow the instructions. Make sure to check the box to add to your PATH. Writing and Running Scripts: • • You can write code in any text editor (e.g., VSCode, PyCharm, Sublime Text) and save the file with a .py extension. To run the script, open a terminal or command prompt and type script_name.py. Basic Syntax: # This is a comment print("Hello, World!") # This prints Hello, World! to the console 2. Basic Concepts Variables and Data Types: x = 5 # Integer y = 3.14 # Float name = "Alice" # String is_active = True # Boolean print(x, y, name, is_active) Operators: # Arithmetic Operators a = 10 b = 3 print(a + b) # Addition print(a - b) # Subtraction print(a * b) # Multiplication print(a / b) # Division print(a % b) # Modulus print(a ** b) # Exponentiation print(a // b) # Floor Division # Comparison Operators print(a == b) # Equal to print(a != b) # Not equal to print(a > b) # Greater than print(a < b) # Less than print(a >= b) # Greater than or equal to print(a <= b) # Less than or equal to # Logical Operators print(a > 5 and b < 5) # Logical AND print(a > 5 or b < 5) # Logical OR print(not(a > 5)) # Logical NOT Control Flow: # If-Else age = 18 if age >= 18: print("You are an adult.") else: print("You are a minor.") # For Loop for i in range(5): print(i) # While Loop count = 0 while count < 5: print(count) count += 1 Functions: def greet(name): return f"Hello, {name}!" print(greet("Alice")) Exception Handling: try: x = 1 / 0 except ZeroDivisionError: print("Cannot divide by zero!") finally: print("This will always execute.") 3. Data Structures Lists: fruits = ["apple", "banana", "cherry"] print(fruits[0]) # Accessing elements fruits.append("orange") # Adding elements print(fruits) fruits.remove("banana") # Removing elements print(fruits) Tuples: coordinates = (10, 20) print(coordinates[0]) # Accessing elements # Tuples are immutable, so elements cannot be added or removed Sets: unique_numbers = {1, 2, 3, 3, 4} print(unique_numbers) # Duplicates are removed unique_numbers.add(5) # Adding elements print(unique_numbers) unique_numbers.remove(3) # Removing elements print(unique_numbers) Dictionaries: student = {"name": "Alice", "age": 20, "courses": ["Math", "Science"]} print(student["name"]) # Accessing elements student["age"] = 21 # Modifying elements print(student) student["grade"] = "A" # Adding elements print(student) del student["courses"] # Removing elements print(student) Feel free to ask for more details on any topic or for specific examples! 4o Write more advance part of ChatGPT 4. Modules and Packages Importing Modules: import math print(math.sqrt(16)) # Using the sqrt function from the math module You can also import specific functions from a module: from math import sqrt print(sqrt(16)) # No need to prefix with 'math.' Creating and Using Packages: 1. Create a directory structure for your package: markdown my_package/ __init__.py module1.py module2.py 2. Add code to your modules: module1.py: def greet(name): return f"Hello, {name}!" module2.py: def add(a, b): return a + b 3. Use your package in another script: from my_package import module1, module2 print(module1.greet("Alice")) print(module2.add(5, 3)) 5. File Handling Reading and Writing Files: # Writing to a file with open('example.txt', 'w') as file: file.write("Hello, World!\n") # Reading from a file with open('example.txt', 'r') as file: content = file.read() print(content) Working with CSV and JSON Files: import csv import json # Writing to a CSV file data = [ ["Name", "Age"], ["Alice", 30], ["Bob", 25] ] with open('data.csv', 'w', newline='') as file: writer = csv.writer(file) writer.writerows(data) # Reading from a CSV file with open('data.csv', 'r') as file: reader = csv.reader(file) for row in reader: print(row) # Writing to a JSON file data = {"name": "Alice", "age": 30} with open('data.json', 'w') as file: json.dump(data, file) # Reading from a JSON file with open('data.json', 'r') as file: data = json.load(file) print(data) 6. Object-Oriented Programming (OOP) Classes and Objects: class Person: def __init__(self, name, age): self.name = name self.age = age def greet(self): return f"Hello, my name is {self.name} and I am {self.age} years old." person = Person("Alice", 30) print(person.greet()) Inheritance: class Student(Person): def __init__(self, name, age, student_id): super().__init__(name, age) self.student_id = student_id def greet(self): return f"Hello, my name is {self.name}, I am {self.age} years old, and my student ID is {self.student_id}." student = Student("Bob", 25, "S12345") print(student.greet()) Polymorphism: class Animal: def sound(self): raise NotImplementedError("Subclasses must implement this method") class Dog(Animal): def sound(self): return "Woof" class Cat(Animal): def sound(self): return "Meow" animals = [Dog(), Cat()] for animal in animals: print(animal.sound()) Encapsulation: class BankAccount: def __init__(self, balance): self.__balance = balance def deposit(self, amount): self.__balance += amount def withdraw(self, amount): if amount <= self.__balance: self.__balance -= amount else: print("Insufficient funds") def get_balance(self): return self.__balance account = BankAccount(100) account.deposit(50) account.withdraw(30) print(account.get_balance()) 7. Advanced Topics Decorators: def my_decorator(func): def wrapper(): print("Something is happening before the function is called.") func() print("Something is happening after the function is called.") return wrapper @my_decorator def say_hello(): print("Hello!") say_hello() Generators: def countdown(n): while n > 0: yield n n -= 1 for count in countdown(5): print(count) Context Managers: class FileOpener: def __init__(self, filename, mode): self.filename = filename self.mode = mode def __enter__(self): self.file = open(self.filename, self.mode) return self.file def __exit__(self, exc_type, exc_val, exc_tb): self.file.close() with FileOpener('example.txt', 'w') as file: file.write("Hello, World!") 8. Working with Databases SQLite: import sqlite3 # Connecting to SQLite database conn = sqlite3.connect('example.db') c = conn.cursor() # Creating a table c.execute('''CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)''') # Inserting data c.execute("INSERT INTO users (name, age) VALUES ('Alice', 30)") conn.commit() # Querying data c.execute("SELECT * FROM users") rows = c.fetchall() for row in rows: print(row) # Closing the connection conn.close() SQLAlchemy: from sqlalchemy import create_engine, Column, Integer, String, Sequence from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker engine = create_engine('sqlite:///example.db') Base = declarative_base() class User(Base): __tablename__ = 'users' id = Column(Integer, Sequence('user_id_seq'), primary_key=True) name = Column(String(50)) age = Column(Integer) Base.metadata.create_all(engine) Session = sessionmaker(bind=engine) session = Session() # Adding a new user new_user = User(name='Bob', age=25) session.add(new_user) session.commit() # Querying users users = session.query(User).all() for user in users: print(user.name, user.age) 9. Web Development Flask: from flask import Flask app = Flask(__name__) @app.route('/') def home(): return "Hello, World!" if __name__ == '__main__': app.run(debug=True) Django: 1. 2. 3. 4. Install Django: pip install django Create a new project: django-admin startproject myproject Create a new app: cd myproject && manage.py startapp myapp Define a simple view in myapp/views.py: from django.http import HttpResponse def home(request): return HttpResponse("Hello, World!") 5. Configure URLs in myproject/urls.py: from django.contrib import admin from django.urls import path from myapp import views urlpatterns = [ path('admin/', admin.site.urls), path('', views.home), ] 6. Run the development server: manage.py runserver 10. Data Science and Machine Learning NumPy: import numpy as np a = np.array([1, 2, 3, 4, 5]) print(a) print(a + 2) print(a * 2) Pandas: import pandas as pd data = {'Name': ['Alice', 'Bob', 'Charlie'], 'Age': [25, 30, 35]} df = pd.DataFrame(data) print(df) # Reading from and writing to CSV df.to_csv('data.csv', index=False) df = pd.read_csv('data.csv') print(df) Matplotlib: import matplotlib.pyplot as plt x = [1, 2, 3, 4, 5] y = [2, 3, 5, 7, 11] plt.plot(x, y) plt.xlabel('x') plt.ylabel('y') plt.title('Simple Plot') plt.show() Scikit-learn: from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import accuracy_score # Loading dataset iris = load_iris() X, y = iris.data, iris.target # Splitting data X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) # Training a model clf = RandomForestClassifier() clf.fit(X_train, y_train) # Making predictions y_pred = clf.predict(X_test) # Evaluating the model print(accuracy_score(y_test, y_pred)) 11. Architectural Patterns MVC (Model-View-Controller): In a typical MVC architecture, you separate your application into three main components: • • • Model: Represents the data and the business logic. View: Represents the user interface. Controller: Manages the communication between the model and the view. Example in Django: # models.py (Model) from django.db import models 4o write different ways we can use and interchange datatypes also mix datatypes in and make use of iterables and generators with multiple variations of examples ChatGPT Sure, let's dive into how we can use, interchange, and mix different data types in , as well as how we can make use of iterables and generators with various examples. Interchanging and Mixing Data Types Converting Between Data Types: # Integer to String num = 123 num_str = str(num) print(num_str, type(num_str)) # Output: '123' <class 'str'> # String to Integer str_num = "456" int_num = int(str_num) print(int_num, type(int_num)) # Output: 456 <class 'int'> # Integer to Float int_num = 789 float_num = float(int_num) print(float_num, type(float_num)) # Float to Integer float_num = 10.67 int_num = int(float_num) print(int_num, type(int_num)) # Output: 789.0 <class 'float'> # Output: 10 <class 'int'> Mixing Data Types: # Mixing integers and floats result = 10 + 3.5 print(result, type(result)) # Output: 13.5 <class 'float'> # Mixing strings and numbers (concatenation and repetition) num = 10 num_str = "20" mixed_str = str(num) + num_str print(mixed_str) # Output: '1020' repeat_str = "Hello" * 3 print(repeat_str) # Output: 'HelloHelloHello' # Mixing lists and other data types mixed_list = [1, "apple", 3.14, True] print(mixed_list) # Output: [1, 'apple', 3.14, True] # Using different data types in a dictionary mixed_dict = {"age": 25, "name": "Alice", "is_student": False, "grades": [88, 92, 75]} print(mixed_dict) Using Iterables and Generators Iterables: An iterable is an object that can return its members one at a time. Examples include lists, tuples, dictionaries, sets, and strings. # List iteration fruits = ["apple", "banana", "cherry"] for fruit in fruits: print(fruit) # Tuple iteration coordinates = (10, 20, 30) for coordinate in coordinates: print(coordinate) # Dictionary iteration student = {"name": "Alice", "age": 20, "grade": "A"} for key, value in student.items(): print(f"{key}: {value}") # Set iteration unique_numbers = {1, 2, 3, 4, 5} for number in unique_numbers: print(number) # String iteration for char in "hello": print(char) Generators: Generators allow you to iterate through a sequence of values. They are written like regular functions but use yield instead of return. # Simple generator def simple_generator(): yield 1 yield 2 yield 3 for value in simple_generator(): print(value) # Generator with a loop def countdown(n): while n > 0: yield n n -= 1 for count in countdown(5): print(count) # Generator expression (similar to list comprehension) squares = (x * x for x in range(10)) for square in squares: print(square) Combining Iterables and Generators: # Generator that filters even numbers from a list def even_numbers(nums): for num in nums: if num % 2 == 0: yield num numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] for even in even_numbers(numbers): print(even) # Generator that combines strings from a list def combine_strings(strings): for string in strings: yield string.upper() words = ["hello", "world", ""] for word in combine_strings(words): print(word) Advanced Generator Usage: # Generator with multiple yields def alternating_generator(): yield "odd" yield "even" yield "odd" for value in alternating_generator(): print(value) # Generator that produces an infinite sequence (use with caution) def infinite_sequence(): num = 0 while True: yield num num += 1 # Limit the output to avoid an infinite loop for i, value in enumerate(infinite_sequence()): if i >= 10: break print(value) Chaining Generators: You can also chain generators together to create more complex sequences: def first_generator(): yield from range(3) # This will yield 0, 1, 2 def second_generator(): yield from "abc" # This will yield 'a', 'b', 'c' def combined_generator(): yield from first_generator() yield from second_generator() for value in combined_generator(): print(value) By mixing and matching data types, iterables, and generators, you can create powerful and flexible programs that efficiently handle a variety of tasks and data processing needs. Testing code for different data types and multiple inputs can be achieved using various methods, including built-in assertions, unit tests, and error handling. Here are some examples demonstrating these concepts. Using Built-in Assertions Built-in assertions allow you to quickly check if your code behaves as expected. # Function to test def add(a, b): return a + b # Assertions assert add(2, 3) == 5 assert add(-1, 1) == 0 assert add(2.5, 0.5) == 3.0 assert add("hello", " world") == "hello world" print("All assertions passed!") Using Unit Tests 's unittest module provides a framework for writing and running tests. import unittest # Function to test def multiply(a, b): return a * b class TestMathFunctions(unittest.TestCase): def test_multiply_integers(self): self.assertEqual(multiply(2, 3), 6) def test_multiply_floats(self): self.assertAlmostEqual(multiply(2.5, 0.5), 1.25) def test_multiply_strings(self): self.assertEqual(multiply("hello", 3), "hellohellohello") def test_multiply_mixed(self): with self.assertRaises(TypeError): multiply(2, "three") if __name__ == "__main__": unittest.main() Handling Multiple Inputs You can use parameterized tests to handle multiple inputs. import unittest from parameterized import parameterized # Function to test def divide(a, b): if b == 0: raise ValueError("Cannot divide by zero!") return a / b class TestMathFunctions(unittest.TestCase): @parameterized.expand([ (10, 2, 5), (9, 3, 3), (7.5, 2.5, 3), (5, -1, -5) ]) def test_divide(self, a, b, expected): self.assertAlmostEqual(divide(a, b), expected) def test_divide_by_zero(self): with self.assertRaises(ValueError): divide(10, 0) if __name__ == "__main__": unittest.main() Error Handling Here's an example of handling different errors and testing them. def safe_divide(a, b): try: return a / b except ZeroDivisionError: return "Cannot divide by zero!" except TypeError: return "Both arguments must be numbers!" # Testing the function print(safe_divide(10, 2)) # Expected: 5.0 print(safe_divide(10, 0)) # Expected: "Cannot divide by zero!" print(safe_divide(10, "a")) # Expected: "Both arguments must be numbers!" # Using unittest to test error handling class TestSafeDivide(unittest.TestCase): def test_safe_divide_valid(self): self.assertEqual(safe_divide(10, 2), 5.0) def test_safe_divide_zero_division(self): self.assertEqual(safe_divide(10, 0), "Cannot divide by zero!") def test_safe_divide_type_error(self): self.assertEqual(safe_divide(10, "a"), "Both arguments must be numbers!") if __name__ == "__main__": unittest.main() Using pytest for Simplicity pytest is another testing framework that simplifies writing and running tests. # save this as test_functions.py import pytest def subtract(a, b): return a - b def test_subtract_integers(): assert subtract(5, 3) == 2 def test_subtract_floats(): assert subtract(5.5, 2.5) == 3.0 def test_subtract_strings(): with pytest.raises(TypeError): subtract("hello", "world") # Running the tests: # pytest test_functions.py In the above examples, we demonstrated how to: 1. Use built-in assertions to check if a function behaves as expected. 2. Write unit tests using 's unittest module and handle multiple inputs with the parameterized module. 3. Handle errors in functions and test them using assertions. 4. Use pytest for writing simple tests and handling exceptions. These examples cover testing functions with different data types, handling errors, and running the tests efficiently. let's explore some advanced functionalities of with working examples. This will include decorators, context managers, metaclasses, advanced usage of comprehensions, and more. Decorators Decorators are a powerful tool for modifying the behavior of functions or classes. def my_decorator(func): def wrapper(): print("Something is happening before the function is called.") func() print("Something is happening after the function is called.") return wrapper @my_decorator def say_hello(): print("Hello!") say_hello() Advanced Decorator 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") Context Managers Context managers allow you to allocate and release resources precisely when you want to. You can use the with statement for this. class FileOpener: def __init__(self, filename, mode): self.filename = filename self.mode = mode def __enter__(self): self.file = open(self.filename, self.mode) return self.file def __exit__(self, exc_type, exc_val, exc_tb): self.file.close() with FileOpener('example.txt', 'w') as file: file.write("Hello, World!") Using contextlib for Context Managers: from contextlib import contextmanager @contextmanager def open_file(name, mode): f = open(name, mode) try: yield f finally: f.close() with open_file('example.txt', 'w') as f: f.write('Hello, World!') Metaclasses Metaclasses allow you to control the creation of classes. class Meta(type): def __new__(cls, name, bases, dct): print(f"Creating class {name}") return super().__new__(cls, name, bases, dct) class MyClass(metaclass=Meta): pass # Output: Creating class MyClass Advanced Comprehensions Comprehensions provide a concise way to create lists, dictionaries, and sets. List Comprehensions: squares = [x * x for x in range(10)] print(squares) # Output: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] Dictionary Comprehensions: squares_dict = {x: x * x for x in range(10)} print(squares_dict) # Output: {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81} Set Comprehensions: unique_squares = {x * x for x in range(10)} print(unique_squares) # Output: {0, 1, 64, 4, 36, 9, 16, 49, 81, 25} Nested Comprehensions: matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] flattened = [num for row in matrix for num in row] print(flattened) # Output: [1, 2, 3, 4, 5, 6, 7, 8, 9] Coroutines Coroutines are used for asynchronous programming. import asyncio async def main(): print("Hello") await asyncio.sleep(1) print("World") asyncio.run(main()) More Advanced Coroutine Example: async def fetch_data(): print("Start fetching") await asyncio.sleep(2) print("Done fetching") return {"data": 42} async def print_numbers(): for i in range(10): print(i) await asyncio.sleep(0.5) async def main(): task1 = asyncio.create_task(fetch_data()) task2 = asyncio.create_task(print_numbers()) value = await task1 print(value) await task2 asyncio.run(main()) Advanced Usage of Generators Generators can be used for more complex tasks like managing state and pipeline processing. def generate_numbers(): num = 0 while True: yield num num += 1 gen = generate_numbers() for _ in range(10): print(next(gen)) Pipeline Processing with Generators: def generator1(n): for i in range(n): yield i def generator2(n): for i in generator1(n): yield i * 2 def generator3(n): for i in generator2(n): yield i + 1 for value in generator3(5): print(value) # Output: 1, 3, 5, 7, 9 Type Hints and Annotations Type hints help with code readability and can be checked by static type checkers like mypy. def greeting(name: str) -> str: return 'Hello ' + name print(greeting("Alice")) Using typing Module for More Complex Annotations: from typing import List, Dict def process_data(data: List[Dict[str, int]]) -> List[int]: return [item['value'] for item in data] data = [{'value': 1}, {'value': 2}, {'value': 3}] print(process_data(data)) # Output: [1, 2, 3] Using dataclasses dataclasses provide a decorator and functions for automatically adding special methods to user-defined classes. from dataclasses import dataclass @dataclass class Point: x: int y: int p1 = Point(10, 20) print(p1) # Output: Point(x=10, y=20) Advanced Usage of dataclasses: from dataclasses import dataclass, field from typing import List @dataclass class Person: name: str age: int friends: List[str] = field(default_factory=list) p = Person("Alice", 30) print(p) # Output: Person(name='Alice', age=30, friends=[]) These examples showcase various advanced functionalities in , highlighting the language's versatility and power in handling complex tasks and structures. Here are 100 puzzle questions based on the advanced functionalities of , including decorators, context managers, metaclasses, comprehensions, coroutines, generators, type hints, and dataclasses. Each puzzle is followed by its solution. Decorators 1. Puzzle: Create a decorator that logs the arguments and return value of a function. def log_args_and_return(func): # Your code here pass @log_args_and_return def add(a, b): return a + b add(2, 3) Solution: def log_args_and_return(func): def wrapper(*args, **kwargs): result = func(*args, **kwargs) print(f"Arguments: {args}, {kwargs}") print(f"Return value: {result}") return result return wrapper @log_args_and_return def add(a, b): return a + b add(2, 3) 2. Puzzle: Write a decorator that measures the execution time of a function. import time def measure_time(func): # Your code here pass @measure_time def slow_function(): time.sleep(2) slow_function() Solution: import time def measure_time(func): def wrapper(*args, **kwargs): start = time.time() result = func(*args, **kwargs) end = time.time() print(f"Execution time: {end - start} seconds") return result return wrapper @measure_time def slow_function(): time.sleep(2) slow_function() 3. Puzzle: Create a decorator that caches the results of a function. def cache_results(func): # Your code here pass @cache_results def fib(n): if n in (0, 1): return n return fib(n-1) + fib(n-2) print(fib(10)) Solution: def cache_results(func): cache = {} def wrapper(n): if n not in cache: cache[n] = func(n) return cache[n] return wrapper @cache_results def fib(n): if n in (0, 1): return n return fib(n-1) + fib(n-2) print(fib(10)) 4. Puzzle: Write a decorator that ensures a function is only called once. def only_once(func): # Your code here pass @only_once def initialize(): print("Initialized!") initialize() initialize() Solution: def only_once(func): called = False def wrapper(*args, **kwargs): nonlocal called if not called: called = True return func(*args, **kwargs) return wrapper @only_once def initialize(): print("Initialized!") initialize() initialize() 5. Puzzle: Create a decorator that retries a function call if it raises an exception. import random def retry(num_retries): # Your code here pass @retry(3) def might_fail(): if random.choice([True, False]): raise ValueError("Failed!") return "Success!" print(might_fail()) Solution: import random def retry(num_retries): def decorator(func): def wrapper(*args, **kwargs): for _ in range(num_retries): try: return func(*args, **kwargs) except Exception as e: print(e) return None return wrapper return decorator @retry(3) def might_fail(): if random.choice([True, False]): raise ValueError("Failed!") return "Success!" print(might_fail()) Context Managers 6. Puzzle: Implement a context manager that times the execution of a block of code. import time class Timer: # Your code here pass with Timer(): time.sleep(2) Solution: import time class Timer: def __enter__(self): self.start = time.time() def __exit__(self, exc_type, exc_value, traceback): self.end = time.time() print(f"Elapsed time: {self.end - self.start} seconds") with Timer(): time.sleep(2) 7. Puzzle: Create a context manager that redirects standard output to a file. import sys class RedirectOutput: # Your code here pass with RedirectOutput('output.txt'): print("This should go to the file!") Solution: import sys class RedirectOutput: def __init__(self, filename): self.filename = filename def __enter__(self): self.file = open(self.filename, 'w') self._stdout = sys.stdout sys.stdout = self.file def __exit__(self, exc_type, exc_value, traceback): sys.stdout = self._stdout self.file.close() with RedirectOutput('output.txt'): print("This should go to the file!") 8. Puzzle: Write a context manager using the contextlib module that prints "Entering" and "Exiting" messages. from contextlib import contextmanager @contextmanager def enter_exit(): # Your code here pass with enter_exit(): print("Inside the context!") Solution: from contextlib import contextmanager @contextmanager def enter_exit(): print("Entering") yield print("Exiting") with enter_exit(): print("Inside the context!") 9. Puzzle: Implement a context manager that changes the current working directory. import os class ChangeDir: # Your code here pass with ChangeDir('/tmp'): print(os.getcwd()) Solution: import os class ChangeDir: def __init__(self, path): self.path = path def __enter__(self): self.old_path = os.getcwd() os.chdir(self.path) def __exit__(self, exc_type, exc_value, traceback): os.chdir(self.old_path) with ChangeDir('/tmp'): print(os.getcwd()) 10. Puzzle: Create a context manager that counts the number of exceptions raised within its block. class ExceptionCounter: # Your code here pass with ExceptionCounter() as counter: try: 1 / 0 except: pass try: int('abc') except: pass print(counter.exceptions) Solution: class ExceptionCounter: def __enter__(self): self.exceptions = 0 return self def __exit__(self, exc_type, exc_value, traceback): if exc_type is not None: self.exceptions += 1 return True with ExceptionCounter() as counter: try: 1 / 0 except: pass try: int('abc') except: pass print(counter.exceptions) Metaclasses 11. Puzzle: Create a metaclass that prints the name of each created class. class PrintMeta(type): # Your code here pass class MyClass(metaclass=PrintMeta): pass class AnotherClass(metaclass=PrintMeta): pass Solution: class PrintMeta(type): def __new__(cls, name, bases, dct): print(f"Creating class {name}") return super().__new__(cls, name, bases, dct) class MyClass(metaclass=PrintMeta): pass class AnotherClass(metaclass=PrintMeta): pass 12. Puzzle: Implement a metaclass that adds a class method to every class it creates. class MethodAdderMeta(type): # Your code here pass class MyClass(metaclass=MethodAdderMeta): pass MyClass.class_method() Solution: class MethodAdderMeta(type): def __new__(cls, name, bases, dct): dct['class_method'] = lambda cls: print(f"{cls.__name__} class method called") return super().__new__(cls, name, bases, dct) class MyClass(metaclass=MethodAdderMeta): pass MyClass.class_method() 13. Puzzle: Write a metaclass that prevents the creation of classes with a specific name. class NoSpecificNameMeta(type): # Your code here pass class Forbidden(metaclass=NoSpecificNameMeta): pass Solution: class NoSpecificNameMeta(type): def __new__(cls, name, bases, dct): if name == 'Forbidden': raise ValueError("Class name 'Forbidden' is not allowed") return super().__new__(cls, name, bases, dct) try: class Forbidden(metaclass=NoSpecificNameMeta): pass except ValueError as e: print(e) 14. Puzzle: Implement a metaclass that ensures all class attributes are uppercase. class UppercaseAttributesMeta(type): # Your code here pass class MyClass(metaclass=UppercaseAttributesMeta): my_attr = 42 print(MyClass.MY_ATTR) Solution: class UppercaseAttributesMeta(type): def __new__(cls, name, bases, dct): dct = {key.upper(): value for key, value in dct.items()} return super().__new__(cls, name, bases, dct) class MyClass(metaclass=UppercaseAttributesMeta): my_attr = 42 print(MyClass.MY_ATTR) 15. Puzzle: Write a metaclass that keeps track of the number of classes it has created. class CountingMeta(type): # Your code here pass class MyClass1(metaclass=CountingMeta): pass class MyClass2(metaclass=CountingMeta): pass print(CountingMeta.class_count) Solution: class CountingMeta(type): class_count = 0 def __new__(cls, name, bases, dct): cls.class_count += 1 return super().__new__(cls, name, bases, dct) class MyClass1(metaclass=CountingMeta): pass class MyClass2(metaclass=CountingMeta): pass print(CountingMeta.class_count) Advanced Comprehensions 16. Puzzle: Create a list comprehension that generates a list of the squares of the first 10 positive integers. # Your code here squares = [] print(squares) Solution: squares = [x ** 2 for x in range(1, 11)] print(squares) # Output: [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] 17. Puzzle: Write a dictionary comprehension that maps the first 10 positive integers to their cubes. # Your code here cubes = {} print(cubes) Solution: cubes = {x: x ** 3 for x in range(1, 11)} print(cubes) # Output: {1: 1, 2: 8, 3: 27, 4: 64, 5: 125, 6: 216, 7: 343, 8: 512, 9: 729, 10: 1000} 18. Puzzle: Create a set comprehension that generates a set of all unique characters in a given string. string = "hello world" # Your code here unique_chars = {} print(unique_chars) Solution: string = "hello world" unique_chars = {char for char in string} print(unique_chars) # Output: {'h', 'e', 'l', 'o', ' ', 'w', 'r', 'd'} 19. Puzzle: Write a nested list comprehension that generates a 3x3 matrix filled with zeros. # Your code here matrix = [] print(matrix) Solution: matrix = [[0 for _ in range(3)] for _ in range(3)] print(matrix) # Output: [[0, 0, 0], [0, 0, 0], [0, 0, 0]] 20. Puzzle: Create a list comprehension that generates a list of tuples, each containing a number and its square, for numbers 1 through 5. # Your code here number_squares = [] print(number_squares) Solution: number_squares = [(x, x ** 2) for x in range(1, 6)] print(number_squares) # Output: [(1, 1), (2, 4), (3, 9), (4, 16), (5, 25)] Coroutines 21. Puzzle: Write a coroutine that takes an integer and prints it after a delay. import asyncio async def print_with_delay(number): # Your code here pass asyncio.run(print_with_delay(5)) Solution: import asyncio async def print_with_delay(number): await asyncio.sleep(1) print(number) asyncio.run(print_with_delay(5)) 22. Puzzle: Create a coroutine that runs two coroutines concurrently using asyncio.gather. import asyncio async def task1(): await asyncio.sleep(1) print("Task 1") async def task2(): await asyncio.sleep(1) print("Task 2") async def main(): # Your code here pass asyncio.run(main()) Solution: import asyncio async def task1(): await asyncio.sleep(1) print("Task 1") async def task2(): await asyncio.sleep(1) print("Task 2") async def main(): await asyncio.gather(task1(), task2()) asyncio.run(main()) 23. Puzzle: Write a coroutine that returns the sum of two numbers after a delay. import asyncio async def async_sum(a, b): # Your code here pass result = asyncio.run(async_sum(3, 5)) print(result) Solution: import asyncio async def async_sum(a, b): await asyncio.sleep(1) return a + b result = asyncio.run(async_sum(3, 5)) print(result) # Output: 8 24. Puzzle: Create a coroutine that handles multiple tasks and returns their results. import asyncio async def task(n): await asyncio.sleep(n) return n async def main(): # Your code here pass results = asyncio.run(main()) print(results) Solution: import asyncio async def task(n): await asyncio.sleep(n) return n async def main(): results = await asyncio.gather(task(1), task(2), task(3)) return results results = asyncio.run(main()) print(results) # Output: [1, 2, 3] 25. Puzzle: Write a coroutine that demonstrates the use of asyncio.sleep and returns a message after a delay. import asyncio async def delayed_message(delay, message): # Your code here pass result = asyncio.run(delayed_message(2, "Hello, Async!")) print(result) Solution: import asyncio async def delayed_message(delay, message): await asyncio.sleep(delay) return message result = asyncio.run(delayed_message(2, "Hello, Async!")) print(result) # Output: "Hello, Async!" Generators 26. Puzzle: Create a generator that yields the first 10 positive integers. def first_ten_integers(): # Your code here pass for num in first_ten_integers(): print(num) Solution: def first_ten_integers(): for i in range(1, 11): yield i for num in first_ten_integers(): print(num) 27. Puzzle: Write a generator that yields the squares of numbers up to a given limit. def squares(limit): # Your code here pass for square in squares(5): print(square) Solution: def squares(limit): for i in range(1, limit + 1): yield i ** 2 for square in squares(5): print(square) # Output: 1, 4, 9, 16, 25 28. Puzzle: Create a generator that yields even numbers up to a given limit. def even_numbers(limit): # Your code here pass for even in even_numbers(10): print(even) Solution: def even_numbers(limit): for i in range(2, limit + 1, 2): yield i for even in even_numbers(10): print(even) # Output: 2, 4, 6, 8, 10 29. Puzzle: Write a generator that yields Fibonacci numbers up to a given limit. def fibonacci(limit): # Your code here pass for fib in fibonacci(10): print(fib) Solution: def fibonacci(limit): a, b = 0, 1 while a <= limit: yield a a, b = b, a + b for fib in fibonacci(10): print(fib) # Output: 0, 1, 1, 2, 3, 5, 8 30. Puzzle: Create a generator that yields prime numbers up to a given limit. def primes(limit): # Your code here pass for prime in primes(10): print(prime) Solution: def primes(limit): def is_prime(n): if n < 2: return False for i in range(2, int(n ** 0.5) + 1): if n % i == 0: return False return True for num in range(2, limit + 1): if is_prime(num): yield num for prime in primes(10): print(prime) # Output: 2, 3, 5, 7 Type Hints 31. Puzzle: Write a function with type hints that takes two integers and returns their sum. def add(a: int, b: int) -> int: # Your code here pass print(add(2, 3)) Solution: def add(a: int, b: int) -> int: return a + b print(add(2, 3)) # Output: 5 32. Puzzle: Create a function with type hints that takes a list of strings and returns the longest string. from typing import List def longest_string(strings: List[str]) -> str: # Your code here pass print(longest_string(["apple", "banana", "cherry"])) Solution: from typing import List def longest_string(strings: List[str]) -> str: return max(strings, key=len) print(longest_string(["apple", "banana", "cherry"])) "banana" # Output: 33. Puzzle: Write a function with type hints that takes a dictionary and returns a list of its keys. from typing import Dict, List def dict_keys(d: Dict) -> List: # Your code here pass print(dict_keys({"a": 1, "b": 2, "c": 3})) Solution: from typing import Dict, List def dict_keys(d: Dict) -> List: return list(d.keys()) print(dict_keys({"a": 1, "b": 2, "c": 3})) # Output: ["a", "b", "c"] 34. Puzzle: Create a function with type hints that takes a string and returns a dictionary of character frequencies. from typing import Dict def char_freqs(s: str) -> Dict[str, int]: # Your code here pass print(char_freqs("hello")) Solution: from typing import Dict def char_freqs(s: str) -> Dict[str, int]: freqs = {} for char in s: if char in freqs: freqs[char] += 1 else: freqs[char] = 1 return freqs print(char_freqs("hello")) 1} # Output: {"h": 1, "e": 1, "l": 2, "o": 35. Puzzle: Write a function with type hints that takes a list of integers and returns a list of their squares. from typing import List def squares(nums: List[int]) -> List[int]: # Your code here pass print(squares([1, 2, 3, 4])) Solution: from typing import List def squares(nums: List[int]) -> List[int]: return [x ** 2 for x in nums] print(squares([1, 2, 3, 4])) # Output: [1, 4, 9, 16] Dataclasses 36. Puzzle: Create a simple dataclass for a Person with name and age attributes. from dataclasses import dataclass @dataclass class Person: # Your code here pass person = Person("Alice", 30) print(person) Solution: from dataclasses import dataclass @dataclass class Person: name: str age: int person = Person("Alice", 30) print(person) # Output: Person(name='Alice', age=30) 37. Puzzle: Write a dataclass for a Book with title, author, and pages attributes. from dataclasses import dataclass @dataclass class Book: # Your code here pass book = Book("1984", "George Orwell", 328) print(book) Solution: from dataclasses import dataclass @dataclass class Book: title: str author: str pages: int book = Book("1984", "George Orwell", 328) print(book) # Output: Book(title='1984', author='George Orwell', pages=328) 38. Puzzle: Create a dataclass with a default value for one of its attributes. from dataclasses import dataclass @dataclass class Car: make: str model: str year: int = 2020 car = Car("Toyota", "Corolla") print(car) Solution: from dataclasses import dataclass @dataclass class Car: make: str model: str year: int = 2020 car = Car("Toyota", "Corolla") print(car) # Output: Car(make='Toyota', model='Corolla', year=2020) 39. Puzzle: Write a dataclass for a Rectangle with width, height, and a method to calculate the area. from dataclasses import dataclass @dataclass class Rectangle: width: float height: float def area(self): # Your code here pass rect = Rectangle(5, 10) print(rect.area()) Solution: from dataclasses import dataclass @dataclass class Rectangle: width: float height: float def area(self): return self.width * self.height rect = Rectangle(5, 10) print(rect.area()) # Output: 50.0 40. Puzzle: Create a dataclass with a method to compare the areas of two rectangles. from dataclasses import dataclass @dataclass class Rectangle: width: float height: float def area(self): return self.width * self.height def is_larger_than(self, other): # Your code here pass rect1 = Rectangle(5, 10) rect2 = Rectangle(4, 12) print(rect1.is_larger_than(rect2)) Solution: from dataclasses import dataclass @dataclass class Rectangle: width: float height: float def area(self): return self.width * self.height def is_larger_than(self, other): return self.area() > other.area() rect1 = Rectangle(5, 10) rect2 = Rectangle(4, 12) print(rect1.is_larger_than(rect2)) # Output: True Error Handling 41. Puzzle: Write a function that takes two integers and returns their division, handling the case where the denominator is zero. def safe_divide(a, b): # Your code here pass print(safe_divide(10, 2)) print(safe_divide(10, 0)) Solution: def safe_divide(a, b): try: return a / b except ZeroDivisionError: return "Division by zero is not allowed" print(safe_divide(10, 2)) print(safe_divide(10, 0)) allowed" # Output: 5.0 # Output: "Division by zero is not 42. Puzzle: Create a function that reads a file and returns its content, handling the case where the file does not exist. def read_file(file_path): # Your code here pass print(read_file("existing_file.txt")) print(read_file("non_existing_file.txt")) Solution: def read_file(file_path): try: with open(file_path, 'r') as file: return file.read() except FileNotFoundError: return "File not found" print(read_file("existing_file.txt")) # Output: (content of the file) print(read_file("non_existing_file.txt")) # Output: "File not found" 43. Puzzle: Write a function that takes a string and returns its integer value, handling the case where the string is not a valid integer. def safe_int(s): # Your code here pass print(safe_int("123")) print(safe_int("abc")) Solution: def safe_int(s): try: return int(s) except ValueError: return "Invalid integer" print(safe_int("123")) print(safe_int("abc")) # Output: 123 # Output: "Invalid integer" 44. Puzzle: Create a function that handles multiple exceptions and returns appropriate messages for TypeError and ValueError. def handle_exceptions(value): try: # Your code here pass except TypeError: return "Type error occurred" except ValueError: return "Value error occurred" print(handle_exceptions(10)) print(handle_exceptions("abc")) Solution: def handle_exceptions(value): try: result = 10 / value return int(result) except TypeError: return "Type error occurred" except ValueError: return "Value error occurred" print(handle_exceptions(10)) # Output: 1 print(handle_exceptions("abc")) # Output: "Type error occurred" 45. Puzzle: Write a function that opens a file and writes to it, ensuring that the file is properly closed even if an error occurs. def safe_write(file_path, content): # Your code here pass safe_write("output.txt", "Hello, world!") Solution: def safe_write(file_path, content): try: with open(file_path, 'w') as file: file.write(content) except Exception as e: print(f"An error occurred: {e}") safe_write("output.txt", "Hello, world!") Context Managers 46. Puzzle: Write a context manager that measures the time taken by a block of code. import time class Timer: # Your code here pass with Timer(): time.sleep(1) Solution: import time class Timer: def __enter__(self): self.start_time = time.time() return self def __exit__(self, exc_type, exc_val, exc_tb): elapsed_time = time.time() - self.start_time print(f"Elapsed time: {elapsed_time:.2f} seconds") with Timer(): time.sleep(1) # Output: Elapsed time: 1.00 seconds 47. Puzzle: Create a context manager that temporarily changes the current working directory. import os class TempDir: # Your code here pass with TempDir("/tmp"): print(os.getcwd()) Solution: import os class TempDir: def __init__(self, new_path): self.new_path = new_path def __enter__(self): self.original_path = os.getcwd() os.chdir(self.new_path) def __exit__(self, exc_type, exc_val, exc_tb): os.chdir(self.original_path) with TempDir("/tmp"): print(os.getcwd()) # Output: /tmp 48. Puzzle: Write a context manager that suppresses specific exceptions. class SuppressException: def __init__(self, *exceptions): self.exceptions = exceptions # Your code here pass with SuppressException(ZeroDivisionError): print(1 / 0) Solution: class SuppressException: def __init__(self, *exceptions): self.exceptions = exceptions def __enter__(self): pass def __exit__(self, exc_type, exc_val, exc_tb): return exc_type is not None and issubclass(exc_type, self.exceptions) with SuppressException(ZeroDivisionError): print(1 / 0) # Output: None (exception is suppressed) 49. Puzzle: Create a context manager that logs entering and exiting a block of code. class Logger: # Your code here pass with Logger(): print("Inside the block") Solution: class Logger: def __enter__(self): print("Entering the block") return self def __exit__(self, exc_type, exc_val, exc_tb): print("Exiting the block") with Logger(): print("Inside the block") the block\nExiting the block # Output: Entering the block\nInside 50. Puzzle: Write a context manager that handles resource cleanup by closing a file. class FileManager: def __init__(self, file_name, mode): self.file_name = file_name self.mode = mode # Your code here pass with FileManager("output.txt", "w") as f: f.write("Hello, world!") Solution: class FileManager: def __init__(self, file_name, mode): self.file_name = file_name self.mode = mode def __enter__(self): self.file = open(self.file_name, self.mode) return self.file def __exit__(self, exc_type, exc_val, exc_tb): self.file.close() with FileManager("output.txt", "w") as f: f.write("Hello, world!") # File is automatically closed after the block Installing 1. Puzzle: What command do you use to check the installed version of ? Solution: shell --version 2. Puzzle: How do you create a virtual environment in ? Solution: shell -m venv myenv 3. Puzzle: What is the command to activate a virtual environment on Windows? Solution: shell myenv\Scripts\activate 4. Puzzle: How do you install the pip package manager? Solution: shell -m ensurepip --upgrade 5. Puzzle: What command do you use to install a package using pip? Solution: shell pip install package_name Writing and Running Scripts 6. Puzzle: How do you run a script from the command line? Solution: shell script.py 7. Puzzle: What is the file extension for scripts? Solution: shell .py 8. Puzzle: Write a simple "Hello, World!" script. Solution: print("Hello, World!") 9. Puzzle: How do you write a script that takes command-line arguments? Solution: import sys print(sys.argv) 10. Puzzle: How do you make a script executable on Unix-based systems? Solution: shell chmod +x script.py ./script.py Basic Syntax 11. Puzzle: Write a script that prints the current date and time. Solution: from datetime import datetime print(datetime.now()) 12. Puzzle: Write a function that calculates the factorial of a number. Solution: def factorial(n): if n == 0: return 1 else: return n * factorial(n-1) print(factorial(5)) # Output: 120 13. Puzzle: Write a script that reads input from the user and prints it. Solution: user_input = input("Enter something: ") print(user_input) 14. Puzzle: Write a script that prints numbers from 1 to 10 using a loop. Solution: for i in range(1, 11): print(i) 15. Puzzle: Write a script that prints the even numbers from 1 to 10. Solution: for i in range(1, 11): if i % 2 == 0: print(i) Variables and Data Types 16. Puzzle: How do you declare a variable and assign it a value in ? Solution: x = 10 17. Puzzle: Write a script that swaps the values of two variables. Solution: a = 5 b = 10 a, b = b, a print(a, b) # Output: 10 5 18. Puzzle: Write a script to concatenate two strings. Solution: str1 = "Hello, " str2 = "World!" result = str1 + str2 print(result) # Output: Hello, World! 19. Puzzle: Write a script to convert a string to an integer. Solution: str_num = "123" int_num = int(str_num) print(int_num) # Output: 123 20. Puzzle: Write a script to convert an integer to a string. Solution: int_num = 123 str_num = str(int_num) print(str_num) # Output: "123" Operators 21. Puzzle: Write a script to find the remainder of two numbers using the modulo operator. Solution: a = 10 b = 3 result = a % b print(result) # Output: 1 22. Puzzle: Write a script to check if a number is even or odd using the modulo operator. Solution: num = 10 if num % 2 == 0: print("Even") else: print("Odd") 23. Puzzle: Write a script to calculate the power of a number using the exponentiation operator. Solution: base = 2 exponent = 3 result = base ** exponent print(result) # Output: 8 24. Puzzle: Write a script to check if two numbers are equal using the equality operator. Solution: a = 5 b = 5 print(a == b) # Output: True 25. Puzzle: Write a script to check if one number is greater than another using the greater than operator. Solution: a = 10 b = 5 print(a > b) # Output: True Control Flow 26. Puzzle: Write a script that prints "Hello" if a number is greater than 5. Solution: num = 6 if num > 5: print("Hello") 27. Puzzle: Write a script that prints "Hello" if a number is greater than 5, otherwise prints "Goodbye". Solution: num = 4 if num > 5: print("Hello") else: print("Goodbye") 28. Puzzle: Write a script that prints numbers from 1 to 5 using a while loop. Solution: i = 1 while i <= 5: print(i) i += 1 29. Puzzle: Write a script that prints each character of a string using a for loop. Solution: string = "Hello" for char in string: print(char) 30. Puzzle: Write a script that uses a nested loop to print a 3x3 matrix of numbers. Solution: for i in range(1, 4): for j in range(1, 4): print(i * j, end=" ") print() Functions 31. Puzzle: Write a function that returns the sum of two numbers. Solution: def add(a, b): return a + b print(add(3, 4)) # Output: 7 32. Puzzle: Write a function that returns the maximum of two numbers. Solution: def maximum(a, b): return a if a > b else b print(maximum(3, 4)) # Output: 4 33. Puzzle: Write a function that checks if a number is prime. Solution: def is_prime(n): if n <= 1: return False for i in range(2, n): if n % i == 0: return False return True print(is_prime(5)) # Output: True 34. Puzzle: Write a function that returns the reverse of a string. Solution: def reverse_string(s): return s[::-1] print(reverse_string("Hello")) # Output: "olleH" 35. Puzzle: Write a function that calculates the sum of a list of numbers. Solution: def sum_list(lst): return sum(lst) print(sum_list([1, 2, 3, 4])) # Output: 10 Exception Handling 36. Puzzle: Write a function that handles division by zero. Solution: def divide(a, b): try: return a / b except ZeroDivisionError: return "Cannot divide by zero" print(divide(10, 2)) print(divide(10, 0)) # Output: 5.0 # Output: "Cannot divide by zero" 37. Puzzle: Write a script that reads a file and handles the file not found error. Solution: try: with open("non_existing_file.txt", "r") as file: content = file.read() except FileNotFoundError: print("File not found") 38. Puzzle: Write a script that handles multiple exceptions (ValueError and TypeError). Solution: try: num = int("abc") except (ValueError, TypeError) as e: print(f"Error occurred: {e}") 39. Puzzle: Write a function that uses a finally block to ensure a resource is closed. Solution: def read_file(file_path): file = None try: file = open(file_path, "r") return file.read() except FileNotFoundError: return "File not found" finally: if file: file.close() print(read_file("existing_file.txt")) 40. Puzzle: Write a script that raises a custom exception. Solution: class CustomError(Exception): pass def check_value(value): if value < 0: raise CustomError("Negative value not allowed") try: check_value(-1) except CustomError as e: print(e) # Output: Negative value not allowed Data Structures Lists 41. Puzzle: Write a script to append an item to a list. Solution: my_list = [1, 2, 3] my_list.append(4) print(my_list) # Output: [1, 2, 3, 4] 42. Puzzle: Write a script to remove an item from a list. Solution: my_list = [1, 2, 3] my_list.remove(2) print(my_list) # Output: [1, 3] 43. Puzzle: Write a script to sort a list. Solution: my_list = [3, 1, 2] my_list.sort() print(my_list) # Output: [1, 2, 3] 44. Puzzle: Write a script to reverse a list. Solution: my_list = [1, 2, 3] my_list.reverse() print(my_list) # Output: [3, 2, 1] 45. Puzzle: Write a script to find the index of an item in a list. Solution: my_list = [1, 2, 3] index = my_list.index(2) print(index) # Output: 1 Tuples 46. Puzzle: Write a script to create a tuple. Solution: my_tuple = (1, 2, 3) print(my_tuple) # Output: (1, 2, 3) 47. Puzzle: Write a script to access an item in a tuple. Solution: my_tuple = (1, 2, 3) print(my_tuple[1]) # Output: 2 48. Puzzle: Write a script to concatenate two tuples. Solution: tuple1 = (1, 2) tuple2 = (3, 4) result = tuple1 + tuple2 print(result) # Output: (1, 2, 3, 4) 49. Puzzle: Write a script to find the length of a tuple. Solution: my_tuple = (1, 2, 3) length = len(my_tuple) print(length) # Output: 3 50. Puzzle: Write a script to convert a list to a tuple. Solution: my_list = [1, 2, 3] my_tuple = tuple(my_list) print(my_tuple) # Output: (1, 2, 3) Sets 51. Puzzle: Write a script to create a set. Solution: my_set = {1, 2, 3} print(my_set) # Output: {1, 2, 3} 52. Puzzle: Write a script to add an item to a set. Solution: my_set = {1, 2, 3} my_set.add(4) print(my_set) # Output: {1, 2, 3, 4} 53. Puzzle: Write a script to remove an item from a set. Solution: my_set = {1, 2, 3} my_set.remove(2) print(my_set) # Output: {1, 3} 54. Puzzle: Write a script to find the union of two sets. Solution: set1 = {1, 2} set2 = {3, 4} result = set1.union(set2) print(result) # Output: {1, 2, 3, 4} 55. Puzzle: Write a script to find the intersection of two sets. Solution: set1 = {1, 2, 3} set2 = {2, 3, 4} result = set1.intersection(set2) print(result) # Output: {2, 3} Dictionaries 56. Puzzle: Write a script to create a dictionary. Solution: my_dict = {"a": 1, "b": 2, "c": 3} print(my_dict) # Output: {'a': 1, 'b': 2, 'c': 3} 57. Puzzle: Write a script to access a value in a dictionary. Solution: my_dict = {"a": 1, "b": 2, "c": 3} print(my_dict["b"]) # Output: 2 58. Puzzle: Write a script to add a key-value pair to a dictionary. Solution: my_dict = {"a": 1, "b": 2} my_dict["c"] = 3 print(my_dict) # Output: {'a': 1, 'b': 2, 'c': 3} 59. Puzzle: Write a script to remove a key-value pair from a dictionary. Solution: my_dict = {"a": 1, "b": 2, "c": 3} del my_dict["b"] print(my_dict) # Output: {'a': 1, 'c': 3} 60. Puzzle: Write a script to iterate over the keys and values of a dictionary. Solution: my_dict = {"a": 1, "b": 2, "c": 3} for key, value in my_dict.items(): print(f"{key}: {value}") Modules and Packages Importing Modules 61. Puzzle: Write a script to import the math module and use the sqrt function. Solution: import math print(math.sqrt(16)) # Output: 4.0 62. Puzzle: Write a script to import the random module and use the randint function. Solution: import random print(random.randint(1, 10)) 10 # Output: Random integer between 1 and 63. Puzzle: Write a script to import a specific function from a module. Solution: from math import pi print(pi) # Output: 3.141592653589793 64. Puzzle: Write a script to import a module with an alias. Solution: import numpy as np print(np.array([1, 2, 3])) # Output: [1 2 3] 65. Puzzle: Write a script to create a custom module and import it. Solution: # Create a file named custom_module.py with the following content: def greet(name): return f"Hello, {name}!" # In another script: import custom_module print(custom_module.greet("Alice")) # Output: Hello, Alice! Standard Library Overview 66. Puzzle: Write a script to use the datetime module to print the current date. Solution: from datetime import date print(date.today()) # Output: Current date 67. Puzzle: Write a script to use the os module to list files in the current directory. Solution: import os print(os.listdir(".")) directory # Output: List of files in the current 68. Puzzle: Write a script to use the sys module to print command-line arguments. Solution: import sys print(sys.argv) # Output: List of command-line arguments 69. Puzzle: Write a script to use the time module to sleep for 2 seconds. Solution: import time time.sleep(2) print("Slept for 2 seconds") 70. Puzzle: Write a script to use the json module to parse a JSON string. Solution: import json json_string = '{"name": "Alice", "age": 30}' data = json.loads(json_string) print(data) # Output: {'name': 'Alice', 'age': 30} Creating and Using Packages 71. Puzzle: Write a script to create a package with an __init__.py file. Solution: # Directory structure: # mypackage/ # __init__.py # module1.py # __init__.py from .module1 import greet # module1.py def greet(name): return f"Hello, {name}!" # In another script: import mypackage print(mypackage.greet("Alice")) # Output: Hello, Alice! 72. Puzzle: Write a script to import a module from a subpackage. Solution: # Directory structure: # mypackage/ # __init__.py # subpackage/ # __init__.py # module1.py # subpackage/module1.py def greet(name): return f"Hello, {name}!" # In another script: from mypackage.subpackage import module1 print(module1.greet("Alice")) # Output: Hello, Alice! 73. Puzzle: Write a script to use a relative import within a package. Solution: # Directory structure: # mypackage/ # __init__.py # module1.py # module2.py # module1.py def greet(name): return f"Hello, {name}!" # module2.py from .module1 import greet print(greet("Alice")) # Output: Hello, Alice! 74. Puzzle: Write a script to list all modules in a package. Solution: import pkgutil package = mypackage for module_info in pkgutil.iter_modules(package.__path__): print(module_info.name) 75. Puzzle: Write a script to dynamically import a module by name. Solution: import importlib module_name = "math" math_module = importlib.import_module(module_name) print(math_module.sqrt(16)) # Output: 4.0 File Handling Reading and Writing Files 76. Puzzle: Write a script to write to a file. Solution: with open("output.txt", "w") as file: file.write("Hello, World!") 77. Puzzle: Write a script to read from a file. Solution: with open("output.txt", "r") as file: content = file.read() print(content) # Output: Hello, World! 78. Puzzle: Write a script to read a file line by line. Solution: with open("output.txt", "r") as file: for line in file: print(line.strip()) 79. Puzzle: Write a script to append to a file. Solution: with open("output.txt", "a") as file: file.write("\nAppended text") 80. Puzzle: Write a script to count the number of lines in a file. Solution: with open("output.txt", "r") as file: lines = file.readlines() print(len(lines)) Working with CSV and JSON Files 81. Puzzle: Write a script to read a CSV file. Solution: import csv with open("data.csv", "r") as file: reader = csv.reader(file) for row in reader: print(row) 82. Puzzle: Write a script to write to a CSV file. Solution: import csv with open("output.csv", "w", newline='') as file: writer = csv.writer(file) writer.writerow(["Name", "Age"]) writer.writerow(["Alice", 30]) 83. Puzzle: Write a script to read a JSON file. Solution: import json with open("data.json", "r") as file: data = json.load(file) print(data) 84. Puzzle: Write a script to write to a JSON file. Solution: import json data = {"name": "Alice", "age": 30} with open("output.json", "w") as file: json.dump(data, file) 85. Puzzle: Write a script to convert a CSV file to a JSON file. Solution: import csv import json data = [] with open("data.csv", "r") as file: reader = csv.DictReader(file) for row in reader: data.append(row) with open("output.json", "w") as file: json.dump(data, file) Object-Oriented Programming (OOP) Classes and Objects 86. Puzzle: Write a class with an __init__ method. Solution: class Person: def __init__(self, name, age): self.name = name self.age = age p = Person("Alice", 30) print(p.name) # Output: Alice 87. Puzzle: Write a class with a method. Solution: class Person: def __init__(self, name, age): self.name = name self.age = age def greet(self): return f"Hello, {self.name}!" p = Person("Alice", 30) print(p.greet()) # Output: Hello, Alice! 88. Puzzle: Write a class with a class variable. Solution: class Person: species = "Homo sapiens" def __init__(self, name, age): self.name = name self.age = age p = Person("Alice", 30) print(p.species) # Output: Homo sapiens 89. Puzzle: Write a class with a static method. Solution: class Math: @staticmethod def add(a, b): return a + b print(Math.add(3, 4)) # Output: 7 90. Puzzle: Write a class with a class method. Solution: class Person: count = 0 def __init__(self, name, age): self.name = name self.age = age Person.count += 1 @classmethod def get_count(cls): return cls.count p1 = Person("Alice", 30) p2 = Person("Bob", 25) print(Person.get_count()) # Output: 2 Inheritance 91. Puzzle: Write a class that inherits from another class. Solution: class Animal: def __init__(self, name): self.name = name def speak(self): pass class Dog(Animal): def speak(self): return "Woof!" d = Dog("Rex") print(d.speak()) # Output: Woof! 92. Puzzle: Write a class that overrides a method in the parent class. Solution: class Animal: def speak(self): return "Generic animal sound" class Dog(Animal): def speak(self): return "Woof!" d = Dog() print(d.speak()) # Output: Woof! 93. Puzzle: Write a class that uses super() to call the parent class method. Solution: class Animal: def __init__(self, name): self.name = name class Dog(Animal): def __init__(self, name, breed): super().__init__(name) self.breed = breed d = Dog("Rex", "Labrador") print(d.name) # Output: Rex 94. Puzzle: Write a class with multiple inheritance. Solution: class Flyable: def fly(self): return "Flying" class Swimmable: def swim(self): return "Swimming" class Duck(Flyable, Swimmable): pass d = Duck() print(d.fly()) # Output: Flying print(d.swim()) # Output: Swimming 95. Puzzle: Write a class with a method that returns the class name. Solution: class Animal: def get_class_name(self): return self.__class__.__name__ class Dog(Animal): pass d = Dog() print(d.get_class_name()) # Output: Dog Polymorphism 96. Puzzle: Write a script to demonstrate method overriding. Solution: class Animal: def speak(self): return "Generic animal sound" class Dog(Animal): def speak(self): return "Woof!" class Cat(Animal): def speak(self): return "Meow!" animals = [Dog(), Cat()] for animal in animals: print(animal.speak()) 97. Puzzle: Write a script to demonstrate method overloading (not natively supported in , but can be simulated). Solution: class Math: def add(self, a, b, c=0): return a + b + c m = Math() print(m.add(1, 2)) # Output: 3 print(m.add(1, 2, 3)) # Output: 6 98. Puzzle: Write a script to demonstrate operator overloading. Solution: class Vector: def __init__(self, x, y): self.x = x self.y = y def __add__(self, other): return Vector(self.x + other.x, self.y + other.y) def __repr__(self): return f"Vector({self.x}, {self.y})" v1 = Vector(1, 2) v2 = Vector(3, 4) print(v1 + v2) # Output: Vector(4, 6) 99. Puzzle: Write a script to demonstrate polymorphism with a common interface. Solution: class Animal: def speak(self): pass class Dog(Animal): def speak(self): return "Woof!" class Cat(Animal): def speak(self): return "Meow!" def make_animal_speak(animal): print(animal.speak()) make_animal_speak(Dog()) make_animal_speak(Cat()) 100. # Output: Woof! # Output: Meow! Puzzle: Write a script to demonstrate duck typing. makefile **Solution**: ``` class Bird: def fly(self): return "Flying" class Airplane: def fly(self): return "Flying" def make_it_fly(thing): print(thing.fly()) make_it_fly(Bird()) # Output: Flying make_it_fly(Airplane()) # Output: Flying ``` These puzzles will give you hands-on practice with basics and help you prepare for more advanced topics. Let me know if you need any further explanations or additional puzzles!