google web font

Показаны сообщения с ярлыком программирование. Показать все сообщения
Показаны сообщения с ярлыком программирование. Показать все сообщения

понедельник, 14 марта 2016 г.

Сколькими способами можно развернуть генератор в список в Python3

Одно из заметных нововведений в Python3 по сравнению с Python2 это то, что встроенные функции filter, map, range и zip теперь возвращают итераторы. В некоторых случаях этот итератор может занимать больше памяти, чем тот список, который от него хотят. А если их ещё и засовывать один в другой, вроде чего-то такого:
def increase(self, *increments):
    self.values = map(sum, zip(self.values, increments))
так вообще никакой памяти не хватит. Отсюда, конечно вопрос: как развернуть этот итератор в нормальную последовательность? Как бы сильно это ни противоречило Дзену Пайтона, способов много.
Самый очевидный вариант:
def increase(self, *increments):
    self.values = tuple(map(sum, zip(self.values, increments)))
Слишком просто, чтобы писать об этом блог-пост. С таким же успехом можно было вообще избавиться от map, использовав list-comprehension:
def increase(self, *increments):
    self.values = [sum(x) for x in zip(self.values, increments)]
(обязательно квадратные скобки, а то генератор никуда не денется :-)
В общем, есть более экзотические варианты.

понедельник, 8 февраля 2016 г.

Немного про познание рекурсии

Для того, чтобы познать рекурсию, надо познать рекурсию.
http://bash.im/quote/11128

Познавать рекурсию нужно с детства, я так считаю. Когда родители вручают ребёнку счётные палочки, речь должна идти только о том, что каждое следующее число есть предыдущее число, увеличенное на единицу.
int getNthNumber(int n) {
    int nthNumber = getNthNumber(n-1) + 1;
    return nthNumber;
}
Ну, конечно, обязательно нужно оговориться, что первое число равно нулю
int getNthNumber(int n) {
    if (n == 1) // первое число равно нулю по определению
        return 0;
    int nthNumber = getNthNumber(n-1) + 1;
    return nthNumber;
}
Хотя, в примере выше есть ошибка, в нём нулю равно второе число. Потому что если первое число равно нулю, то первый номер первого числа тоже равен нулю, а не единице (вот это утверждение уже имеет отчётливый привкус рекурсии)
int getNthNumber(int n) {
    if (n == 0) // первое число равно нулю по определению
        return 0;
    int nthNumber = getNthNumber(n-1) + 1;
    return nthNumber;
}

вторник, 25 августа 2015 г.

Как сделать jar, который может сам себя выполнить


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

Типичное использование:
$ java -jar my-fancy-app.jar
Для того, чтобы это работало, нужно при сборке jar-файла указать исполняемый класс (MainClass), это всем известно, абитуриентов не принимают на первый курс, если они этого не знают.

Все программы, которые умеют делать что-то полезное, используют какие-то библиотеки, написанные другими людьми и заранее упакованные в другие -jar-файлы. Чтобы моё приложение могло их подцепить, мне нужно добавить их в classpath. Но когда я запускаю -jar, я не могу указать дополнительно другой classpath. Я не склонен винить кого-либо в этом ограничении, вопрос "почему" не настолько сильно меня беспокоит. Больше интересно, что делать.

Популярное решение: "uber-jar". Говорят, раньше у maven был плагин, который так назывался (сейчас для этого используется плагин shade). Он архивирует jar'ы зависимостей внутрь jar'а моего приложения и прописывает свой MainClass, который устанавливает свой classloader, а потом возвращает управление моей программе. Classloader загружает библиотеки из вложенных jar-файлов и не сильно отличается от того, который описан в одном из первых уроков по java на сайте оракла. Раньше, говорят, был плагин, который вообще jar'ы зависимостей распаковывал прямо в мой jar, ему даже classloader подменять не надо было.

Это решение может не работать в ситуации, когда одна из зависимостей имеет злобную лицензию, не позволяющую паковать её в свой jar. Поскольку указать дополнительный classpath при использовании ключа -jar нельзя, остаётся два варианта: поставить эту библиотеку в систему (типа $JAVA_HOME/lib/) либо не использовать ключ -jar. Как это не использовать?

суббота, 23 июля 2011 г.

Достоверный источник

На нашей юмористической работе никаких башоргов не надо. Самый юмористический ресурс, который я читаю — это еженедельный отчёт техподдержки, который генерируется системой автоматически. Именно оттуда я узнал про эту загадочную историю.

Введение. Центробанк каждый день публикует курсы валют в свободном доступе для того, чтобы другие банки могли своевременно его узнавать. Для того, чтобы автоматизировать импорт, центробанк предоставляет "API" — XML-файл с названием в виде текущей даты, который можно получить по определённому адресу у них на сайте. Поскольку наша система работает с деньгами, у неё в комплекте есть скриптик, который вытаскивает этот XML и засовывает курсы нужных валют в базу данных. Согласно моим наблюдениям (пока я расплачивался с ипотекой, мне приходилось следить за курсом доллара), ЦБ РФ публикует курс на следующий день не раньше часа дня, иногда даже после двух.

