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 46: The Miniature API! ✨

Ever wondered how `@property` works, or how powerful libraries like ORMs manage database fields? Meet Python's Descriptors! These fundamental objects allow you to customize attribute access (get, set, delete) at a low level, giving you incredible control over how your class attributes behave.

With the magic of `__set_name__`, your descriptor instance even knows the name of the attribute it's managing within the owner class. This makes your descriptors self-aware, enabling more generic error messages, logging, or complex setup without needing manual configuration. Dive in to craft elegant, robust, and reusable attribute behavior! 🐍

```python
class ValidatedString:
"""
A descriptor that ensures an attribute is a non-empty string and
can enforce min/max length, using __set_name__ for self-awareness.
"""
def __init__(self, min_len=1, max_len=float('inf')):
self.min_len = min_len
self.max_len = max_len

def __set_name__(self, owner, name):
# 'owner' is the class the descriptor is attached to (e.g., User)
# 'name' is the attribute name it's assigned to (e.g., 'username')
self.public_name = name
self.private_name = f'_{name}' # Store the actual value in a private attribute

def __get__(self, obj, objtype=None):
if obj is None:
return self # Accessing the descriptor itself via the class
return getattr(obj, self.private_name, '') # Return the private value

def __set__(self, obj, value):
if not isinstance(value, str):
raise TypeError(f"'{self.public_name}' must be a string.")
if not (self.min_len <= len(value) <= self.max_len):
if self.max_len == float('inf'):
raise ValueError(
f"'{self.public_name}' must be at least {self.min_len} characters long."
)
else:
raise ValueError(
f"'{self.public_name}' must be between {self.min_len} and "
f"{self.max_len} characters long."
)
setattr(obj, self.private_name, value) # Set the private value

class User:
username = ValidatedString(min_len=3, max_len=20)
email = ValidatedString(min_len=5) # No max_len constraint here

def __init__(self, username, email):
self.username = username
self.email = email

# --- Demonstration ---
try:
user1 = User("Alice", "alice@example.com")
print(f"User 1: {user1.username}, {user1.email}")

user1.username = "BobTheBuilder" # Valid update
print(f"User 1 (updated username): {user1.username}")

# Attempt to set an invalid username (too short)
user1.username = "Bo"
except ValueError as e:
print(f"Error caught: {e}")

try:
# Attempt to create a user with invalid email (too short)
user2 = User("Charlie", "c@ex")
except ValueError as e:
print(f"Error caught: {e}")

try:
# Attempt to create a user with non-string username
user3 = User(123, "test@example.com")
except TypeError as e:
print(f"Error caught: {e}")
```

Output example:
```
User 1: Alice, alice@example.com
User 1 (updated username): BobTheBuilder
Error caught: 'username' must be at least 3 characters long.
Error caught: 'email' must be at least 5 characters long.
Error caught: 'username' must be a string.
```

💡 Your Challenge: Can you create a `PositiveNumber` descriptor that ensures an attribute (like `age` or `quantity`) is always an integer greater than zero? Or perhaps a `ReadOnly` descriptor that allows setting a value only once during initialization? Go ahead, build your own miniature API! 🛠️

---
🚀 Day 48: Level up your Python! ✨ Ever wondered how frameworks enforce patterns or create domain-specific languages? Today, we're diving into the heart of Python's type system with **Metaclasses and `__init_subclass__`**! 🤯

We'll explore how to programmatically control class creation itself, ensuring your classes adhere to specific rules *before* they even exist. `__init_subclass__` offers a powerful hook for class-level validation and modification, a perfect stepping stone into the world of metaprogramming. Get ready to master the art of class factories!

