Python basic to advance
43 subscribers
131 photos
98 links
Learn Python daily with bite-sized lessons, code examples, output previews, and fun quizzes. Perfect for beginners and enthusiasts!
Download Telegram
Day 25: Unit Testing \- Code & Output
Here's your Telegram post for Day 26: Basic Web Scraping with Beautiful Soup!

---

πŸ“š Day 26: Basic Web Scraping (Beautiful Soup) πŸ•ΈοΈ

Today, we're diving into the exciting world of web scraping! ✨ Learn how to extract information from websites using Python's fantastic Beautiful Soup library. Beautiful Soup makes parsing HTML and XML documents a breeze, allowing you to navigate, search, and modify the parse tree. It's an essential tool for data collection, research, and automating tasks. Let's start with a simple example!

```python
from bs4 import BeautifulSoup

# A simple HTML string for demonstration purposes
html_doc = """
<html>
<head>
<title>Beautiful Soup Demo Page</title>
</head>
<body>
<h1>Welcome to Web Scraping!</h1>
<p class="intro">This is an introduction to Beautiful Soup.</p>
<a href="https://www.python.org">Python Website</a>
<div id="footer">
<p>Copyright 2023</p>
</div>
</body>
</html>
"""

# Create a BeautifulSoup object
soup = BeautifulSoup(html_doc, 'html.parser')

# Extract the page title
title_tag = soup.title
print(f"Page Title: {title_tag.string}")

# Extract the text from the h1 tag
h1_tag = soup.h1
print(f"H1 Content: {h1_tag.string}")

# Find a specific paragraph by class
intro_paragraph = soup.find('p', class_='intro')
print(f"Intro Paragraph: {intro_paragraph.text}")
```

Output example:
```
Page Title: Beautiful Soup Demo Page
H1 Content: Welcome to Web Scraping!
Intro Paragraph: This is an introduction to Beautiful Soup.
```

πŸš€ **Challenge:**
Can you modify the code to extract the `href` attribute from the `<a>` tag and the text content from the `div` with `id="footer"`? Share your solutions!

---
Day 26: Basic Web Scraping \(Beautiful Soup\) \- Code & Output
Here's your Telegram post and quiz:

---

πŸš€ Day 27: Web Wonders! 🌐 Ready to build your first web app? Today, we're diving into the exciting world of Python web frameworks with an introduction to Flask and Django! These powerful tools let you create dynamic websites, APIs, and more. We'll start with a super simple Flask example to get your feet wet and see how easy it is to serve content directly from Python. Let's make some magic happen! ✨

```python
from flask import Flask

# Create a Flask application instance
app = Flask(__name__)

# Define a route for the home page ('/')
@app.route('/')
def hello_world():
"""Returns a simple 'Hello, World!' message when the home page is accessed."""
return "Hello from Flask, Pythonista! 🌍"

# Run the application if this script is executed directly
if __name__ == '__main__':
# debug=True enables the debugger and auto-reloader, great for development
app.run(debug=True)
```

Output example:
(When you run the script, open your browser and navigate to `http://127.0.0.1:5000/`)

*Console output when running `python your_script_name.py`:*
```
* Debug mode: on
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: XXX-XXX-XXX
```

*What you'll see in your browser:*
```
Hello from Flask, Pythonista! 🌍
```

### Small challenge:
✨ Try changing the message returned by `hello_world()` to something else, like `return "Welcome to my first web page with Flask!"`. Can you also add another route, say `/about`, that returns information about yourself or the learning series? Hint: You'll need another `@app.route('/about')` decorator and a new function. Good luck! πŸ’‘

---
Here's your Telegram post and quiz question!

---

πŸŽ‰ Day 28: Diving into Asynchronous Programming with `asyncio`! πŸš€

Today, we're tackling one of Python's most powerful features for efficient, non-blocking I/O operations and concurrency: `asyncio`! πŸ’‘ Ever wondered how to make your programs run multiple tasks seemingly at once without getting stuck? `asyncio` is your answer! We'll explore `async` and `await` to write concurrent code that scales. Let's make our Python faster and more responsive! ⏱️

