20251003-1
This commit is contained in:
75
anb_python_components/extensions/type_extension.py
Normal file
75
anb_python_components/extensions/type_extension.py
Normal file
@@ -0,0 +1,75 @@
|
||||
# anb_python_components/extensions/type_extension.py
|
||||
|
||||
import datetime
|
||||
from typing import Any
|
||||
|
||||
|
||||
# Базовая структура для представления расширенного типа
|
||||
class TypeExtension:
|
||||
"""
|
||||
Класс для расширения типов.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
"""
|
||||
Инициализирует экземпляр класса.
|
||||
"""
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def to_dict(instance: Any) -> dict[str, Any]:
|
||||
"""
|
||||
Преобразует экземпляр объекта в словарь.
|
||||
|
||||
:param instance: Экземпляр класса.
|
||||
:return: Словарь представлений всех полей.
|
||||
"""
|
||||
# Создаём словарь
|
||||
result = {}
|
||||
|
||||
# Перебираем поля экземпляра
|
||||
for key, value in vars(instance).items():
|
||||
# - если значение является экземпляром datetime, преобразуем его в timestamp
|
||||
if isinstance(value, datetime.datetime):
|
||||
result[key] = int(value.timestamp())
|
||||
# - если значение является словарем, вызываем рекурсивно функцию to_dict
|
||||
elif hasattr(value, '__dict__'):
|
||||
result[key] = TypeExtension.to_dict(value)
|
||||
# - иначе просто добавляем значение
|
||||
else:
|
||||
result[key] = value
|
||||
|
||||
# Возвращаем словарь
|
||||
return result
|
||||
|
||||
@staticmethod
|
||||
def from_dict(data: dict, cls=None) -> Any:
|
||||
"""
|
||||
Восстанавливает объект из словаря.
|
||||
|
||||
:param data: Словарь, представляющий поля объекта.
|
||||
:param cls: Класс для восстановления объекта (необязательный параметр, равный None по умолчанию).
|
||||
:return: Восстановленный объект.
|
||||
"""
|
||||
|
||||
# Проверяем, что класс указан и является типом
|
||||
if cls is None or not isinstance(cls, type):
|
||||
# - если класс не указан, бросаем исключение
|
||||
raise TypeError('Класс для восстановления не указан.')
|
||||
|
||||
# Создаём объект класса
|
||||
obj = cls.__new__(cls)
|
||||
|
||||
# Перебираем поля словаря
|
||||
for key, value in data.items():
|
||||
# - если значение является словарем, вызываем рекурсивно функцию from_dict и устанавливаем результат в поле объекта
|
||||
if isinstance(value, int) and hasattr(obj, key) and isinstance(getattr(obj, key), datetime.datetime):
|
||||
setattr(obj, key, datetime.datetime.fromtimestamp(value))
|
||||
elif isinstance(value, dict):
|
||||
nested_cls = getattr(obj, key).__class__
|
||||
setattr(obj, key, TypeExtension.from_dict(value, nested_cls))
|
||||
else:
|
||||
setattr(obj, key, value)
|
||||
|
||||
# Возвращаем восстановленный объект
|
||||
return obj
|
77
help/class_desc/extensions/type_extension.md
Normal file
77
help/class_desc/extensions/type_extension.md
Normal file
@@ -0,0 +1,77 @@
|
||||
# Класс `TypeExtension`
|
||||
|
||||
Класс `TypeExtension` предназначен для работы с объектами Python и их сериализацией / десериализацией. Он поддерживает
|
||||
удобное преобразование объектов в словари и восстановление объектов из словарей, включая вложенные структуры и специфику
|
||||
обработки дат.
|
||||
|
||||
## Основная информация
|
||||
|
||||
- **Имя файла**: anb_python_components\extensions\type_extension.py
|
||||
- **Автор**: Александр Бабаев
|
||||
- **Версия**: 1.0.0
|
||||
- **Дата начала поддержки**: с версии 1.0
|
||||
|
||||
## Атрибуты и методы класса
|
||||
|
||||
### Метод `to_dict`
|
||||
|
||||
Преобразует экземпляр произвольного объекта в словарь, поддерживая рекурсию для вложенных структур и специальное
|
||||
преобразование экземпляров классов `datetime` в целые числа (timestamp).
|
||||
|
||||
**Параметры**:
|
||||
|
||||
- `instance`: Объект, подлежащий преобразованию.
|
||||
|
||||
**Пример использования**:
|
||||
|
||||
```python
|
||||
import datetime
|
||||
|
||||
from anb_python_components.extensions.type_extension import TypeExtension
|
||||
|
||||
|
||||
class SomeClass:
|
||||
def __init__(self, field1, field2):
|
||||
self.field1 = field1
|
||||
self.field2 = field2
|
||||
|
||||
|
||||
obj = SomeClass(field1="value1", field2=datetime.datetime.now())
|
||||
data = TypeExtension.to_dict(obj)
|
||||
print(data)
|
||||
```
|
||||
|
||||
### Метод `from_dict`
|
||||
|
||||
Восстанавливает объект из словарного представления, также поддерживая вложенные объекты и специальную десериализацию
|
||||
экземпляров класса `datetime`.
|
||||
|
||||
**Параметры**:
|
||||
|
||||
- `data`: Словарь, содержащий поля восстанавливаемого объекта.
|
||||
- `cls`: Класс, экземпляр которого необходимо восстановить.
|
||||
|
||||
**Пример использования**:
|
||||
|
||||
```python
|
||||
from anb_python_components.extensions.type_extension import TypeExtension
|
||||
|
||||
|
||||
class SomeClass:
|
||||
def __init__(self, field1, field2):
|
||||
self.field1 = field1
|
||||
self.field2 = field2
|
||||
|
||||
|
||||
data = {'field1': 'Иван', 'field2': 20}
|
||||
|
||||
restored_obj = TypeExtension.from_dict(data, SomeClass)
|
||||
print(restored_obj.field1) # Иван
|
||||
```
|
||||
|
||||
## Заключение
|
||||
|
||||
Класс `TypeExtension` значительно упрощает процесс сериализации и десериализации объектов, что позволяет сохранять
|
||||
состояние объектов в JSON или других форматов и загружать его обратно в приложение.
|
||||
|
||||
[На главную](../../index.md)
|
@@ -20,4 +20,5 @@
|
||||
|
||||
- [класс `StringExtensionConstants`](class_desc/extensions/string_extension_constant.md)
|
||||
- [класс `StringExtension`](class_desc/extensions/string_extension.md)
|
||||
- [класс `BoolExtension`](class_desc/extensions/bool_extension.md)
|
||||
- [класс `BoolExtension`](class_desc/extensions/bool_extension.md)
|
||||
- [класс `TypeExtension`](class_desc/extensions/type_extension.md)
|
36
tests/extensions/type_extension_test.py
Normal file
36
tests/extensions/type_extension_test.py
Normal file
@@ -0,0 +1,36 @@
|
||||
# type_extension_test.py
|
||||
|
||||
import unittest
|
||||
|
||||
from anb_python_components.extensions.type_extension import TypeExtension
|
||||
|
||||
|
||||
class DemoClass:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.age = 20
|
||||
|
||||
|
||||
class TypeExtensionTest(unittest.TestCase):
|
||||
|
||||
def test_to_dict(self):
|
||||
converted = TypeExtension.to_dict(DemoClass('Иван'))
|
||||
self.assertEqual(converted, {'name': 'Иван', 'age': 20})
|
||||
|
||||
def test_from_dict(self):
|
||||
# Представим данные в виде словаря
|
||||
data = {'name': 'Иван', 'age': 20}
|
||||
|
||||
# Преобразуем данные в объект DemoClass
|
||||
converted = TypeExtension.from_dict(data, DemoClass)
|
||||
|
||||
# Проверяем, что полученный объект является экземпляром DemoClass
|
||||
self.assertIsInstance(converted, DemoClass)
|
||||
|
||||
# Проверяем, что объект содержит ожидаемые значения
|
||||
self.assertEqual(converted.name, 'Иван')
|
||||
self.assertEqual(converted.age, 20)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
Reference in New Issue
Block a user