```python
class PluginBase:
"""
Base class for plugins, enforcing that all subclasses define
a 'PLUGIN_NAME' attribute and an 'execute' method.
This logic runs when the subclass itself is defined, not when an instance is created.
"""
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs) # Always call super()

# Enforce PLUGIN_NAME attribute
if not hasattr(cls, 'PLUGIN_NAME') or not isinstance(cls.PLUGIN_NAME, str):
raise TypeError(f"Subclass '{cls.__name__}' must define a string 'PLUGIN_NAME'.")

# Enforce 'execute' method
if not callable(getattr(cls, 'execute', None)):
raise TypeError(f"Subclass '{cls.__name__}' must define an 'execute' method.")

print(f"✅ Plugin '{cls.PLUGIN_NAME}' validated and ready!")

# --- Valid Plugin Definition ---
class MyAwesomePlugin(PluginBase):
PLUGIN_NAME = "AwesomePlugin"

def execute(self, data):
print(f"Executing {self.PLUGIN_NAME} with data: {data}")
return data.upper()

# --- Instantiation of a valid plugin ---
print("n--- Creating MyAwesomePlugin instance ---")
plugin_instance = MyAwesomePlugin()
result = plugin_instance.execute("hello metaprogramming!")
print(f"Result: {result}")

# --- Invalid Plugin Definition (will raise an error) ---
print("n--- Attempting to define BadPlugin (will fail) ---")
try:
class BadPlugin(PluginBase):
# Missing PLUGIN_NAME and execute method
pass
except TypeError as e:
print(f"Error caught as expected: {e}")

# --- Another Invalid Plugin (missing execute) ---
print("n--- Attempting to define AnotherBadPlugin (will fail) ---")
try:
class AnotherBadPlugin(PluginBase):
PLUGIN_NAME = "MissingExecute"
# Missing execute method
pass
except TypeError as e:
print(f"Error caught as expected: {e}")
```

Output example:
```
✅ Plugin 'AwesomePlugin' validated and ready!

--- Creating MyAwesomePlugin instance ---
Executing AwesomePlugin with data: hello metaprogramming!
Result: HELLO METAPROGRAMMING!

--- Attempting to define BadPlugin (will fail) ---
Error caught as expected: Subclass 'BadPlugin' must define a string 'PLUGIN_NAME'.

--- Attempting to define AnotherBadPlugin (will fail) ---
Error caught as expected: Subclass 'AnotherBadPlugin' must define an 'execute' method.
```

🧠 **Small Challenge:** Modify `PluginBase` to automatically register all valid subclasses in a global dictionary (e.g., `_REGISTERED_PLUGINS = {}`) upon their definition via `__init_subclass__`. This is a very common pattern for building extensible architectures!

---
Which special method is automatically called when a class is created as a subclass of another class, allowing for class-level validation or registration *before* the subclass is fully defined?
Anonymous Quiz
0%
__new__
33%
__init__
67%
__init_subclass__
0%
__call__
🚀 **Python Learning Series - Day 49: Disassembling the Zen!** 🤯

Ever wondered what truly happens beneath the elegant surface of your Python code? Today, we're not just peeking; we're diving deep into the CPython interpreter's brain! 🧠 Welcome to the world of runtime bytecode manipulation and dynamic code generation. This isn't just about writing Python; it's about understanding how Python itself *runs* and how you can bend its internal mechanics to your will for advanced optimization, instrumentation, or even building truly adaptive systems. Get ready to deconstruct and reconstruct the very essence of your functions! ✨

```python
import dis
import types

def original_add(a, b):
"""A simple function to add two numbers."""
return a + b

def original_subtract(a, b):
"""A simple function to subtract two numbers."""
return a - b

print("--- Original add function bytecode ---")
dis.dis(original_add)

print("n--- Original subtract function bytecode ---")
dis.dis(original_subtract)

print(f"nBefore manipulation: original_add(5, 3) = {original_add(5, 3)}")

# Deep dive: Runtime bytecode manipulation!
# We can dynamically change a function's underlying code object.
# Here, we're making 'original_add' execute 'original_subtract's logic!
original_add.__code__ = original_subtract.__code__

print(f"nAfter manipulation: original_add(5, 3) = {original_add(5, 3)}")

# Let's verify by disassembling 'original_add' again
print("n--- original_add function bytecode after manipulation ---")
dis.dis(original_add)
```

**Output example:**
```
--- Original add function bytecode ---
9 0 LOAD_FAST 0 (a)
2 LOAD_FAST 1 (b)
4 BINARY_ADD
6 RETURN_VALUE

--- Original subtract function bytecode ---
13 0 LOAD_FAST 0 (a)
2 LOAD_FAST 1 (b)
4 BINARY_SUBTRACT
6 RETURN_VALUE

Before manipulation: original_add(5, 3) = 8

After manipulation: original_add(5, 3) = 2

--- original_add function bytecode after manipulation ---
13 0 LOAD_FAST 0 (a)
2 LOAD_FAST 1 (b)
4 BINARY_SUBTRACT
6 RETURN_VALUE
```

