Python — vars на примере SQLAlchemy

Admin Python, SQLAlchemy

Разбор python функции vars() из методов для словарей (dict).

Многие классы python показывают содержимое в виде словаря, но при этом не являются словарем, а являются объектом класса, внутри которого может быть представлен формат данных __dict__.

Если попытаться к такому объекту обратиться с методами словаря, то будут выкидываться ошибки.

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

Разберем на примере

Запрос SQLAlchemy:

response = db.session.query(UserSetting).filter_by(user_id=user_id).order_by(asc(UserSetting.name)).all()

С помощью запроса type(response) мы узнаем, что response является объектом list:

<class 'list'>

С помощью print(response) мы увидим следующее содержимое:

[<1:analyse_sp500:120:None:1597834582>, <1:brent_oil:300:None:1597834559>]

Теперь проверим содержимое отдельного элемента <> класса list:

for s in response:
    print(type(s))

Нам показывают, что это класс модели ОРМ SQLAlchemy, содержащий данные из таблицы UserSetting:

<class 'app.models.UserSetting'>

Мы не можем работать с ним методами словаря. Нам нужно преобразовать его в словарь явно. Для этого воспользуемся функцией vars() в Python:

for s in response:
    setting = vars(s)
    print(type(setting))

Так мы превратили содержимое части объекта в словарь:

<class 'dict'>

Вместо vars(s) можно использовать s.__dict__, но первый вариант, как говорится, более «питонист».

Напоследок посмотрим, что находится внутри созданного словаря:

for s in response:
    setting = vars(s)
    print(setting)

Вместо такого безликого формата данных:

<1:analyse_sp500:120:None:1597834582>

Мы увидим:

{'_sa_instance_state': <sqlalchemy.orm.state.InstanceState object at 0x11942c510>,
 'id': 2,
 'name': 'analyse_sp500',
 'percent': None,
 'timer': '120',
 'timestamp': 1597834582,
 'user_id': 1}

Теперь мы можем использовать любые методы словаря и обращаться к данным привычным образом:
setting[‘name’].

Обратить внимание!

Нельзя применить vars() или .__dict__ к классу class ‘list’.

response = db.session.query(UserSetting).filter_by(user_id=user_id).order_by(asc(UserSetting.name)).all()

# Следующее приведет к ошибке!
dicts = vars(response)

Если так сделать будет ошибка:

TypeError: vars() argument must have __dict__ attribute

И все будет верно, ведь класс list не содержит атрибуты словаря. Но в самих листах (списках), если их разбить: for x in response, то внутри будут словари и вот они содержат атрибут словаря.

Однако, мы можем сразу получить данные в словаре. Это в том случае, если мы запрос делаем с конкретизацией колонок, которые хотим забрать PriceMinute.price:

response = [r._asdict() for r in
              db.session.query(PriceMinute.price, PriceMinute.time).filter_by(ticker=ticker).order_by(
                  db.desc(PriceMinute.time)).limit(10).all()]

В данном случае мы можем сразу применить к response методы словаря.

Если вам пригодилась информация, вы можете поблагодарить автора сайта символическим пожертвованием:

Добавить комментарий

Напишите свой комментарий, если вам есть что добавить/поправить/спросить по теме текущей статьи:
"Python — vars на примере SQLAlchemy"