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 32: Unlock the ultimate power of Python! 🌟 Ever wondered how frameworks create magical APIs or enforce specific class structures? Today, we dive deep into the #MetaclassMultiverse! 🤯 We'll explore how to forge custom type systems, going far beyond simple `type` calls to control class creation itself. Get ready to redefine what a Python class can be! Let's build some powerful magic together. ✨ #PythonLearning #AdvancedPython #Metaclasses

Metaclasses allow you to intercept class creation and inject behavior, attributes, or methods before the class is even fully defined. This enables powerful patterns for validation, registration, and framework building!

```python
import datetime

# 🚀 Our custom metaclass
class MyMeta(type):
"""
A metaclass that automatically adds a creation timestamp and a 'greet' method
to any class that uses it.
"""
def __new__(cls, name, bases, dct):
# 1. Add a creation timestamp to the class dictionary
dct['_creation_timestamp'] = datetime.datetime.now()

# 2. Add a default 'greet' method if not already defined
if 'greet' not in dct:
def greet_method(self):
return (f"Hello from {self.__class__.__name__}! "
f"Created at {self._creation_timestamp.strftime('%Y-%m-%d %H:%M:%S')}")
dct['greet'] = greet_method

# 3. Call the base type's __new__ to complete class creation
return super().__new__(cls, name, bases, dct)

# 🧙‍♀️ Classes using our custom metaclass
class Character(metaclass=MyMeta):
def __init__(self, name):
self.name = name

class Item(metaclass=MyMeta):
def __init__(self, name):
self.name = name

# This class defines its own greet, which will override the metaclass's
def greet(self):
return f"Hello, I am {self.name}, an item created magically!"

# ✨ Let's see them in action!
hero = Character("Alice")
sword = Item("Excalibur")

print(hero.greet())
print(sword.greet()) # Notice how Item's custom greet takes precedence!
print(f"Character created at: {Character._creation_timestamp}")
```

Output example:
```
Hello from Character! Created at 2023-10-27 10:30:00 # (Timestamp will vary)
Hello, I am Excalibur, an item created magically!
Character created at: 2023-10-27 10:30:00 # (Timestamp will vary)
```

💡 **Your Challenge:** Modify `MyMeta` to automatically add a class-level `_registry` dictionary. For every class that uses `MyMeta`, register the class itself in this `_registry` using its `name` as the key. How would you then access this registry from another part of your code to list all registered classes?

---
👋 Hey Python Learners!

Welcome to **Day 6** of our Python journey! 🚀 Today, we're diving into one of the most fundamental and powerful concepts in programming: **Functions**.

Functions are reusable blocks of code that perform a specific task. They help organize your code, make it more readable, and save you from repeating yourself (DRY - Don't Repeat Yourself principle!). Think of them as mini-programs within your main program. Let's see how to define and use them!

```python
# Define a simple function to greet someone
def greet_user(name):
"""This function takes a name and prints a greeting."""
print(f"Hello, {name}! Welcome to Day 6. 👋")

# Define a function that adds two numbers and returns the result
def add_numbers(num1, num2):
"""This function adds two numbers and returns their sum."""
return num1 + num2

# Call the greet_user function
greet_user("Alice")
greet_user("Bob")

# Call the add_numbers function and store the result
result = add_numbers(10, 5)
print(f"The sum of 10 and 5 is: {result}")

# You can also call it directly in a print statement
print(f"Adding 7 and 3 gives: {add_numbers(7, 3)}")
```

Output example:
```
Hello, Alice! Welcome to Day 6. 👋
Hello, Bob! Welcome to Day 6. 👋
The sum of 10 and 5 is: 15
Adding 7 and 3 gives: 10
```

---

### 🔥 Small Challenge:
Write a Python function called `calculate_area` that takes two arguments: `length` and `width`. The function should return the product of these two numbers (the area of a rectangle). Then, call your function with example values and print the result!

---

💡 Keep practicing, and you'll master functions in no time! See you tomorrow for Day 7! #PythonLearning #Functions #PythonBasics #CodingChallenge
Here's your Telegram post for Day 45 of your Python learning series!

---

Day 45: Ever wondered how Python attributes can do more than just store values? 🤔 Today, we dive into **Advanced Descriptors**! Forget simple `property` – we'll learn to craft "self-aware" attributes that can validate input, trigger side effects, and perform introspection automatically. Unleash the true power behind Python's object model and build more robust, expressive classes! 🚀 #PythonLearning #AdvancedPython #Descriptors

```python
class PositiveNumber:
"""
A descriptor that ensures the attribute it manages is a positive number.
It also prints messages on access and modification.
"""
def __set_name__(self, owner, name):
# __set_name__ allows the descriptor to know the name of the attribute
# it's managing on the owner class.
self.public_name = name
self.private_name = '_' + name # Store the actual value in a private attribute

def __get__(self, obj, obj_type=None):
if obj is None:
return self # Accessing the descriptor itself via the class
print(f"🔍 Accessing attribute '{self.public_name}'...")
# Retrieve the value from the instance's private attribute
return getattr(obj, self.private_name)

def __set__(self, obj, value):
print(f"✏️ Attempting to set attribute '{self.public_name}' to {value}...")
if not isinstance(value, (int, float)):
raise TypeError(f"Error: '{self.public_name}' must be a number, got {type(value).__name__}.")
if value <= 0:
raise ValueError(f"Error: '{self.public_name}' must be a positive number.")
# Store the validated value in the instance's private attribute
setattr(obj, self.private_name, value)
print(f"✅ Successfully set '{self.public_name}' to {value}.")

class Product:
# Assign descriptors to class attributes
price = PositiveNumber()
quantity = PositiveNumber()

def __init__(self, name, price, quantity):
self.name = name
# Setting these attributes triggers the __set__ method of our descriptors
self.price = price
self.quantity = quantity

print("--- Initializing Product ---")
product1 = Product("Laptop", 1200, 5)
print(f"nProduct details: {product1.name}, Price: {product1.price}, Quantity: {product1.quantity}")

print("n--- Testing Invalid Assignments ---")
try:
product1.price = -100 # This should raise a ValueError
except ValueError as e:
print(e)

try:
product1.quantity = "ten" # This should raise a TypeError
except TypeError as e:
print(e)

print("n--- Testing Valid Assignment ---")
product1.price = 1250.75
print(f"nUpdated Price: {product1.price}")
```

Output example:
```
--- Initializing Product ---
✏️ Attempting to set attribute 'price' to 1200...
✅ Successfully set 'price' to 1200.
✏️ Attempting to set attribute 'quantity' to 5...
✅ Successfully set 'quantity' to 5.

🔍 Accessing attribute 'price'...
🔍 Accessing attribute 'quantity'...
Product details: Laptop, Price: 1200, Quantity: 5

--- Testing Invalid Assignments ---
✏️ Attempting to set attribute 'price' to -100...
Error: 'price' must be a positive number.
✏️ Attempting to set attribute 'quantity' to ten...
Error: 'quantity' must be a number, got str.

--- Testing Valid Assignment ---
✏️ Attempting to set attribute 'price' to 1250.75...
✅ Successfully set 'price' to 1250.75.

🔍 Accessing attribute 'price'...
Updated Price: 1250.75
```

Small challenge:
How would you modify the `PositiveNumber` descriptor to also keep a history of all previously set values for that attribute in a list? Share your ideas! 👇

---