Строка фильтра Python

#python-3.x #binance-api-client

Вопрос:

С помощью следующей команды я могу распечатать баланс своих активов из своего аккаунта binance ac.

Команда:

 USDT_BAL = client.futures_account_balance(asset='USDT')
 

Возврат:

 [{'accountAlias': 'sRuXXqTioCfWFz', 'asset': 'BNB', 'balance': '0.00000142', 'withdrawAvailable': '0.00000142', 'updateTime': 1621516315044}, {'accountAlias': 'sRuXXqTioCfWFz', 'asset': 'USDT', 'balance': '0.00000000', 'withdrawAvailable': '0.00000000', 'updateTime': 0}, {'accountAlias': 'sRuXXqTioCfWFz', 'asset': 'BUSD', 'balance': '0.00000000', 'withdrawAvailable': '0.00000000', 'updateTime': 0}]
 

Он возвращает остатки других активов, но мне нужен только баланс актива USDT. Как я мог бы отфильтровать переменную USDT_BAL для нее?

Комментарии:

1. next((i['balance'] for i in USDT_BAL if i['asset'] == 'USDT'), None) должно сработать. В противном случае он вернет баланс 'USDT' актива, если он существует None .

2. Это работает, спасибо.

3. Не могли бы вы объяснить, как это работает?

4. Я добавил это в качестве ответа и рассказал немного подробнее.

Ответ №1:

Расширяю свой комментарий:

У тебя есть list оф dict . list доступ осуществляется с помощью итераций ( for циклов) или индексов. my_list[0] и т.д..

dict доступ может быть также выполнен итерацией, но большим преимуществом является доступ с ключом. my_dict['some_key'] и т.д..

Python упростил способы выполнения общих list и dict часто называемых «постижений».

Таким list образом, понимание чего-то вроде:

 my_list = []
for i in range(10):
    my_list.append(i)
 

Может быть записано как

 my_list = [i for i in range(10)]
 

То, что я вам дал, не обязательно является list пониманием, но следует той же идее. Это называется «генераторным выражением». Разница в том, что он генерирует некоторые выходные данные, когда вы повторяете его, но его выходные данные в целом не представлены в виде какой-либо встроенной коллекции ( list или dict ).

Причина, по которой это имеет смысл в данном контексте, заключается в:

  1. Мне нужно повторить list , чтобы найти dict правильный 'asset' ключ.
  2. Я ожидаю, что это произойдет только в одном случае, поэтому я забочусь только о первом случае.

Итак, чтобы разбить его, у вас есть выражение генератора:

 (i['balance'] for i in USDT_BAL if i['asset'] == 'USDT')
 

Что примерно эквивалентно.

 def my_gen():
    for i in USDT_BAL:
        if i['asset'] == 'USDT':
            yield i['balance']
 

Или, если вы не знакомы с генераторами и хотели бы, чтобы это было list :

 my_list = []
for i in USDT_BAL:
    if i['asset'] == 'USDT':
        my_list.append(i['balance'])
 

Так что теперь вы видите, что у нас есть проблема.
Если у нас есть это как list понимание, то оно в форме а list с одним элементом.

 print(my_list) # ['0.00000000']
 

Мы могли бы получить к нему доступ, my_list[0] но это выглядит уродливо, ИМО, но для каждого это свое.

Так вот в чем заключается next функция. Согласно документам next , вызывает __next__ метод на итераторе (которым является генератор) и в основном продвигает генератор. Так что , если бы наш генератор должен был производить 1 , то 2 тогда 3 вызов next(my_gen) произвел 1 бы, затем вызов его снова произвел 2 бы и так далее.

Поскольку я ожидаю, что это выражение генератора произведет только 1 элемент, я вызываю его только один раз. Присвоение ему значения по умолчанию None означает, что если оно пустое, вместо того, чтобы вызывать ошибку, которую оно вызовет None .

Так:

 next((i['balance'] for i in USDT_BAL if i['asset'] == 'USDT'), None)
 

создает генератор , который повторяет ваш list , создает только 'balance' ключ dict s, 'asset' ключ которого равен 'USDT' , и вызывает next этот генератор по умолчанию None .