понедельник, 21 марта 2011 г.

Дайте этим лентяям побольше работы

Некоторые считают, что народ занимается ерундой и ленится только тогда, когда ему нечего делать. Проблема лентяйства решается просто: загрузить работой. В результате програмисты всегда имеют несколько срочных задач, из-за которых им некогда уделять внимание таким интересным и полезным ресурсам, как собственный баг трекер.

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

И вот, значит, формулировка бага: «демон с какого-то момента начинает обновлять свои записи не каждую минуту, а раз в две с половиной минуты (вот вам логи), а другие экземпляры считают его записи устаревшими и удаляют их». Правильное решение проблемы: заставить техподдержку и тестировщиков выяснить, в чём причина задержек, найти виновного и заставить его исправить ошибку/устранить проблему.

Но высоконагруженный программист вместо этого добавляет конфигурируемый параметр: теперь таймаут устаревания записи можно настраивать самостоятельно. То есть получаем следующий нюанс: демон начинает произвольным образом забывать/опаздывать обновлять записи о том, что он ещё не умер, а техподдержка подстраивает под него таймауты в настройках. Образец стройности архитектуры, нечего сказать.

Самое главное в итоге, конечно, это не то, что архитектура получилась неочевидная. Главное, что техподдержка без работы не останется. Руководство одобряет такой подход, ибо техподдержка у нас платная.

четверг, 17 февраля 2011 г.

ускоренный повтор или замедленная перемотка shell replay

Как я уже отмечал, по долгу работы я иногда оптимизирую рутинные действия в консоли с помощью всяких интересных штучек. И сегодня я хочу рассказать об одной "фиче", которую я изобрёл для того, чтобы не вбивать набор команд несколько раз, но при этом не создавать для них одноразовые alias'ы.

вторник, 15 февраля 2011 г.

error="All OK"

Обожаю подобные мессаджи: <ERROR error="All OK">
Ужасная ошибка, должно быть, произошла. Я такое уже видел недавно, только там было:
error connecting to target. Error message was [SUCCESS]

Самое интересное, что на самом деле это даже не сообщение об ошибке, а именно сообщение об отсутствии ошибок :-)

Ну прям как в классике:

воскресенье, 13 февраля 2011 г.

alias против bash-функицй: rm -i

Итак, я решил на наглядном примере объяснить, чем принципиально отличается шелловский alias от шелловской функции. В качестве примера я решил использовать распространённый совет, который дают всем начинающим админам многочисленные авторы книг и статей про консоль: это совет прописать в ~/.bashrc такое:
alias rm='rm -i' 
Кстати, этот алиас демонстрирует хорошую особенность: если в теле алиаса есть команда, совпадающая по имени с именем алиаса, то он не впадает в бесконечную рекурсию, а нормально обрабатывает эту ситуацию.

Для тех, кто не понял: этот алиас заставляет команду rm запрашивать ввод подтверждения для каждого удаляемого файла. Напомню, к чему это ведёт, помимо того, что понижает вероятность случайно снести нужный файл.

пятница, 11 февраля 2011 г.

Как сделать, чтоб ничего не делать

Компьютер — замечательная вещь, позволяющая эффективно решать проблемы, которые без него вообще не возникли бы (© афоризм). По долгу работы мне приходится часто вбивать одну и ту же последовательность команд в линуксовую консоль, чтобы эффективно решить проблему. Наиболее банальные последовательности быстро превратились в алиасы. Алиасы многократно вводятся путём нажатия стрелки вверх и кнопки Enter, что заставило меня проникнуться понимаем основ цикла for непосредственно в командной строке (это выглядит примерно так: for X in $(seq 1 10); do useful_alias; done). В общем-то, большая часть bash_history примерно из такого мусора и состоит, но есть вещи, которые автоматизированы чуть более весело. Итак, есть несколько способов заставить консоль саму выполнять нужную последовательность команд.

Двойственные чувства и провалы в менеджменте

У меня такое впервые на этой работе. Во мне просыпаются двойственные чувства к этой несчастной Платформе предоставления IPTV услуг. С одной стороны, проект практически готов и оттестирован, несмотря на ужасные провалы в менеджменте. С другой стороны, провалы в менджменте приводят к тому, что каждый раз, как только кто-то из нас тянется к кнопке Resolved, приходит обновлённый вариант ТЗ и приходится всё переделывать. Кто виноват и что делать?

понедельник, 11 октября 2010 г.

to bydlocode or not to bydlocode