```python
import asyncio
import time

async def fetch_data(delay, item_name):
"""Simulates an asynchronous I/O operation like fetching data from a network."""
print(f"⏳ {item_name}: Starting data fetch (will take {delay}s)...")
await asyncio.sleep(delay) # Non-blocking pause
print(f"βœ… {item_name}: Data fetched!")
return f"Data for {item_name}"

async def main():
start_time = time.monotonic()
print("πŸš€ Main program started!")

# Run multiple coroutines concurrently
results = await asyncio.gather(
fetch_data(3, "User Profile"),
fetch_data(1, "Product List"),
fetch_data(2, "Order History")
)

end_time = time.monotonic()
print("--- All fetches completed! ---")
for res in results:
print(f"Retrieved: {res}")
print(f"Total time taken: {end_time - start_time:.2f} seconds.")

if __name__ == "__main__":
asyncio.run(main())
```

Output example:
```
πŸš€ Main program started!
⏳ User Profile: Starting data fetch (will take 3s)...
⏳ Product List: Starting data fetch (will take 1s)...
⏳ Order History: Starting data fetch (will take 2s)...
βœ… Product List: Data fetched!
βœ… Order History: Data fetched!
βœ… User Profile: Data fetched!
--- All fetches completed! ---
Retrieved: Data for User Profile
Retrieved: Data for Product List
Retrieved: Data for Order History
Total time taken: 3.00 seconds.
```

Challenge: πŸ€”
Modify the `main` function to use `asyncio.create_task()` for each `fetch_data` call instead of `asyncio.gather()`. How would you then collect their results? Share your solution! ✍️

---
Day 28: Asynchronous Programming \(asyncio\) \- Code & Output
Here's your Telegram post for Day 29!

---

**Python Learning Series - Day 29: Basic Database Interaction (SQLite)**

Day 29 is here! πŸš€ Ever wondered how your Python apps can store and retrieve data persistently? Today, we dive into the world of databases with SQLite! πŸ’Ύ We'll learn the basics of connecting, creating tables, inserting data, and fetching results using Python's built-in `sqlite3` module. Get ready to give your scripts a memory! πŸ§ πŸ’»

```python
import sqlite3

# 1. Connect to an SQLite database (or create one if it doesn't exist)
# Using 'my_app_data.db' will create a file. ':memory:' would create an in-memory DB.
conn = sqlite3.connect('my_app_data.db')
cursor = conn.cursor()

# 2. Create a table
# IF NOT EXISTS prevents error if table already exists
cursor.execute('''
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
age INTEGER
)
''')

# 3. Insert some data
# Using '?' as placeholders for parameters for safety and convenience
cursor.execute("INSERT INTO users (name, age) VALUES (?, ?)", ("Alice", 30))
cursor.execute("INSERT INTO users (name, age) VALUES (?, ?)", ("Bob", 24))
cursor.execute("INSERT INTO users (name, age) VALUES (?, ?)", ("Charlie", 35))

# 4. Commit changes (save them to the database file)
conn.commit()

# 5. Fetch data
print("All users:")
cursor.execute("SELECT * FROM users")
rows = cursor.fetchall() # Fetch all results
for row in rows:
print(row)

# 6. Close the connection
conn.close()
print("nDatabase operations completed. 'my_app_data.db' created/updated.")
```

Output example:
```
All users:
(1, 'Alice', 30)
(2, 'Bob', 24)
(3, 'Charlie', 35)

Database operations completed. 'my_app_data.db' created/updated.
```

πŸ’‘ **Challenge:**
Modify the code to:
1. Insert one more user into the `users` table.
2. Select and print only users whose age is greater than 25.

Share your solution or just let us know you tried! πŸ‘‡

---
Day 29: Basic Database Interaction \(SQLite\) \- Code & Output
Which method of a `cursor` object is used to execute SQL commands in Python's `sqlite3` module?
Anonymous Quiz
0%
execute()
0%
run_sql()
0%
query()
0%
perform()
πŸ₯³ *Congratulations on reaching Day 30 of our Python series!* 🐍

Today is all about gearing up for your Final Project! πŸŽ‰ It's time to consolidate everything you've learned into something truly your own. We'll explore how to brainstorm ideas and review key concepts we've covered. Don't be overwhelmed – think of it as a creative challenge! Let's get those project ideas flowing! πŸ’‘

---

Here's a little helper to get your brainstorming started:

