Книга открытых ордеров на эксмо содержит занятную структуру данных:
{"BTC_USD":{"ask_quantity":"226.82420996","ask_amount":"2992323.79093759","ask_top":"8475","bid_quantity":"11720.48826229","bid_amount":"1243102.82950626","bid_top":"8453.490004","ask":[["8475","0.0591663","501.4343925"],["8480","0.00145227","12.3152496"],["8484.99","0.05216288","442.60151517"]],"bid":[["8453.490004","0.037","312.77913014"],["8453.390004","0.405","3423.62295162"],["8453.290002","0.00175728","14.85479745"]]}}
Если вы понимаете, о чем это всё – фигурные скобки, двоеточия, квадратные скобки, кавычки и т.п., то эта статья не для вас. Иначе – welcome aboard! К концу статьи такие вещи как книга ордеров будут щелкаться как орешки.
Знаете вы или нет, но роботы уже плотно ворвались в нашу жизнь. Например, в Сингапуре роботы заменяют официантов – принимают заказы от клиентов и развозят заказы по столикам и увозят грязную посуду.
Давайте пофантазируем и предположим, что владелец ресторана в Кондапоге решил привлечь внимание посетителей к своему заведению, закупил железо и теперь просит вас написать для них программное обеспечение. Почему он выбрал именно вас и почему вы будете писать код на Питоне, оставим за кадром. Поехали.
Итак, вам надо в удобном виде предоставить меню. В меню есть первые блюда, вторые, напитки, десерты, мороженное и т.п. У каждого блюда есть какая-то единица измерения и стоимость, у некоторых есть возможность выбора ингредиентов.
Начинающий программист начнет с обычных переменных, и в них же утонет. Например, он может написать так:
borsch = 150 kvas = 100
подразумевая, что борщ продается по 150, а квас по 100. Но потом он вспомнит, что квас бывает в большом стакане и маленьком, и появится новый виток мысли:
borsch = 150 kvas_little = 70 kvas_big = 100
Потом внезапно окажется, что к борщу можно подать сметану, белый или черный хлеб. Появится новый набор:
borsch = 150 kvas_little = 70 kvas_big = 100 borsch_extra_1 = "Сметана" borsch_extra_2 = "Белый хлеб" borsch_extra_3 = "Черный хлеб"
Потом окажется, что надо на экране выводить список того, что есть в меню, и появится новый пассаж:
Реклама:
print("borsch="+borsch, "kvas_little="+kvas_little)
и т.п. В итоге такой робот выехал в зал, клиент посмотрел «меню» и сказал – я буду borsch со сметаной и kvas_big. Что бы передать заказ клиента на кухню, программисту придется писать что-то такое:
if "borsch": print("Клиент заказал borsch за " + str(borsch) + " рублей") if "kvas_little": print("Клиент заказал kvas_little за " + str(kvas_little) + " рублей") if "kvas_big": print("Клиент заказал kvas_big за " + str(kvas_big) + " рублей")
и т.п.
В итоге, когда владелец ресторана решит убрать из меню квас и добавить лимонад, а также 50 видов пиццы, программист повесится.
Для того, чтобы удобно хранить разнородные статичные данные и получать к ним доступ во многих языках разработаны словари (они же хеш-таблицы, они же ассоциативные массивы). Словарь – это, хм, словарь. Например, англо-русский словарь содержит слова на английском (ключи), которым соответствуют значения на русском. Любой словарь, это связка ключа и значения.
В питоне пустой словарь создается и обозначается так: {}
например
menu = {}
Ключи и значения обозначаются через двоеточие, например, если бы мы хотели перенести код выше в словарь, мы могли бы написать так:
menu = {"borsch":150, "kvas":100}
и потом «вытащить» эти значения вот так:
print(menu["borsch"])
print(menu["kvas"])
но это пока что не добавляет изящности, поэтому мы сделаем красивее: мы в словарь вложим отдельные словари. Любой ключ может ссылаться как на значение, так и на другой словарь, массив, экземпляр класса и т.п. Более красивая структура могла бы иметь такой вид:
menu = { "borsch": { "price":150, "name": "Борщ", "extra": ["Сметана", "Белый хлеб", "Черный хлеб"] }, "kvas": { "name": "Квас", "little": { "price": 70, "amount": 0.3 }, "big": { "price": 100, "amount": 0.5 } } }
Сделаем print(menu) и посмотрим, что возвращается:
{'borsch': {'price': 150, 'name': 'Борщ', 'extra': ['Сметана', 'Белый хлеб', 'Черный хлеб']}, 'kvas': {'name': 'Квас', 'little': {'price': 70, 'amount': 0.3}, 'big': {'price': 100, 'amount': 0.5}}}
Уже похоже на ответ exmo, правда?
Теперь, когда клиент спросит «А что у вас есть?», робот может выполнить что то такое (что бы получить ключи массива):
for item in menu: print(item)
borsch kvas
Или вот так:
print(menu.keys())
Но зачем клиенту знать внутренние обозначения? Надо писать по русски. Например, так:
for item in menu: print(menu[item]['name'])
Что произошло?
Когда мы пишем for item in menu, питон берет словарь, и, до тех пор, пока в словаре есть ключи, получает следующий ключ и присваивает его переменной item (или как вы её назовете). Разберем подробнее:
menu = { "borsch": { "price":150, "name": "Борщ", "extra": ["Сметана", "Белый хлеб", "Черный хлеб"] }, "kvas": { "name": "Квас", "little": { "price": 70, "amount": 0.3 }, "big": { "price": 100, "amount": 0.5 } } } for any_variable_name in menu: print("Текущее значение переменной any_variable_name=", any_variable_name) print("В словаре под этим ключом хранится вот что: ", menu[any_variable_name]) print("Возьмем из вложенного словаря значение name -> ", menu[any_variable_name]['name']) print('---')
Похожих результатов можно добиться, если использовать метод словаря items(). Этот метод возвращает сразу и ключ, и значение. Заменим код на вот такой, что бы код был проще и «чище»:
menu = { "borsch": { "price":150, "name": "Борщ", "extra": ["Сметана", "Белый хлеб", "Черный хлеб"] }, "kvas": { "name": "Квас", "little": { "price": 70, "amount": 0.3 }, "big": { "price": 100, "amount": 0.5 } } } for key, value in menu.items(): print(key, value) print(value['name']) print('---')
Но бывает такое, что мы не знаем, есть ключ в словаре или нет – например, у борща есть цена price, а у кваса нет. Есть несколько способов проверить – каждый подбирается по ситуации.
menu = { "borsch": { "price":150, "name": "Борщ", "extra": ["Сметана", "Белый хлеб", "Черный хлеб"] }, "kvas": { "name": "Квас", "little": { "price": 70, "amount": 0.3 }, "big": { "price": 100, "amount": 0.5 } } } for key, value in menu.items(): print("Вариант 1") print(value['name']) if 'price' in value: print("Цена", value['price']) print('---') print("Вариант 2") print(value['name']) print("Цена", value.get('price', 'Не указано')) print('---') print("Вариант 3") print(value['name']) try: print("Цена", value['price']) except KeyError: print("Цена не указана") print('---') print("Вылетит с ошибкой, если нет цены") print("Цена", value['price']) print('---')
В первом случае мы проверили, есть ли ключ, и, если есть, вывели значение.
Во втором, воспользовались методом get(), который либо выведет значение указанного ключа, либо выведет указанное нами значение.
В третьем случае, мы выводим цену в любом случае, но если её нет, то перехватываем ошибку, и пишем своё сообщение.
В четвертом случае выводим как есть, и, если ключа нет, вылетает ошибка (вообще-то такие «ошибки» называются исключениями, но об этом в другой раз).
До этого мы руками завели словарь (или получили готовый), давайте посмотрим, как можно манипулировать содержимым.
menu = { "borsch": { "price":150, "name": "Борщ", "extra": ["Сметана", "Белый хлеб", "Черный хлеб"] }, "kvas": { "name": "Квас", "little": { "price": 70, "amount": 0.3 }, "big": { "price": 100, "amount": 0.5 } } } # Добавим вареники menu["vareniki"] = {"price":20, 'name': "Вареники"} print(menu) # Удалим вареники del menu['vareniki'] print(menu) # Заменим квас на строку menu['kvas'] = "Закончился" print(menu) # Добавим 50 сортов пиццы по 300 рублей for i in range(100): menu["pizza_"+str(i)] = {"price":300, 'name': "Пицца " + str(i)} print(menu) # Очистим словарь menu.clear() print(menu)
Что бы вам еще рассказать?
Узнать количество ключей словаря можно узнать с помощью len()
print(len(menu))
Иногда людям зачем-то хочется еще и сортировать словари в алфавитном или ином порядке. Вообще, это не задача для словарей, т.к. они спроектированы не для этого, а для того, что бы как можно быстрее возвращать значения для указанного ключа. Но если очень хочется, то можно воспользоваться такой конструкцией:
for k in sorted(menu): print(k)
Что бы выводить в обратном порядке, добавьте параметр функции:
for k in sorted(menu, reverse=True): print(k)
По сути сейчас словарь не отсортировался, а были получены ключи, которые и были отсортированы.
Ну, и для закрепления давайте рассмотрим пример из начала статьи - тот же словарь, в нем другие словари, местами массивы.. Ну, вы сами знаете :)
exmo_response = {"BTC_USD":{"ask_quantity":"226.82420996","ask_amount":"2992323.79093759","ask_top":"8475","bid_quantity":"11720.48826229","bid_amount":"1243102.82950626","bid_top":"8453.490004","ask":[["8475","0.0591663","501.4343925"],["8480","0.00145227","12.3152496"],["8484.99","0.05216288","442.60151517"]],"bid":[["8453.490004","0.037","312.77913014"],["8453.390004","0.405","3423.62295162"],["8453.290002","0.00175728","14.85479745"]]}} for pair, value in exmo_response.items(): print("Пара",pair) print("Лучшие цены", value['ask_top'], value['bid_top']) print("Стаканы:") print("Продажа", value['ask']) print("Покупка", value['bid']) for item in value['ask']: print("Готовы продать {amount:0.8f} по курсу {rate:0.8f}".format( amount=float(item[1]), rate=float(item[0]) ))
Всем удачи и позитива )