You don't need a class
The point of a class is so that you can make an instance of it which represents some kind of object which can be passed around and can hold internal state.
This isn't the case here. The class coins
has no use except to be a namespace in which two functions are defined (which is subverted by prefixing the function names by the class name).
An indicator for this is that the self
argument of the two functions is never used.
You don't need two functions
The two functions essentially do the same thing, except that one function (coins_arr
returns a sorted list of coin names) is a specialized version of the other function (coins_dict
returns a mapping from coin names to their prices).
There should be only the coins_dict
function, and if absolutely necessary the coins_arr
function could be defined in terms of coins_dict
, but not by repeating a variation of the same code.
Bug
As already noted in another answer, the two parameters limit
and convert
have no effect because they are passed to request.get
in the wrong way:
>>> params = {'limit': 10, 'convert': 'USD'}
>>> print('https://api.coinmarketcap.com/v1/ticker/?%s' % params)
https://api.coinmarketcap.com/v1/ticker/?{'convert': 'USD', 'limit': 10}
I'm surprised that this works, but in any case the request.get
function accepts the parameters as a second argument and does the correct thing:
>>> response = requests.get('https://api.coinmarketcap.com/v1/ticker/', params)
>>> print(response.url)
https://api.coinmarketcap.com/v1/ticker/?convert=USD&limit=10
Improved code
The function name could be improved and a docstring could be added to better describe what the function does.
The limit
and convert
parameters could be made into function arguments so that different parameters can be used without having to change the function definition each time.
The response status code could be checked in order to provide a more helpful error message in case the URL is wrong or the service isn't available, etc., instead of trying to process a meaningless result.
Assembling the return value can be simplified by using a dictionary comprehension.
def fetch_coin_prices(**kwargs):
"""Retrieve cryptocurrency data from CoinMarketCap and return a dictionary
containing coin names with their current prices.
Keyword arguments to this function are mapped to the CoinMarketCap API,
refer to their documentation for their meaning:
https://coinmarketcap.com/api/
"""
response = requests.get(
'https://api.coinmarketcap.com/v1/ticker/',
params=kwargs
)
response.raise_for_status()
coin_data = response.json()
currency = kwargs.get('convert', 'USD')
return {
coin['id']: float(coin['price_{}'.format(currency.lower())])
for coin in coin_data
}
The coins_arr
function can be easily emulated by using the keys()
of the dictionary returned by fetch_coin_prices
:
>>> coins = fetch_coin_prices(limit=5)
>>> print(sorted(coins.keys()))
['bitcoin', 'bitcoin-cash', 'cardano', 'ethereum', 'ripple']
coins_arr
and others in which you wantcoins_dict
? \$\endgroup\$I thought of returning the coins_dict.keys(), but it wont return me it in a sorted order
why not usesorted(dict.keys())
? \$\endgroup\$