```python
import random

def generate_project_idea():
categories = [
"Web Application",
"Command-Line Tool",
"Data Analysis Script",
"Game",
"Automation Script",
"Desktop Application",
"API Integration"
]
themes = [
"personal finance tracker",
"to-do list manager",
"simple calculator",
"weather app",
"file organizer",
"quiz game",
"recipe book",
"contact manager"
]
technologies = [
"using Flask",
"with SQLite database",
"fetching data from an API",
"using object-oriented programming",
"with a GUI library like Tkinter",
"using Pandas for data manipulation"
]

idea_category = random.choice(categories)
idea_theme = random.choice(themes)
idea_tech = random.choice(technologies)

return f"πŸ’‘ Your project idea: A {idea_category} that is a {idea_theme} {idea_tech}."

if __name__ == "__main__":
print(generate_project_idea())
```

Output example:
```
πŸ’‘ Your project idea: A Web Application that is a recipe book using Flask.
```

---

**Your Challenge:**
1. What's one project idea you've been thinking about building with Python? Share it!
2. Expand the `generate_project_idea` function to include more categories, themes, or even suggest specific Python libraries to use. πŸš€

---
Day 30: Final Project Idea and Review \- Code & Output
πŸš€ Day 31: Ready to peer into Python's soul? πŸ•΅οΈβ€β™‚οΈ Today, we're diving deep into the **Abstract Syntax Tree (AST)**! Forget just writing code; we'll learn how Python *sees* your code at its structural core. Understanding ASTs empowers you to build incredible tools: custom linters, code generators, refactoring scripts, and even new language features! ✨ This is pure metaprogramming magic. Let's crack open the parser! πŸ› οΈ

```python
import ast

# Sample Python code to analyze
code_snippet = """
def greet(name):
print(f"Hello, {name}!")

class MyClass:
def __init__(self, value):
self.value = value

def display(self):
return f"Value: {self.value}"

def calculate_sum(a, b):
# This is a comment
return a + b
"""

class NodeCounter(ast.NodeVisitor):
"""
A simple AST visitor to count different types of nodes
and find function names.
"""
def __init__(self):
self.node_counts = {}
self.function_names = []

def visit(self, node):
# Count all node types
node_type = type(node).__name__
self.node_counts[node_type] = self.node_counts.get(node_type, 0) + 1

# Specific action for FunctionDef
if isinstance(node, ast.FunctionDef):
self.function_names.append(node.name)

self.generic_visit(node) # Continue visiting children

# Parse the code into an AST
tree = ast.parse(code_snippet)

# Create an instance of our visitor and traverse the tree
counter = NodeCounter()
counter.visit(tree)

print("πŸ“Š AST Analysis Results:")
print("-----------------------")
print("Detected Function Names:")
for func_name in counter.function_names:
print(f"- {func_name}")

print("nNode Type Counts:")
for node_type, count in sorted(counter.node_counts.items()):
print(f"- {node_type}: {count}")
```

Output example:
```
πŸ“Š AST Analysis Results:
-----------------------
Detected Function Names:
- greet
- __init__
- display
- calculate_sum

Node Type Counts:
- Arg: 4
- Arguments: 4
- Assign: 1
- Attribute: 1
- BinOp: 1
- Call: 1
- ClassDef: 1
- Constant: 3
- Expr: 1
- FString: 1
- FormattedValue: 1
- FunctionDef: 4
- Load: 8
- Module: 1
- Name: 12
- Return: 2
- Store: 1
- With: 0
```

### Small Challenge 🧠
Can you modify the `NodeCounter` class to also find and list all `ClassDef` names present in the `code_snippet`? Hint: You'll need to look for `ast.ClassDef` nodes!

---
Here's your Telegram post for Day 32 on Metaclasses!

πŸš€ Day 32 of our Python journey takes us deep into the magic! Today, we're unveiling **Metaclasses**! πŸ§™β€β™‚οΈ Forget just creating objects; metaclasses let you **architect how classes themselves are created and behave**. Think frameworks, ORMs, and advanced library design. Ready to bend Python's reality? Let's dive into dynamic class creation beyond `type()`! ✨