В пятницу наблюдал замечательное явление: душевные терзания. Все знают, что быдлокодить плохо и все однозначно осуждают быдлокод. Но на самом деле не всё так однозначно и быдллокодить бывает необходимо. Это ставит хорошего программиста перед дилеммой.
Обстановка: есть некий словарь в БД. Сторонний процесс постоянно вносит в этот словарь новые данные, наш демон эти данные перечитывает в свой кэш по команде от стороннего процесса. Но перечитывает не полностью, так как словарь слишком огромный, а только те записи, момент создания которых больше момента последнего обновления кэша. Почему он не определяет новые записи по id? Да хоть бы и по id, ничего от этого не изменится.

вторник, 22 сентября 2009 г.


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

Нет, тот опус у меня на самом деле вызвал странную смесь чувств: я был очень удивлён тем, что Голубицикй, работающий с компьютерами не один десяток лет, начал испытывать это разочарование только сейчас (ещё меня удивило то, что и я сейчас начал испытывать это разочарование: очень странное совпадение) и я очень понимал праведный гнев "старого голубятника".

Ведь действительно, неужели никогда не видать нам такого, чтоб всё просто работало? Почему всегда обнаруживается архитектурный недостаток, древний баг, который никто не хочет исправлять, неподдерживаемое железо, неподдерживаемое ПО, wrong place, wrong time or wrong state of mind? Это что, карма? Или тенденция?

Хоть вопрос и выглядит риторическим, но у меня есть внутреннее ощущение, что ответ вот он, рядом. Ведь откуда все проблемы? А вот простая аналогия. Открываем ktorrent, ставим на загрузку торрент с несколькими (>20) файлами, открываем окно управления порядком загрузки файлов и пытаемся сделать так, чтобы первые 3-4 файла загружались последними. В текущей версии для этого понадобится около 60-ти кликов мышкой. Это тихий ужас. Не, то есть, конечно, хорошо, что вообще есть такое окошко, в котором можно изменить этот порядок загрузки файлов, но почему тот человек, который это окошко написал сам не попробовал им воспользоваться? У меня такое чувство, что его заставили это сделать из под палки, он сам не понимает, нафига нужна такая функция, и сделал её, чтобы от него отстали. Только тут есть нестыковка: это свободное программное обеспечение, разрабатываемое сообществом на добровольной основе. То есть никто не мог никого заставить. Человек взялся за это добровольно и сделал абы как. Не понимаю.

Антонимичная на первый взгляд ситуация на работе: заказчик заплатил за функциональность, но, ввиду некоторого расп...ского менталитета ТЗ на функционал у нас никогда не проходит тестирования, а пишет его сам заказчик, который не очень представляет на самом деле, как должен выглядеть интерфейс для реализации запрашиваемого функционала. И вот уже на внедрение заказчику отдаётся функционал, котрый полностью соответствует ТЗ, но которым очень не удобно пользоваться по причине, чертовски напоминающей причину из первого случая: нет удобной и полезной кнопки. Програмер отказывается её добавлять: не было в ТЗ. Заказчик мучается только из-за того, что не умеет составлять ТЗ. Глупо. Приходится делать исправленное ТЗ и оплачивать очередную доработку функционала.

Вроде ситуации разные. Вроде разный результат. А в итоге одно и то же: проблемы с дерьмовым софтом - системные. Все делают то, за что взялись, так, как будто хотят не сделать что-то новое или полезное, а только, чтоб от них отвязались. И когда таким софтом пользуешься - плакать хочется. Вот я и плáчу...

воскресенье, 20 сентября 2009 г.

Host on ImageShack

Совсем забыл: уже, наверно, больше месяца назад один участник kde-apps попросил меня опубликовать мои изменения сервис-меню для загрузки картинок на ImageShack. Изменения там были значительные (для меня) и уже давно я писал автору сервис-меню, что есть патчи, которые неплохо было бы опубликовать. В принципе, выкладывать было не обязательно, я мог ими пользоваться сам, но вот захотелось, чтобы и другие могли попользоваться.

Так что я выложил это на kde-apps.org. В составе пакета простенький shell-скрипт (bash), который использует curl для загрузки картинок на хостинг, и два сервис-меню (для KDE-3 и KDE-4), которые вызывают этот скрипт для выбранной картинки. Единственное, чего не хватает - система автоустановки. Сервис-меню нужно чуть-чуть отредактировать - в зависимости от того, куда ляжет скрипт, а файлы по системе нужно раскладывать руками. Я пока не очень хочу писать систему автоустановки, потому что не умею

Совместными усилиями с участником YAFU было сделано:
  • поддержка KDE-4
  • поддержка российских хостингов IPicture и oPicture
  • существенно улучшен cmd-line интерфейс
  • всякая другая фигня
Посмотреть и забрать можно здесь. Там же можно комментировать. Фичереквесты, как и багрепорты, если будут, можно писать и там, и здесь.