Преобразования монет к доллару США


Я использую 2 объекты внутри моего класса. Мои действия практически идентичны, однако я хочу вернуть 2 разных типов данных, и оба они немного отличаются друг от друга.

import requests


class coins:

    def coins_arr(self):
        params = {'limit': 10, 'convert': 'USD'}
        data = requests.get('https://api.coinmarketcap.com/v1/ticker/?%s' % params).json()
        coinsData = []
        for objects in data:
            for k in objects.keys():
                if k == 'id':
                    coinsData += objects[k].split()
        #returns array of coin names 
        return sorted(coinsData)



    def coins_dict(self):
        params = {'limit': 10, 'convert': 'USD'}
        data = requests.get('https://api.coinmarketcap.com/v1/ticker/?%s' % params).json()
        coinsDict = {}
        for objects in data:
            for k,v in objects.items():
                if k == 'id':
                    coinsDict.update({objects[k]:objects['price_usd']})
        #returns dictionary with name:price   
        return coinsDict

d = coins()

print (d.coins_arr())

Я думал о возвращении coins_dict.keys()но это не вернет мне его в отсортированном порядке. Я не уверен, если я могу реализовать функцию Lambda, когда я называю объект класса.



292
4
задан 29 января 2018 в 04:01 Источник Поделиться
Комментарии
4 ответа

Первые вещи во-первых, конвенция является использование прописных-начальная для названия класса.

Все модули, функции, классы и методы должны иметь комментарии.

Согласно их документации по API, если limit Не указано, по умолчанию-100 и по умолчанию convert это 'США'. Ваш coins_arr() метод возвращает 100 монет, а не 10, я думаю это из-за неверного форматирования заполнитель в URL, передаваемые в requests.get(). Вы разделяете каждой монеты и объединении его coinsData, которая не является необходимой, так как вы просто должны добавить его в список.

В coins_dict() метод также возвращается 100 монет, а не 10.

Есть также некоторые повторения в два метода, которые вы могли бы избежать.

Здесь я хотел бы написать класс, вот так:

import requests

class Coins:
"""This is a class for cryptocurrencies."""

def __init__(self, url, limit=10):
self.url = url
self.limit = limit
self.data = requests.get(self.url.format(self.limit)).json()

def get_coins(self):
"""Return a sorted list of cryptocurrencies."""

coins = sorted(v for obj in self.data
for k, v in obj.items() if k == 'id') # sorted() returns a list

return coins

def get_coins_prices(self):
"""Return a dictionary of cryptocurrencies and their prices."""

coins_prices = {obj[k]: obj['price_usd'] for obj in self.data
for k, v in obj.items() if k == 'id'}

return coins_prices

if __name__ == '__main__':
url = 'https://api.coinmarketcap.com/v1/ticker/?limit={}'

obj_a = Coins(url)
print(obj_a.get_coins())

obj_b = Coins(url)
print(obj_b.get_coins_prices())

obj_c = Coins(url, limit=5) # Setting limit to 5 results
print(obj_c.get_coins_prices())

В версии Python используются для тест приведенный выше код 3.6.

Надеюсь, что помогает.

5
ответ дан 30 января 2018 в 04:01 Источник Поделиться

Вам не нужен класс

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

Это не тот случай здесь. Класс coins никакой пользы, кроме пространства имен, в котором две функции определены (что извращаться, добавив функцию имен имя класса).

Показателем этого является то, что self аргумент две функции никогда не используется.

Вам не нужны две функции

Эти две функции, по сути, делают то же самое, за исключением того, что одна функция (coins_arr возвращает отсортированный список имен монета) - это специализированная версия другие функция (coins_dict возвращает сопоставление с монету имен по их ценам).

Там должны быть только coins_dict функция, и если это абсолютно необходимо coins_arr функция может быть определена в терминах coins_dictно не путем повторения вариации одного и того же кода.

Ошибка

Как уже отмечалось в другой ответ, два параметра limit и convert не имеют никакого эффекта, потому что они передаются request.get неправильно:

>>> params = {'limit': 10, 'convert': 'USD'}
>>> print('https://api.coinmarketcap.com/v1/ticker/?%s' % params)
https://api.coinmarketcap.com/v1/ticker/?{'convert': 'USD', 'limit': 10}

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