```python
class ClassRegistryMeta(type):
# A dictionary to store all classes created by this metaclass
_registry = {}

def __new__(mcs, name, bases, attrs):
print(f"Metaclass: Preparing to create class '{name}'...")

# You can inspect/modify 'attrs' before the class is created
# For example, ensure a method exists or add new attributes
if '__str__' not in attrs:
attrs['__str__'] = lambda self: f"<Registered Object: {self.__class__.__name__}>"

# Create the class using the parent (type) __new__ method
new_class = super().__new__(mcs, name, bases, attrs)

# Add a custom class-level attribute
new_class._registered_name = name

# Register the new class in our metaclass's registry
mcs._registry[name] = new_class
print(f"Metaclass: Class '{name}' created and registered.")
return new_class

# Define classes using our custom metaclass
class MyService(metaclass=ClassRegistryMeta):
def __init__(self, id):
self.id = id

def identify(self):
print(f"{self._registered_name} instance with ID: {self.id}")

class AnotherComponent(metaclass=ClassRegistryMeta):
def __init__(self, data):
self.data = data

def show_data(self):
print(f"{self._registered_name} processing data: {self.data}")

print("n--- Class Definitions Complete ---")

# Accessing the registry via the metaclass itself
print(f"nAll registered classes: {list(ClassRegistryMeta._registry.keys())}")

# Instantiate registered classes using the registry
service_instance = ClassRegistryMeta._registry["MyService"](101)
service_instance.identify()
print(service_instance) # Uses the __str__ added by the metaclass

component_instance = ClassRegistryMeta._registry["AnotherComponent"]({"key": "value"})
component_instance.show_data()
print(component_instance)
```

Output example:
```
Metaclass: Preparing to create class 'MyService'...
Metaclass: Class 'MyService' created and registered.
Metaclass: Preparing to create class 'AnotherComponent'...
Metaclass: Class 'AnotherComponent' created and registered.

--- Class Definitions Complete ---

All registered classes: ['MyService', 'AnotherComponent']
MyService instance with ID: 101
<Registered Object: MyService>
AnotherComponent processing data: {'key': 'value'}
<Registered Object: AnotherComponent>
```

**Challenge:**
Modify the `ClassRegistryMeta` to automatically add a `VERSION = "1.0"` attribute to any class it creates, but only if the class does *not* already define a `VERSION` attribute.

---
🌟 Day 33: Prepare to go *way* beyond surface-level Python! Today, we're deconstructing the interpreter itself. Ever wondered what happens to your code before it runs? We're diving deep into Python's Abstract Syntax Trees (AST) and bytecode. Understanding these internals unlocks immense power for runtime code transformation, static analysis, and even building your own language tools! Get ready to manipulate Python at its very core. πŸ§™β€β™‚οΈβœ¨

```python
import ast
import dis
import types

# 1. Original Python code string
original_code_str = """
def calculate_secret(x):
y = x * 2 + 5 # The constant '5' will be our target for modification
print(f"Original calculation for {x}: {y}")
return y
"""

# 2. Parse the code into an AST
original_ast = ast.parse(original_code_str)

# 3. Define a NodeTransformer to modify the AST
# We will change the constant '5' to '10' within the AST
class ConstantChanger(ast.NodeTransformer):
def visit_Constant(self, node):
if isinstance(node.value, int) and node.value == 5:
# Return a new Constant node with the modified value
return ast.Constant(value=10)
return node # Return the original node for others

# 4. Apply the transformation
modified_ast = ConstantChanger().visit(original_ast)
# Fix line numbers and other metadata in the modified AST
ast.fix_missing_locations(modified_ast)

# 5. Compile and execute both original and modified ASTs
# Compile the original AST and get the function
original_compiled_code = compile(original_ast, '<string>', 'exec')
original_namespace = {}
exec(original_compiled_code, original_namespace)
original_func = original_namespace['calculate_secret']

# Compile the modified AST and get the function
modified_compiled_code = compile(modified_ast, '<string>', 'exec')
modified_namespace = {}
exec(modified_compiled_code, modified_namespace)
modified_func = modified_namespace['calculate_secret']

print("--- Original Function Bytecode ---")
dis.dis(original_func)

print("n--- Modified Function Bytecode ---")
dis.dis(modified_func)

print("n--- Execution Comparison ---")
# Call both functions to observe the runtime transformation
original_func(10)
modified_func(10) # Observe the result of 'x * 2 + 10' instead of 'x * 2 + 5'
```

