Попытка применить дескриптор к атрибутам вложенных классов с использованием метаклассаPython

Программы на Python
Anonymous
Попытка применить дескриптор к атрибутам вложенных классов с использованием метакласса

Сообщение Anonymous »

Попытка применить дескриптор ко всем атрибутам, включая атрибуты вложенных классов. Вот моя попытка:

Код: Выделить всё

from typing import Any
import os
import json
import logging

logger = logging.getLogger("config_manager")

class Descriptor:
def __init__(self, name, config_file):
self.name = name
self.config_file = config_file

def _read_config(self):
if os.path.exists(self.config_file):
with open(self.config_file, "r") as file:
return json.load(file)
return {}

def _write_config(self, config):
with open(self.config_file, "w") as file:
json.dump(config, file, indent=4)

def __get__(self, instance, owner):
config = self._read_config()
keys = self.name.split(".")
value = config
for key in keys:
value = value.get(key, {})
print(f"Accessing {self.name} from {owner}: {value}")
return value

def __set__(self, instance, value):
config = self._read_config()
keys = self.name.split(".")
d = config
for key in keys[:-1]:
if key not in d:
d[key] = {}
d = d[key]
d[keys[-1]] = value
self._write_config(config)
print(f"Setting {self.name} to {value}")

class DescriptorMeta(type):
def __new__(cls, name: str, bases: tuple[type, ...], dct: dict[str, Any]):
config_file = dct.get("config_file", "config.json")
for attr_name, attr_value in dct.items():
if isinstance(attr_value, type):
cls._process_group(attr_name, attr_value, config_file)
elif not attr_name.startswith("__") and not callable(attr_value):
dct[attr_name] = Descriptor(attr_name, config_file)
return super().__new__(cls, name, bases, dct)

@staticmethod
def _process_group(base_name: str, group_class: type, config_file: str):
for attr_name, attr_value in group_class.__dict__.items():
if not attr_name.startswith("__") and not callable(attr_value):
if isinstance(attr_value, type):
DescriptorMeta._process_group(attr_name, attr_value, config_file)
else:
setattr(group_class, attr_name, Descriptor(f"{base_name}.{attr_name}", config_file))

class Config(metaclass=DescriptorMeta):
config_file = "config.json"
theme_path = "default_theme"

class Colors:
base_color = "white"

class Geometry:
class Size:
height = 200
width = 800

# Accessing and setting top-level attributes
print(Config.theme_path)  # Accessing theme_path from 
config = Config()
print(config.theme_path)  # Accessing theme_path from 
Config.theme_path = "new_theme"  # Setting theme_path to new_theme
print(Config.theme_path)  # Accessing theme_path from 

# Accessing and setting nested attributes
print(Config.Colors.base_color)  # Accessing Colors.base_color from 
config.Colors.base_color = "blue"  # Setting Colors.base_color to blue
print(config.Colors.base_color)  # Accessing Colors.base_color from 

print(Config.Geometry.Size.height)  # Accessing Geometry.Size.height from 
config.Geometry.Size.height = 1024  # Setting Geometry.Size.height to 1024
print(config.Geometry.Size.height)  # Accessing Geometry.Size.height from 

Метод __set__ дескриптора не вызывается, когда атрибуту присваивается новое значение (

Код: Выделить всё

Config.theme_path = "new_theme"). Похоже, что значение присваивается атрибуту напрямую, поскольку метод __get__
также не вызывается после присвоения.
Извините, если я плохо объясняю. Я делаю все возможное. Спасибо!

Подробнее здесь: https://stackoverflow.com/questions/786 ... -metaclass

Вернуться в «Python»