google web font

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

How to expand an iterator into a list in Python3

One of the most noticeable changes from Python 2 to Python 3 is that map, filter, zip and range builtins now return iterators instead of lists. This is usually a good feature to have, because, well, nobody uses range outside of a for statement. But there may be rare cases when resulting list might take less memory then the iterator itself, especially when you nesting them like this:
def increase(self, *increments):
    self.values = map(sum, zip(self.values, increments))
This is going to eat all the memory and crash with a several gigabyte core dump. So the question is: how does one expand an iterator into a sequence in Python 3? Well, I don't want to hurt the Zen of Python, but there are more than one way to do so.

The most obvious one is this:
def increase(self, *increments):
    self.values = tuple(map(sum, zip(self.values, increments)))
It's too obvious to write the whole post about it. It is as obvious as to get rid of the iterator in favor of the list comprehension:
def increase(self, *increments):
    self.values = [sum(x) for x in zip(self.values, increments)]
(Don't forget to use square brackets, or else you will get a generator, which is practically the same as iterator in this case).

I mean, there are some more exotic ways to do it.

Сколькими способами можно развернуть генератор в список в 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)]
(обязательно квадратные скобки, а то генератор никуда не денется :-)
В общем, есть более экзотические варианты.

пятница, 26 февраля 2016 г.

Javascript plugins for Blogspot

I've just finished with some interface tuning here. I generally like when some piece of work looks nice at the end of the day. Blogspot have some problems here, though. First, it doesn't offer nice fonts (well, it have a few, but with no support for cyrillic). Second, adding a source code syntax highlighter requires manually editing the source code of the template, which is not so fun and have a sad consequence that changes get lost every time I switch the template.

Luckily, there is a clean and portable way to solve my problems without the need to edit the template at all. Here is the recipe:
  • Open blog setting and go to the "Design" tab.
  • Choose a block to add new gadget to. In some cases a block from the top of the page is preferable and in some cases it is better to choose one from the bottom, but in most cases it den's matter so much.
  • Click the "add gadget" link.
  • Choose "HTML/Javascript" in the pop-up
  • Enter any XHTML code, containing CSS and Javascript (enclosed into style and script tags) and hit the "save" button.

Javascript-плагины для blogspot

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

К счастью, на самом деле есть одно решение для обеих этих проблем: это возможность создания собственных "гаджетов".
  • В настройках блога выбираем "Дизайн"
  • Выбираем блок, в который не жалко добавить невидимый гаджет. В зависимости от цели можно предпочесть блок из верхней части страницы или из нижней.
  • Нажимаем "Добавить гаджет"
  • В появившемся окне выбираем "HTML/JavaScript"
  • В окне настроек пишем XHTML-код того, что нам нужно добавить, и сохраняем.

среда, 10 февраля 2016 г.

A word for recursion

Personally, I think that parents must teach recursion to their children as early as they give them counting rods for the first time. The first lesson about counting must be that every number is the previous number plus one
int getNthNumber(int n) {
    int nthNumber = getNthNumber(n-1) + 1;
    return nthNumber;
}
Of course, they need to define that the first number is zero
int getNthNumber(int n) {
    if (n == 1) // first number is zero by definition
        return 0;
    int nthNumber = getNthNumber(n-1) + 1;
    return nthNumber;
}
And there is a second lesson about recursion, which is that the first number have to have the index of zero, too
int getNthNumber(int n) {
    if (n == 0) // first number is zero by definition
        return 0;
    int nthNumber = getNthNumber(n-1) + 1;
    return nthNumber;
}

понедельник, 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;
}

вторник, 29 сентября 2015 г.

Мегафон, опция "Вокруг Света"

А вот вам дельный совет: если вы абонент Мегафона, улетая за границу, включайте опцию "Вокруг Света" в аэропорту вылета, а не прилёта. Потому что она действует по московскому времени.


Что примечательно, в описании опции про это даже действительно написано. Простой пример: если в Сан-Франциско вы вдруг вспомните, что забыли подключить эту опцию, то действовать она начнёт через примерно 10 часов после подключения. Если её включить в московском аэропорту, то в Сан-Франциско она тоже начнёт действовать только через десять часов, но поскольку перелёт длится ещё больше, никто этого не заметит.