Output example:
(Note: `ast.dump` is verbose, so we'll highlight the key change and show `dis` and execution comparison.)
The `ast.dump` for the original AST would show `Constant(value=5)`.
The `ast.dump` for the modified AST would show `Constant(value=10)` in the corresponding place.

```
--- Original Function Bytecode ---
3 0 LOAD_FAST 0 (x)
2 LOAD_CONST 1 (2)
4 BINARY_MULTIPLY
6 LOAD_CONST 2 (5) # Original constant value
8 BINARY_ADD
10 STORE_FAST 1 (y)
...
--- Modified Function Bytecode ---
3 0 LOAD_FAST 0 (x)
2 LOAD_CONST 1 (2)
4 BINARY_MULTIPLY
6 LOAD_CONST 2 (10) # Modified constant value!
8 BINARY_ADD
10 STORE_FAST 1 (y)
...
--- Execution Comparison ---
Original calculation for 10: 25
Original calculation for 10: 30
```

Small challenge:
Can you modify the `ConstantChanger` class to not just change a constant, but to transform an arithmetic operator? For instance, change all `ast.Add` operations to `ast.Mult` operations within a specific function! 😈

---
Which Python module is primarily used for programmatically inspecting, traversing, and modifying the Abstract Syntax Tree (AST) of Python code?
Anonymous Quiz
0%
A. `sys`
0%
B. `inspect`
0%
C. `ast`
0%
D. `dis`
πŸ‘» Day 34: Unmasking the "Ghost in the Machine"! Ever wondered how to manage memory efficiently in Python, especially with caches or large data structures? Today, we dive into **Weak References** and **Ephemeral Objects**! πŸ’‘ Discover how to create references to objects without preventing them from being garbage collected, crucial for preventing memory leaks and building robust, memory-sensitive applications. Let's make our Python programs lighter and smarter! 🧠✨

```python
import weakref
import gc # Import gc to manually trigger collection for demonstration

class MyEphemeralObject:
def __init__(self, name):
self.name = name
print(f"✨ Object '{self.name}' created.")

def __del__(self):
print(f"πŸ’€ Object '{self.name}' garbage collected.")

print("--- Scenario 1: Object collected when only weak references exist ---")
# 1. Create a strong reference
strong_ref = MyEphemeralObject("Ephemeral A")

# 2. Create a weak reference to the same object
# This reference will not prevent the object from being garbage collected
weak_ref = weakref.ref(strong_ref)

print(f"Weak reference currently points to: {weak_ref()}")

# 3. Delete the strong reference. Now, only the weak_ref points to the object.
print("nπŸ”₯ Deleting the strong reference 'strong_ref'...")
del strong_ref

# Manually trigger garbage collection (often happens automatically, but good for demo)
gc.collect()

print("Attempting to access object via weak reference after strong reference deletion:")
retrieved_object = weak_ref()

if retrieved_object is None:
print("βœ… Object has been garbage collected!")
else:
print(f"❌ Object still exists: {retrieved_object.name}")

print("n--- Scenario 2: Object NOT collected if a strong reference persists ---")
strong_ref_2 = MyEphemeralObject("Persistent B")
weak_ref_2 = weakref.ref(strong_ref_2)

print(f"Weak reference 2 points to: {weak_ref_2()}")

# We don't delete strong_ref_2 yet.
print("Strong reference 'strong_ref_2' still exists. Object should NOT be collected.")
gc.collect() # Trigger GC, but object is still strongly referenced

retrieved_object_2 = weak_ref_2()
if retrieved_object_2 is None:
print("❌ Object unexpectedly collected!")
else:
print(f"βœ… Object still exists: {retrieved_object_2.name}")

# Now, let's delete the remaining strong reference for Persistent B
print("nπŸ”₯ Deleting the strong reference 'strong_ref_2' for Persistent B...")
del strong_ref_2
gc.collect() # Trigger GC again
```

Output example:
```
--- Scenario 1: Object collected when only weak references exist ---
✨ Object 'Ephemeral A' created.
Weak reference currently points to: <__main__.MyEphemeralObject object at 0x...>

πŸ”₯ Deleting the strong reference 'strong_ref'...
πŸ’€ Object 'Ephemeral A' garbage collected.
Attempting to access object via weak reference after strong reference deletion:
βœ… Object has been garbage collected!

--- Scenario 2: Object NOT collected if a strong reference persists ---
✨ Object 'Persistent B' created.
Weak reference 2 points to: <__main__.MyEphemeralObject object at 0x...>
Strong reference 'strong_ref_2' still exists. Object should NOT be collected.
βœ… Object still exists: Persistent B

πŸ”₯ Deleting the strong reference 'strong_ref_2' for Persistent B...
πŸ’€ Object 'Persistent B' garbage collected.
```

πŸ€” **Your Challenge:** Think of a common Python use case, like a large cache, a GUI framework, or a network connection pool, where using weak references would be absolutely critical to prevent memory leaks or excessive memory consumption. How would you apply them? Share your ideas! πŸ‘‡