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)
|
- [класс `StringExtensionConstants`](class_desc/extensions/string_extension_constant.md)
|
||||||
- [класс `StringExtension`](class_desc/extensions/string_extension.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