### 🎯 **Small Challenge:**

Can you define a third function, `original_multiply(a, b)`, and then dynamically change `original_add`'s behavior *again* so that it performs multiplication when called? Show the output before and after your modification! Good luck, bytecode wizard! 🧙‍♂️

---
🚀 Day 50: Dive into the heart of Python's object model! Today, we're not just writing code, we're *designing* its very behavior. Welcome to **The Architect's Loom: Weaving Runtime Behavior with Advanced Metaclasses and Descriptors**. 🤯 Discover how to craft custom attribute access, enforce validation, and build dynamic systems that adapt at runtime. Descriptors and metaclasses are your powerful tools to unlock Python's deepest metaprogramming capabilities. Get ready to reshape how your objects behave! 👇

```python
class PositiveNumber:
"""
A descriptor that ensures an attribute is a positive number and logs access.
"""
def __set_name__(self, owner, name):
# Store the name of the attribute it manages (e.g., '_price')
self._private_name = '_' + name

def __get__(self, obj, objtype=None):
if obj is None: # Accessing the descriptor directly from the class
return self
print(f"🔍 Accessing attribute '{self._private_name}'...")
return obj.__dict__.get(self._private_name, None)

def __set__(self, obj, value):
if not isinstance(value, (int, float)) or value <= 0:
raise ValueError(f"🛑 Attribute '{self._private_name}' must be a positive number.")
print(f"✏️ Setting attribute '{self._private_name}' to {value}...")
obj.__dict__[self._private_name] = value

class Product:
# Assigning a descriptor instance to a class attribute
price = PositiveNumber()
quantity = PositiveNumber()

def __init__(self, name, price, quantity):
self.name = name
self.price = price # This assignment uses the 'price' descriptor
self.quantity = quantity # This assignment uses the 'quantity' descriptor

# --- Usage Example ---
print("--- Initializing Product ---")
p = Product("SuperWidget", 1200, 5)
print(f"nProduct: {p.name}")
print(f"Price: {p.price}") # Accessing uses the descriptor's __get__
print(f"Quantity: {p.quantity}") # Accessing uses the descriptor's __get__

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

try:
p.quantity = "five" # This will raise a ValueError
except ValueError as e:
print(e)

print("n--- Testing Valid Assignment ---")
p.price = 1500 # This assignment uses the descriptor's __set__
print(f"New price: {p.price}")
```

Output example:
```
--- Initializing Product ---
✏️ Setting attribute '_price' to 1200...
✏️ Setting attribute '_quantity' to 5...

Product: SuperWidget
🔍 Accessing attribute '_price'...
Price: 1200
🔍 Accessing attribute '_quantity'...
Quantity: 5

--- Testing Invalid Assignments ---
🛑 Attribute '_price' must be a positive number.
🛑 Attribute '_quantity' must be a positive number.

--- Testing Valid Assignment ---
✏️ Setting attribute '_price' to 1500...
🔍 Accessing attribute '_price'...
New price: 1500
```

💡 **Your Challenge:** How would you modify the `PositiveNumber` descriptor to allow a default value of `1` if no value has been explicitly set for the attribute yet, without breaking the positive number constraint? Think about when `__get__` is called and what information it receives! Share your ideas! 👇

---
Which special method is invoked when an attribute managed by a descriptor is *accessed* (read) on an instance?
Anonymous Quiz
0%
__get__(self, obj, objtype=None)
0%
__set__(self, obj, value)
0%
__delete__(self, obj)
0%
__set_name__(self, owner, name)
Hey Pythonistas! 👋 Welcome to Day 52 of our deep dive! 🚀 Today, we're twisting Python itself with a mind-bending topic: **"The Malleable Codebase: Dynamic Class Generation and Runtime Code Alteration for Self-Modifying Python."**

Ever wondered if your code could change its own rules on the fly? We'll explore how to not just write classes, but *generate* them and *alter* their behavior *after* they've been defined, even affecting existing instances! Get ready for some serious metaprogramming magic that pushes Python's dynamic nature to its limits. ✨

