Создание словаря из полей объекта в Python: метод без методов

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Если нужно просто и быстро преобразовать атрибуты объекта в словарь, можно воспользоваться функцией vars(obj) либо атрибутом obj.__dict__. Оба варианта вернут словарь, в котором ключами будут наименования атрибутов объекта, а значениями — сами эти атрибуты.

Вот пример:

Python
Скопировать код
class MyClass:
    def __init__(self, name, value):
        self.name = name
        self.value = value

obj = MyClass('яблоко', 42)
attributes_as_dict = vars(obj)  # или obj.__dict__

В результате получим:

Python
Скопировать код
{'name': 'яблоко', 'value': 42}

Учтите, что данный подход не включает в себя методы и переменные класса, и может не сработать для объектов без атрибута __dict__.

Кинга Идем в IT: пошаговый план для смены профессии

Поживем как-нибудь со словарём: наследование от dict

Объекты могут унаследоваться от dict, благодаря чему можно напрямую работать со словарём, используя его методы.

Python
Скопировать код
class MyClass(dict):
    def __init__(self, some, stuff):
        super().__init__(some, stuff)

obj = MyClass('пирог', 3.14)

Конвертация через итерацию: метод __iter__

Для преобразования объекта в словарь можно ввести метод __iter__ и воспользоваться функцией dict().

Python
Скопировать код
class MyClass:
    ...
    def __iter__(self):
        for attr, value in self.__dict__.items():
            yield (attr, value)

obj = MyClass(...)
converted_dict = dict(obj)

Исключение методов и приватных атрибутов

Для того чтобы преобразовать в словарь только публичные атрибуты объекта, то есть исключить методы и приватные атрибуты, используйте генератор словарей.

Python
Скопировать код
class MyClass:
    ...

obj = MyClass(...)
new_dict = {
    attr: value
    for attr, value in obj.__dict__.items()
    if not callable(value) and not attr.startswith('__')
}

Создание функции object_to_dict

При необходимости частого преобразования объектов в словари обойдётся создать специализированную функцию.

Python
Скопировать код
import inspect

def object_to_dict(obj):
    return {
        attr: val
        for attr, val in inspect.getmembers(obj)
        if not attr.startswith('__') and not inspect.ismethod(val)
    }

fields_as_dict = object_to_dict(obj)

Взаимодействие с декораторами классов

Декоратор @dataclass упрощает преобразование объекта в словарь, предоставляя метод asdict().

Python
Скопировать код
from dataclasses import dataclass

@dataclass
class MyClass:
    name: str
    value: int

obj = MyClass('пицца', 33)

Визуализация

Иллюстрируем процесс преобразования объекта в словарь на примере меню фудтрака:

Markdown
Скопировать код
Открываем ящик с бургером (🍔):
Python
Скопировать код
class FoodTruck:
    burger = '🍔'
    fries = '🍟'
    soda = '🥤'
Markdown
Скопировать код
И вот перед вами меню в понятном словарном виде:
Python
Скопировать код
menu = {field: value for field, value in FoodTruck.__dict__.items() if not field.startswith('__')}
Markdown
Скопировать код
И теперь полный обзор меню перед вами на столе (📋):
| Наименование | Эмодзи |
| ------------ | ------ |
| burger       | 🍔     |
| fries        | 🍟     |
| soda         | 🥤     |

Чем пожалуете себя из нашего меню?

Мудрое использование getattr

В случае использования в классе декораторов @property или вычисляемых атрибутов придётся прибегнуть к помощи функции getattr(), так как vars() и __dict__ здесь сработать не могут.

Python
Скопировать код
class MyClass:
    @property
    def computed(self):
        return 'значение свойства'

obj = MyClass()
dict_version = {
    attribute: getattr(obj, attribute)
    for attribute in dir(obj)
    if not attribute.startswith('__') and not callable(getattr(obj, attribute))
}

Объединение атрибутов класса и экземпляра

Иногда требуется совместить атрибуты класса и экземпляра в общий словарь.

Python
Скопировать код
class MyClass:
    class_var = '1'

    def __init__(self):
        self.instance_var = '2'

combined = {**MyClass.__dict__, **obj.__dict__}
combined = {key: value for key, value in combined.items() if not (key.startswith('__') or callable(value))}

Полезные материалы

  1. Официальная документация Python по словарям.
  2. Полное руководство по словарям Python.
  3. Магические методы в Python.
  4. Документация Python по функции getattr.
  5. Модуль inspect.
  6. Сериализация объектов в Python.