Создание классов из вложенных словарей - PullRequest
0 голосов
/ 26 апреля 2018

Так что я новичок во всем этом, прошу прощения за мое плохое форматирование и только слабое понимание жаргона.

Короче, у меня есть

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

, который возвращает вложенные словари json () (извините за ужасные фразы), которые выглядят так:

{
"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
    }]
}

Короче говоря, я хотел бы получить доступ к каждому словарю в пределах coins["result"] и создать из них свои собственные значения, чтобы сгенерировать класс для каждой монеты, чтобы унаследованный код был заполнен, например:

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)

Я понимаю, что этот код неверен, но я пытаюсь дать вам представление о том, чего я пытаюсь достичь. Извините за мою ужасную фразу, я новичок в программировании в целом, и, хотя у меня есть общее представление о функции, я все еще пытаюсь догнать жаргон.

Ответы [ 2 ]

0 голосов
/ 26 апреля 2018

Вот общий сценарий того, что вы пытаетесь сделать:

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))

Этот скрипт получает ответ, затем перебирает словари в result[] и строит CoinBuilder объекты из этого. Все созданные объекты также хранятся в списке, list_of_coin_obs[].

Затем вы можете распечатать первые 10 результатов, которые у вас есть, например, так:

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

Для этого примера это вывело бы:

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

Если вы хотите создать метод для поиска конкретной монеты по ее символу тикера, вы можете создать что-то вроде этого:

# 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)

Это печатает:

CurrencyName:  BTC CurrencyLong:  Bitcoin

Примечание: Это предполагает, что вы уже создали list_of_coin_obs[] и в той же области действия, что и этот метод.

Одно предложение, здесь название класса CoinBuilder не полностью имеет смысл. Лучшим именем для класса / объектов будет просто Coin или NamedCurrency или другое подобное имя. Думаю, я знаю, к чему вы стремились, но это, вероятно, лучше подходит для вашего проекта.

Удачи.

0 голосов
/ 26 апреля 2018

Есть несколько разных способов сделать это, например, вы можете разобрать словарь внутри вашей функции __init__.

Я склонен справляться с этим, имея отдельный @classmethod, который отвечает за синтаксический анализ словарей для создания экземпляров моего класса.

Примерно так:

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'])

Таким образом, я не обязан передавать Coinbuilder словарь для создания экземпляра класса, но у меня есть простой метод, который я могу использовать для разбора словаря для создания экземпляра моего класса.

Для этого простого примера я могу сделать следующее:

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

Или я мог бы использовать:

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

И получите два одинаковых экземпляра класса:

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

Выход:

BTC Bitcoin
BTC Bitcoin

Используя ваш пример ввода в качестве руководства, как только вы напишите свой @classmethod для разбора словаря, вы можете просто использовать:

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

Или:

my_coins = [Coinbuilder.build_from_dict(result) for result in coins['result']]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...