```python
import types

# Day 52: The Malleable Codebase 🧩
# 1. Dynamic Class Generation: Creating a class 'TaskProcessor' on the fly.
# The `type()` function allows us to define classes programmatically.
TaskProcessor = type(
"TaskProcessor", # The name of our new class
(), # A tuple of base classes (empty means no inheritance)
{ # A dictionary of attributes and methods for the class
"__init__": lambda self, task_id: setattr(self, 'task_id', task_id),
"process": lambda self: f"Processing task {self.task_id} with basic logic."
}
)

# Create an instance of our dynamically generated class
task1 = TaskProcessor("alpha-123")
print(f"Task 1 initial: {task1.process()}")

# 2. Runtime Code Alteration / Self-Modification:
# Now, imagine we need to add advanced logic or change behavior dynamically.
# We can redefine methods on the class *after* it's been created.

def advanced_process_logic(self):
"""A new function that represents our 'advanced' processing logic."""
print(f"🔍 Task {self.task_id}: Activating advanced processing protocols!")
return f"Processing task {self.task_id} with *advanced* logic now!"

# Assign the new function to the 'process' method of the TaskProcessor class.
# This immediately modifies the class's behavior and affects all existing
# instances (that haven't overridden 'process' individually) and new ones!
TaskProcessor.process = advanced_process_logic

# Observe the change in the *existing* instance!
print(f"Task 1 modified: {task1.process()}")

# New instances also get this new behavior by default
task2 = TaskProcessor("beta-456")
print(f"Task 2 new: {task2.process()}")
```

Output example:
```
Task 1 initial: Processing task alpha-123 with basic logic.
🔍 Task alpha-123: Activating advanced processing protocols!
Task 1 modified: Processing task alpha-123 with *advanced* logic now!
🔍 Task beta-456: Activating advanced processing protocols!
Task 2 new: Processing task beta-456 with *advanced* logic now!
```

---
**Small challenge:**
How would you dynamically *remove* the `process` method from `TaskProcessor` at runtime, or replace it with a placeholder that raises `NotImplementedError`? 🤔 Share your thoughts!

---
Which of the following built-in functions is primarily used in Python for dynamically creating new class types at runtime?
Anonymous Quiz
0%
`exec()`
0%
`eval()`
0%
`type()`
0%
`compile()`
Which of the following magic methods must a descriptor implement to control attribute assignment (setting a value)?
Anonymous Quiz
0%
__set__(self, instance, value)
0%
__get__(self, instance, owner)
0%
__delete__(self, instance)
0%
__init__(self, ...)
Here's your Telegram post for Day 55, focusing on "Zero-Copy Python"!

---

**Day 55: Zero-Copy Python: Leveraging `mmap` and `memoryview` for High-Throughput Data Pipelines 🚀**

Ever needed to process massive datasets without unnecessary memory overhead? Today, we're diving into `mmap` and `memoryview` – your power tools for high-throughput data pipelines! Learn how to directly access and manipulate data buffers, bypassing costly data copies. This technique is crucial for performance-critical applications, from network programming to large-scale data processing. Get ready to supercharge your Python code with true zero-copy operations! ⚡💾

```python
import mmap
import os
import tempfile

# 1. Create a temporary file and mmap it
FILE_SIZE = 64 # Small size for demo purposes
with tempfile.NamedTemporaryFile(delete=False) as tmp_file:
filepath = tmp_file.name
tmp_file.write(b'x00' * FILE_SIZE) # Pre-allocate space
tmp_file.flush() # Ensure data is written to disk

try:
with open(filepath, 'rb+') as f:
# Map the entire file into memory
with mmap.mmap(f.fileno(), 0) as mm:
print(f"Initial mmap content (first 10 bytes): {mm[:10]}")

# 2. Create a memoryview for zero-copy access
mv = memoryview(mm)

# Write data directly through the memoryview buffer
data_to_write = b"Hello, Zero-Copy World!"
mv[:len(data_to_write)] = data_to_write
print(f"Content after writing (through mv): {mv[:len(data_to_write)]}")

# 3. Create a sliced memoryview – still no copy!
# Let's extract "Zero-Copy" part
zero_copy_slice = mv[7:17]
print(f"Sliced view content ('Zero-Copy'): {zero_copy_slice.tobytes().decode()}")

# 4. Prove zero-copy: Modify the original mmap,
# and observe the change directly in the slice
mm[7:8] = b'X' # Change 'Z' to 'X' in "Zero-Copy"
print(f"Slice reflects mmap change ('Xero-Copy'): {zero_copy_slice.tobytes().decode()}")

# Read directly from mmap again to confirm its current state
print(f"Original mmap (start) confirms change: {mm[:len(data_to_write)].decode()}")

finally:
os.remove(filepath) # Clean up the temporary file
```

