Search code examples
python-3.xbinance-api-client

Python filter string


With the following command i can print the balance of my assets from my binance ac.

Command:

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

Return:

[{'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}]

It returns the balances of other assets, but i only need the balance of the USDT asset. How could I filter the USDT_BAL variable for it?


Solution

  • Expanding on my comment:

    You have a list of dict. list access is done by iteration (for loops) or by indexes. my_list[0], etc..

    dict access can, also done by iteration, but a big benefit is keyed access. my_dict['some_key'], etc..

    Python has simplified ways to do common list and dict building commonly called "comprehensions".

    So a list comprehension for something like:

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

    Could be written as

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

    What I gave you isn't necessarily a list comprehension but follows the same idea. It's called a "generator expression". The difference is it generates some output when you iterate over it but it's output as a whole isn't in the form of some built-in collection (list or dict).

    The reason it makes sense in this context is:

    1. I need to iterate over the list to find dict with the correct 'asset' key.
    2. I expect there is only one occurrence of this so I care only about the first occurrence.

    So to break it down you have a generator expression:

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

    Which is roughly equivalent to.

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

    Or if you're not familiar with generators and would like it as a list:

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

    So now you can see we have a problem. If we have it as a list comprehension it's in the form of a list with one element.

    print(my_list) # ['0.00000000']
    

    We could access it with my_list[0] but that looks ugly IMO but to each it's own.

    So that's where the next function comes in. According to the docs next calls the __next__ method on an iterator (which a generator is) and basically advances the generator. So if our generator were to produce 1 then 2 then 3, calling next(my_gen) would produce 1 then calling it again would produce 2 and so on.

    Since I expect this generator expression to only produce 1 item, I only call it once. Giving it a default of None means, if it's empty, rather than raising an error it will produce None.

    So:

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

    creates a generator that iterates over your list, only produces the 'balance' key of dicts who's 'asset' key equals 'USDT' and calls next on that generator with a default of None.