>>> response = requests.get('https://api.coinmarketcap.com/v1/ticker/', params)
>>> print(response.url)
https://api.coinmarketcap.com/v1/ticker/?convert=USD&limit=10

Улучшен код

Имя функции может быть улучшена и строкой документации могут быть добавлены, чтобы лучше описать то, что делает функция.

В limit и convert параметров может быть сделано в функции аргументы так, что различные параметры могут быть использованы без изменения определение функции каждый раз.

В ответ код состояния могут быть проверены для того чтобы обеспечить более полезные сообщения об ошибке в случае, если URL-адрес является неправильным или сервис не доступен и т. д., вместо того, чтобы процесс бессмысленный результат.

Монтаж возвращаемое значение может быть упрощена с помощью понимания словарь.

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
}

В coins_arr функция может быть легко воспроизведена с помощью keys() из словаря, возвращаемого fetch_coin_prices:

>>> coins = fetch_coin_prices(limit=5)
>>> print(sorted(coins.keys()))
['bitcoin', 'bitcoin-cash', 'cardano', 'ethereum', 'ripple']

5
ответ дан 30 января 2018 в 03:01 Источник Поделиться

Я подозреваю, что есть больше, соответствующего кода, чем то, что я вижу здесь, так что примите мои предложения с зерном соли.

Обновлены Организации

Это звучит, как вы нужны оба. У меня была подобная проблема раньше, когда я нуждался в массив и словарь. Я не пишу много на Python, так что я собираюсь написать это в JSON. Я бы просто поставил их на один и тот же объект. И пусть клиент код вызова coins.arr или coins.dict.

var coins = {
arr: [coin1, coin2, coin3],
dict: {
'coin1': coin1,
'coin2': coin2,
'coin3': coin3
}
};

Обновлено Оптимизации

Я хотел бы быть осторожным, что отдельные объекты между Арр и дикт сослался на те же объекты в памяти, и я хотел бы убедиться, идти за ваш ответ с сервера только один раз и выполнить вставки в массив и словарь одновременно.


Предыдущие Организации

Я бы рекомендовал рассматривать через 'собранность' если вы хотите повторно использовать код между этими объектами. Возможно, давайте посмотрим, что еще происходит.

Предыдущей Оптимизации


  • Что мы с помощью этих словарей и массивов?

  • Как они используются?

  • Вы действительно хотите повторно запросить данные каждый раз?

Я подозреваю, что было бы разумно просить после того, как данные, и хранить данные в первичный формат (массив, словарь или другие), а затем преобразовать в другой при необходимости. Но мне потребуется больше информации, чтобы сделать обоснованное предположение есть.

2
ответ дан 29 января 2018 в 04:01 Источник Поделиться


  1. Занятия должны быть в CamelCase - Coins, а не coins.

  2. Вы можете объединить requests позвоните в одну функцию, так что ваш код сухой.

  3. Не использовать CamelCase для переменных, coins_dict лучше. Я бы просто использовать coins.

  4. Цикл весь objects чтобы найти ключ 'id'. Вместо этого, если это словарь, использовать dict.get.

  5. Если вы используете collections.OrderedDict затем вы можете хранить все в одном объекте, и извлечь дополнительную информацию, когда вам нужно.

    Однако вам даже не нужна для этого, как вы не волнует, если ваш вклад в Ваш массив упорядочен.


  6. Вы используете objects.itemsно не используйте vвместо того, чтобы вас использовать objects[k]. Не делай этого.

  7. Не ставьте пробел между print и скобки.

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

import requests

class Coins:
def _get_coins(self):
params = {'limit': 10, 'convert': 'USD'}
return requests.get('https://api.coinmarketcap.com/v1/ticker/?%s' % params).json()

def coins(self):
coins = {}
null = object()
for objects in self._get_coins():
id_ = objects.get('id', null)
if id_ is not null:
coins[id_] = objects['price_usd']
return coins

@staticmethod
def coins_it(coins):
return sorted(
v
for value in coins.values()
for v in value.split()
)

d = Coins().coins()
print(d)
print(list(Coins.coins_it(d)))

1
ответ дан 30 января 2018 в 09:01 Источник Поделиться