**Output example:**
```
Initial mmap content (first 10 bytes): b'x00x00x00x00x00x00x00x00x00x00'
Content after writing (through mv): b'Hello, Zero-Copy World!'
Sliced view content ('Zero-Copy'): Zero-Copy
Slice reflects mmap change ('Xero-Copy'): Xero-Copy
Original mmap (start) confirms change: Hello, Xero-Copy World!
```

**Small challenge:**
Explore how `memoryview` can wrap `bytes`, `bytearray`, `array.array`, and `numpy` arrays. How does this `buffer protocol` enhance interoperability for zero-copy operations across different data types? Share your findings! 👇

---
Here's your Telegram post for Day 56 of the Python learning series!

---

✨ **Day 56: Unveiling the Metaclass!** 🤯

Ready to peek behind Python's curtain? Today, we're diving into Metaclasses – the classes of classes! While `type` is Python's built-in metaclass, you can define your own to gain ultimate control over how classes are created. Think of it as intercepting the `class` statement itself! This allows for incredible power, from enforcing design patterns to injecting behavior at the class level. Let's unlock this advanced concept and design custom object creation beyond typical class definitions! 🛠️

```python
class EnforceMethodsMetaclass(type):
"""
A metaclass that enforces all methods in a class to start with 'do_'.
It also adds a custom class attribute.
"""
def __new__(mcs, name, bases, dct):
# 1. Enforce a custom class attribute
dct['_created_by_metaclass'] = True
dct['_metaclass_version'] = '1.0'

# 2. Iterate through the dict to check method names
for attr_name, attr_value in dct.items():
# Check if it's a callable (method) and not a special method
if callable(attr_value) and not attr_name.startswith('__'):
if not attr_name.startswith('do_'):
raise TypeError(
f"Method '{attr_name}' in class '{name}' "
"must start with 'do_'"
)

# Call the base type's __new__ to actually create the class object
cls = super().__new__(mcs, name, bases, dct)
return cls

# Using our custom metaclass
class MyDataProcessor(metaclass=EnforceMethodsMetaclass):
def __init__(self, data):
self.data = data

def do_process_data(self):
"""Processes the internal data."""
return [item * 2 for item in self.data]

def do_display_results(self, processed_data):
"""Displays the processed data."""
return f"Processed results: {processed_data}"

# This class would raise a TypeError because 'calculate' doesn't start with 'do_'
# class BadProcessor(metaclass=EnforceMethodsMetaclass):
# def calculate(self, x):
# return x * x

# Instantiate and use the class
processor = MyDataProcessor([1, 2, 3])
processed = processor.do_process_data()
print(processor.do_display_results(processed))

# Access attributes added by the metaclass
print(f"Created by metaclass: {MyDataProcessor._created_by_metaclass}")
print(f"Metaclass version: {MyDataProcessor._metaclass_version}")

```

Output example:
```
Processed results: [2, 4, 6]
Created by metaclass: True
Metaclass version: 1.0
```

**Challenge:** Modify `EnforceMethodsMetaclass` to automatically add a `__repr__` method to any class it creates. This `__repr__` method should return a string like `<ClassName object with data: [...]>`. 🚀

---
Here's your Telegram post for Day 58!

---

🌟 **Day 58: Metaclasses as Runtime Policy Engines: Enforcing Constraints Before `__init__`** 🚀

Ready to dive deep into Python's object model? Today, we're unlocking the true power of **metaclasses**! Forget simple class decorators; metaclasses allow you to become a "factory for classes" themselves. We'll explore how they can act as powerful runtime policy engines, enforcing architectural rules, validating class structures, or injecting behavior *before a class is even fully defined*, let alone instantiated. This is where truly robust and self-validating systems are born! Let's build classes that *cannot* be badly formed. ✨

