Deadmon
Deadmon

Reputation: 49

Building classes from nested dictionaries

So I am new to all this, please pardon my poor formatting and only loose grasp of jargon.

In short, I have a

coins = requests.get("https://bittrex.com/api/v1.1/public/getcurrencies")

that returns json() nested dictionaries (sorry for terrible phrasing) that look like this:

{
"success" : true,
"message" : "",
"result" : [{
        "Currency" : "BTC",
        "CurrencyLong" : "Bitcoin",
        "MinConfirmation" : 2,
        "TxFee" : 0.00020000,
        "IsActive" : true,
        "CoinType" : "BITCOIN",
        "BaseAddress" : null
    }, {
        "Currency" : "LTC",
        "CurrencyLong" : "Litecoin",
        "MinConfirmation" : 5,
        "TxFee" : 0.00200000,
        "IsActive" : true,
        "CoinType" : "BITCOIN",
        "BaseAddress" : null
    }]
}

In short I would like to access each dictionary within coins["result"] and build my own values with them to generate a class for each coin so that the inherited code gets filled, like:

class coinbuilder(self, currency, currencyLong, minConfirmation...):
    def __init__(self):
        self.currency = currency
        self.currencyLong = currencyLong
    ticker = requests.get("https://bittrex.com/api/v1.1/public/getticker?market=BTC-" + currency)

I understand this code is incorrect, but Im trying to give you an idea of what I am trying to accomplish. Sorry for my terrible phrasing, im new to programming in general and while I have a general grasp of function I am still trying to catch up on jargon.

Upvotes: 2

Views: 1867

Answers (2)

NBlaine
NBlaine

Reputation: 493

Here is a total script for what you are trying to do:

import requests
import json

class CoinBuilder:
  def __init__(self,dict):
    self.currency = dict['Currency']
    self.currencyLong = dict['CurrencyLong']
    self.minConfirmation = dict['MinConfirmation']
    self.txFee = dict['TxFee']
    self.isActive = dict['IsActive']
    self.coinType = dict['CoinType']
    self.baseAddress = dict['BaseAddress']
    self.notice = dict['Notice']


coins_response = requests.get("https://bittrex.com/api/v1.1/public/getcurrencies")

all_coins = json.loads(coins_response.content)

list_of_coin_obs = []

for coin in all_coins["result"]:
  list_of_coin_obs.append(CoinBuilder(coin))

This script is getting the response, then iterating through the dictionaries in result[] and building CoinBuilder objects from that. All of the created objects are also being stored in a list, list_of_coin_obs[].

You can then print the first 10 results you have, for example, like this:

# Print out the first 10 coins
print("First 10 coins:")
for i in range(1,11):
  print(i,") ",list_of_coin_obs[i].currency)

For this example, this would output:

First 10 coins:
1 )  LTC
2 )  DOGE
3 )  VTC
4 )  PPC
5 )  FTC
6 )  RDD
7 )  NXT
8 )  DASH
9 )  POT
10 )  BLK

If you wanted to create a method to look up a specific coin by it's ticker symbol, you could create something like this:

# method to retrieve a specific coin from 'list_of_coin_obs[]'
#   we are passing in a parameter, 'coin_abr' to give to our filter
def get_specific_coin_by_abr(coin_abr):
  return next(filter(lambda x: x.currency == coin_abr, list_of_coin_obs)) 
# call our method, which returns a 'CoinBuilder' type  
specific_coin = get_specific_coin_by_abr('BTC')
# print our results to show it worked
print('CurrencyName: ',specific_coin.currency,'CurrencyLong: ',specific_coin.currencyLong)

This prints:

CurrencyName:  BTC CurrencyLong:  Bitcoin

Note: This is assuming that you already have the list_of_coin_obs[] created and in the same scope as this method.

One suggestion, here the class name CoinBuilder doesn't totally make the most sense. A better name for the class/objects would simply be Coin or NamedCurrency or some other similar name. I think I know what you were going for, but this is probably a better fit for your project.

Best of luck.

Upvotes: 1

user3483203
user3483203

Reputation: 51175

There are several different ways to do this, you could parse the dictionary inside your __init__ function for example.

I tend to handle this by having a separate @classmethod that is responsible for parsing dictionaries to create instances of my class.

Something like this:

class Coinbuilder:
    def __init__(self, cur, curlong):
      self.currency = cur
      self.currency_long = curlong

    @classmethod
    def build_from_dict(coin_b, d):
      attributes = {'Currency', 'CurrencyLong'}
      try:
        class_dct = {a: d[a] for a in attributes}
      except:
        raise ValueError('Input did not contain necessary attributes')
      return coin_b(class_dct['Currency'], class_dct['CurrencyLong'])

This way I am not forced to pass Coinbuilder a dictionary to create a class instance, but I have a simple method I can use to parse a dictionary to create an instance of my class.

For this simple example, I can do the following:

x = Coinbuilder.build_from_dict({'Currency': 'BTC', 'CurrencyLong': 'Bitcoin'})

Or I could use:

y = Coinbuilder('BTC', 'Bitcoin')

And get two equal class instances:

print(x.currency, x.currency_long)
print(y.currency, y.currency_long)

Output:

BTC Bitcoin
BTC Bitcoin

Using your sample input as a guide, once you write your @classmethod to parse your dictionary, you could then simply use:

my_coins = []
for result in coins['result']:
    my_coins.append(Coinbuilder.build_from_dict(result))

Or:

my_coins = [Coinbuilder.build_from_dict(result) for result in coins['result']]

Upvotes: 3

Related Questions