```python
# 1. Define our Metaclass
class EnforceMethodsMeta(type):
"""
A metaclass that enforces the presence of specific methods in classes
that use it.
"""
REQUIRED_METHODS = ['process_data', 'validate_input']

def __new__(mcs, name, bases, namespace):
# We need to check the 'namespace' (the class's dict) for methods.
# This runs *before* the class object is fully created.
for method_name in mcs.REQUIRED_METHODS:
if method_name not in namespace or not callable(namespace[method_name]):
raise TypeError(
f"Class '{name}' must implement the '{method_name}' method."
)

# If all checks pass, proceed to create the class
return super().__new__(mcs, name, bases, namespace)

# 2. A class that correctly adheres to the policy
class ValidProcessor(metaclass=EnforceMethodsMeta):
def process_data(self, data):
print(f"Processing: {data}")

def validate_input(self, data):
print(f"Validating: {data}")
return True

# 3. A class that violates the policy
try:
class InvalidProcessor(metaclass=EnforceMethodsMeta):
def process_data(self, data):
print(f"Processing only: {data}")
# Missing 'validate_input' method!

except TypeError as e:
print(f"nCaught expected error: {e}")

# 4. Using the valid class
print("n--- Instantiating ValidProcessor ---")
vp = ValidProcessor()
vp.process_data("sample input")
vp.validate_input("sample input")
```

**Output example:**
```
Caught expected error: Class 'InvalidProcessor' must implement the 'validate_input' method.

--- Instantiating ValidProcessor ---
Processing: sample input
Validating: sample input
```

### Small Challenge:
Modify `EnforceMethodsMeta` to not only check for method existence but also to ensure that a method named `process_data` accepts exactly one positional argument (excluding `self`). Hint: You might need to inspect the method's signature within the metaclass's `__new__`. Good luck! 🧐

---
Here's your Telegram post for Day 60!

---

**Day 60: Event Loop Alchemy: Building Custom `asyncio` Schedulers and Executors**

Day 60: Ready for the ultimate Python deep dive? 🤯 Today, we're not just creating objects; we're *sculpting* the very blueprint of classes themselves! ✨ Unlock the mystical powers of **Custom Metaclasses** and the elegant **`__init_subclass__`** method. Learn how to dynamically alter class creation, inject methods, enforce patterns, and gain unparalleled control over your Python runtime. This is where Python truly becomes a malleable language in your hands. Let's transcend `type()`! 🚀

```python
class RegistryMeta(type):
"""
A custom metaclass that automatically registers classes and injects a 'report' method.
It acts as a factory for classes, not instances.
"""
_registered_classes = {} # A dictionary to keep track of all classes using this metaclass

def __new__(cls, name, bases, class_dict):
# 1. Create the new class object using the default type.__new__
new_class = super().__new__(cls, name, bases, class_dict)

# 2. Modify the new class: inject a custom method
def _report_method(instance):
"""A method injected into every class created by RegistryMeta."""
return f"Instance of {new_class.__name__} created by RegistryMeta."
setattr(new_class, 'report', _report_method) # Dynamically add 'report' method

# 3. Register the new class in our metaclass's internal registry
RegistryMeta._registered_classes[name] = new_class

# 4. Return the (potentially modified) new class
return new_class

# --- Using our Custom Metaclass ---

class MyService(metaclass=RegistryMeta):
"""A class using RegistryMeta, automatically gaining a 'report' method."""
def __init__(self, service_id):
self.service_id = service_id

def get_id(self):
return self.service_id

class DataProcessor(metaclass=RegistryMeta):
"""Another class benefiting from RegistryMeta."""
def process(self, data):
return f"Processing '{data}' with DataProcessor."

# --- Demonstrate the effects ---

service_instance = MyService("SVC001")
print(f"Service ID: {service_instance.get_id()}")
print(f"Service Report: {service_instance.report()}") # Method injected by metaclass

data_instance = DataProcessor()
print(f"Data Processor Report: {data_instance.report()}") # Method injected by metaclass
print(f"Processed Data: {data_instance.process('raw_log_entry')}")

print("n--- All Classes Registered by RegistryMeta ---")
for class_name, cls_obj in RegistryMeta._registered_classes.items():
print(f"- {class_name}: {cls_obj}")

```

Output example:
Service ID: SVC001
Service Report: Instance of MyService created by RegistryMeta.
Data Processor Report: Instance of DataProcessor created by RegistryMeta.
Processed Data: Processing 'raw_log_entry' with DataProcessor.

--- All Classes Registered by RegistryMeta ---
- MyService: <class '__main__.MyService'>
- DataProcessor: <class '__main__.DataProcessor'>

💡 **Your Advanced Challenge:**
Can you achieve a similar runtime class modification using `__init_subclass__`? 🕵️‍♀️ Create a base class `Auditable` that, when subclassed, automatically ensures the subclass has a `_version` attribute set to `1.0` if not already present. If a subclass *doesn't* define it, `__init_subclass__` should add it! (Hint: `__init_subclass__` is a class method called on the base class for new subclasses.)

---
🚀 Day 61: Ever wondered how `property` works, or how ORMs validate fields behind the scenes? 🤔 Welcome to the captivating world of Python Descriptors! These powerful objects allow you to customize attribute access (get, set, delete) on a class level. This means you can add validation, caching, lazy loading, or even complex ORM-like field definitions with elegant, reusable logic. Uncover the secret lives of these unsung heroes and start crafting smarter, more robust attributes! 🐍✨

```python
class NonNegativeNumber:
"""
A descriptor that enforces an attribute to be a non-negative integer or float.
"""
def __set_name__(self, owner, name):
# Store the actual attribute name (e.g., 'price')
# We'll store the value in a 'private' attribute (e.g., '_price')
self._private_name = f'_{name}'
self._public_name = name

def __get__(self, obj, objtype=None):
# If accessed via the class (e.g., Product.price), return the descriptor itself.
# Otherwise, return the instance's value.
if obj is None:
return self
return getattr(obj, self._private_name)

def __set__(self, obj, value):
# Validation logic for setting the attribute
if not isinstance(value, (int, float)):
raise TypeError(
f"Attribute '{self._public_name}' must be an int or float, "
f"got {type(value).__name__}."
)
if value < 0:
raise ValueError(
f"Attribute '{self._public_name}' must be non-negative, "
f"got {value}."
)
# Store the validated value in the 'private' attribute
setattr(obj, self._private_name, value)

class Product:
price = NonNegativeNumber()
quantity = NonNegativeNumber()

def __init__(self, name: str, price: float, quantity: int):
self.name = name
# These assignments trigger the descriptor's __set__ method
self.price = price
self.quantity = quantity

print("--- Valid Assignments ---")
p1 = Product("Gaming Laptop", 1299.99, 10)
print(f"Product: {p1.name}, Price: ${p1.price}, Quantity: {p1.quantity}")

p2 = Product("USB Cable", 5.50, 100)
p2.price = 6.75 # This will also use the descriptor's __set__
print(f"Product: {p2.name}, Price: ${p2.price}, Quantity: {p2.quantity}")

print("n--- Invalid Type Assignment ---")
try:
p1.price = "expensive" # String is not allowed
except (TypeError, ValueError) as e:
print(f"Error: {e}")

print("n--- Invalid Value Assignment ---")
try:
p1.quantity = -5 # Negative value is not allowed
except (TypeError, ValueError) as e:
print(f"Error: {e}")

print("n--- Accessing Descriptor from Class ---")
print(f"Product.price is of type: {type(Product.price)}")
```

Output example:
```
--- Valid Assignments ---
Product: Gaming Laptop, Price: $1299.99, Quantity: 10
Product: USB Cable, Price: $6.75, Quantity: 100

--- Invalid Type Assignment ---
Error: Attribute 'price' must be an int or float, got str.

--- Invalid Value Assignment ---
Error: Attribute 'quantity' must be non-negative, got -5.

--- Accessing Descriptor from Class ---
Product.price is of type: <class '__main__.NonNegativeNumber'>
```

### Small Challenge 🧠
Your Challenge: Create a new descriptor called `StringLengthValidator` that takes `min_length` and `max_length` arguments in its `__init__` method. It should ensure that any string assigned to its attribute falls within the specified length range (inclusive). Test it on a `username` attribute for a `User` class! Good luck! 🚀

---