Непайтоновый Пайтон

http://skien.cc/blog/2014/04/09/unpythonic-python/
  • Перевод

FizzBuzz


Когда я подавал заявку на вступление в Hacker School, я столкнулся со следующей задачкой:
Напишите программу, которая выводит числа от 1 до 100 (включительно). Если число делится на 3, выведите Fizz вместо числа. Если оно делится на 5, выведите Buzz. Если оно делится как на 3, так и 5, выведите FizzBuzz. Вы можете использовать любой язык программирования.

(С тех пор сотрудники Hacker School слегка изменили задачку, скорее всего, для того, чтобы затруднить её решение с помощью интернет-поисковиков. Я намеренно не включил сюда изменённое условие, чтобы минимизировать эффект моего поста на гуглобельность.)

Задачка довольно проста и не требует обдумывания, поэтому хорошо подходит как пример для разных языков и стилей программирования словно Hello, World или задача на поиск чисел Фибоначчи.

Немного непайтонового Пайтона


Сегодня я опять видел эту задачу, когда показывал другу мою заявку в Hacker School, и внезапно я задумался над тем, как много способов её решения существует лишь только в Пайтоне. Пайтон, особенно с PEP 8, представляет пользователю идеальные методы написаний пайтонового Пайтона. Но Пайтон не требует пайтоновости, поэтому я задумался, в каких стилях я могу писать.

Внимание: далее следует очень непайтоновый Пайтон. Тем не менее, код должен работать (с Пайтоном версии 2.7.5).

Присылайте мне свои комментарии или твиты с исправлениями ошибок или добавлениями.

Пайтоновый Пайтон


def fizzbuzz(number):
    if number % 3 == 0 and number % 5 == 0:
        return 'FizzBuzz'
    elif number % 3 == 0:
        return 'Fizz'
    elif number % 5 == 0:
        return 'Buzz'
    else:
        return number

for number in range(1, 101):
    print fizzbuzz(number)


Лисповый Пайтон


fizzbuzz = lambda n: 'FizzBuzz' if n % 3 == 0 and n % 5 == 0 else None
fizz = lambda n: 'Fizz' if n % 3 == 0 else None
buzz = lambda n: 'Buzz' if n % 5 == 0 else None
fizz_andor_maybenot_buzz = lambda n: fizzbuzz(n) or fizz(n) or buzz(n) or str(n)

print reduce(lambda m,n: m+'\n'+n, map(fizz_andor_maybenot_buzz, range(1, 101)))


Джавовый Пайтон


import sys

class Value(object):
    def __init__(self,value):
        self.setValue(value)

    def setValue(self,value):
        self.value = value

    def getValue(self):
        return self.value

    def toString(self):
        return self.getValue().__str__()

class FizzBuzz(object):
    def __init__(self, n):
        if n % 15 == 0:
            value = 'FizzBuzz';
        elif n % 3 == 0:
            value = 'Fizz';
        elif n % 5 == 0:
            value = 'Buzz';
        else:
            value = str(n);
        self.setValue(value);

    def setValue(self,value):
        self.value = Value(value);

    def getValue(self):
        return self.value;

class FizzBuzzRunner(object):
    def __init__(self, n):
        self.setN(n)

    def setN(self, n):
        self.n = n

    def run(self):
        for i in range(1,self.n):
            sys.stdout.write(FizzBuzz(i).getValue().toString()+'\n');

if __name__ == '__main__':
    n = 101;
    FizzBuzzRunner(n).run()


Сишный Пайтон


def main():
    i = 0;
    value = '';

    while i < 100:
        i += 1
        if i % 15 == 0:
            value = 'FizzBuzz';
        elif i % 3 == 0:
            value = 'Fizz';
        elif i % 5 == 0:
            value = 'Buzz';
        else:
            value = str(i);
        print value;

    return 0;

main();


Кложурный Пайтон


def fizzbuzz(n):
    return 'FizzBuzz' if n % 3 == 0 and n % 5 == 0 else None

def fizz(n):
    return 'Fizz' if n % 3 == 0 else None

def buzz(n):
    return 'Buzz' if n % 5 == 0 else None

def fizz_andor_maybenot_buzz(n):
    print fizzbuzz(n) or fizz(n) or buzz(n) or str(n)

map(fizz_andor_maybenot_buzz, xrange(1, 101))
Поделиться публикацией

Комментарии 126

    –10
    «Пайтон» — это Питон (Python)?
      –12
      лол
        +9
        «Пайтон» — это «Пайтон» (в честь Летающего Цирка Монти Пайтона), а питон — змея.
          +35
          Почему-то никого не смущает, когда, например, американцы произносят «Москоу». Никто, почему-то, не требует от них произносить «Москва». Зато любого питонщика задевает, когда Питон произносят на русский манер. Если я буду разговаривать по-английски, я, конечно, буду произносить «Пайтон». Но пока мы разговариваем по-русски на русскоязычном ресурсе, будьте любезны иметь уважение к русскому языку.
            +12
            Я очень уважаю русский язык. Только вот тот факт, что название языка «Пайтон» звучит так же как змея «пайтон» — не более чем совпадение. К змее это слово отношения не имеет.

            Кстати, называете ли в «Руби» «Рубином», «Си» — «Вэ», а «Бейсик» — «Базисным»?
              0
              BASIC вообще-то аббревиатура.
                +3
                Знаю я.
                –3
                Вы не поверите, но змею «пайтон» по-русски зовут «питон».
                А остров «Джава» по-русски зовут «Ява».
                Ну так тут принято.
                  +8
                  Змею — да. А тут «Пайтон» — фамилия.
                    +13
                    Тогда уж «Пайсн». Еще, кстати, обратите внимание на логотип на python.org
                    +2
                    Как представлю, Исаак Азимов, Георгий Кустин, Федор Ртутный. Сразу начинаю гордиться за свою страну.
                      +4
                      Во-первых, Азимова по его российским документам действительно звали Исааком.

                      Во-вторых, последний-то Фредди, а не Тедди — так что Фёдор мимо.
                        +5
                        Это, конечно, все меняет :/
                        +3
                        Георгий Кустин, Федор Ртутный
                        — Кто все эти люди?
                          +3
                          Джордж Буш, Фредди Меркьюри.
                            +2
                            О последнем я даже и не знал. Некультурный я человек…
                          +6
                          Давайте сразу Иван Севастьянович Ручьёв
                        +6
                        «К змее это слово отношения не имеет»

                        тем не менее, присутствие в символике языка изображений змей говорит о том, что такое совпадение не только не игнорируется сообществом, но и приветствуется им. поэтому не вижу причин отказываться от русской альтернативы названия языка.
                          0
                          Именую язык «питоном» мы теряем основную ассоциацию. Всё-таки Монти Пайтоны довольно известны и в России тоже.
                        • НЛО прилетело и опубликовало эту надпись здесь
                          0
                          Мы из пятой колонны. Выучили нас на свою голову, что теперь делать.
                            +14
                            Я питонщик и считаю, что в русском языке нужно говорить «Питон». Вы же не говорите «Зирокс» и «Мэк оу-эс тэн»?
                              +8
                              Блин, если вы питонщик, то должны знать, что холивор здесь не про произношение английских слов по английски в русской речи, а в том, что имя языка — это имя персонажа (человека). А имена в русской речи не переводятся и произносятся как есть.
                              Претензия имеет все основания на существование.

                              Поэтому в писменной речи я стараюсь употреблять Python, и пусть все читают как хотят. А в устной по русски я говорю «Питон» просто потому что.

                              Другие торговые марки, которые содержат в себе имена, воспринимаются нормально и произносятся как по-английски — Hewlett-Packard, Johnson&Johnsons, Ford и другие.
                                +3
                                А имена в русской речи не переводятся и произносятся как есть.

                                Ну да, Джордж Уошингтон и Айзек Нью́тон одобряют ваше утверждение.
                                  +4
                                  А Айзек Азимов, Джордж Буш, Фредди Меркюри — ваше.

                                  То, что в русском языке принято коверкать некоторые имена (например, безграмотное «Фрейд» вместо «Фройд» или «Вашингтон» вместо «Уошинтон»), это не значит, что каждый русскоговорящий обязан коверкать все иностранные имена.

                                  PS К иностранцам всегда представляюсь «Андрей», а не «Эндрю».
                                    +5
                                    > К иностранцам представляюсь
                                    > в русском языке принято коверкать
                                      +1
                                      Ну я бы не стал называть это «коверканием». Есть «устоявшиеся» интерпретации имён и названий. Ну, вот к примеру, мы же не говорим «Хамбург», хотя правильно именно так. Этот город всю жизнь был Гамбургом. А вот название Хайдельберг употребляется, равно как и Гейдельберг. Также и с Питон/Пайтон. Язык постоянно развивается, а уж что приживётся — время покажет. Пайтон пока что режет слух, честно говоря.
                                        +1
                                        Эдак можно и до Уотсона/Ватсона дойти.
                                          +3
                                          Этот аргумент работает и в обратную сторону. Например, Ньютон/Невтон.
                                      0
                                      Давайте тогда на основании того, что название города Москва (Moscow) основано на названии реки Москва (Moskva) требовать, что бы иностранцы использовали перевод названия реки в качестве перевода названия города.
                                        +2
                                        Так и должно быть, но исторически сложилось не так. Название раньше было «гра́д Моско́в», если верить википедии, от этого и произошла англоязычная форма.
                                        +1
                                        Джек Ландон, Исаак Азимов.

                                        Честно, мне самому не нравится, что так сильно (я не беру во внимание, что в русском и английском одинаковых звуков не так уж много) транскрипция и написание меняется, но не вижу повода для холивара. Это общепринято, не только в русском языке. Да и нашли повод, чтоб ругаться
                                      +2
                                      Ну почему же «любого»? Мой друг-питонщик в шутку называет свой любимый язык «Пятон» и иногда «Пятончег». :)
                                      +30
                                      И на логотипе тоже 2 господина Монти нарисованы?
                                      Пайтон блин

                                      Я не сомневаюсь, что Гвидо назвал язык в честь персонажа, но по русски это режет слух. Надеюсь вы не говорите «ПиЭйчПи», «ЭйчТиЭмЭл», «СиПласПлас».

                                      UPD на ваш комментарий выше: На логотипе нарисованы 2 питона. Так что отношение имеет.
                                        –9
                                        Да уж обсудили сто раз логотип-то. Все знают, что Гвидо смирился с неграмотностью и выбрал змей.
                                          +12
                                          Как у Пелевина:

                                          — Ой, то не вечер да не ве-е-ечер, — запели строгие мужские голоса, — мне да малым мало спало-ось…
                                          — Люблю эту песню, — сказал я.
                                          — Как же ты ее барин, любить можешь, если не слышал никогда? — спросил Игнат, присаживаясь рядом.
                                          — Почему же не слышал? Это ведь старая казачья песня.
                                          — Не, — сказал Игнат. — Путаешь. Эту песню господин барон специально для нас сочинили, чтоб мы пели и думали. А чтобы нам легче запомнить было, в ней и слова такие же, как в той песне, про которую ты говоришь, и музыка.

                                          Мне, вдруг, подумалось, что в какой-то параллельной Вселенной мог бы возникнуть форк языка. Таким образом, один — Питон — был бы посвящен змее, а второй — Пайтон — был бы посвящен цирку Монти Пайтона. Разницы не было бы абсолютно никакой, зато можно было бы холиварить вволю.
                                          0
                                          Надеюсь, вы не говорите «сэ-плюс-плюс»?
                                            +2
                                            Что сказать — подловили.
                                            +7
                                            Хм… Мы со знакомыми говорим именно «пи-эйч-пи» и «эйч-ти-эм-эл». «Си-плас-плас» — уже перебор, конечно. Как и «цэ-плюс-плюс».

                                            Это всё исключительно дело привычки. Спор на пустом месте.
                                              +3
                                              Си-плас-плас тоже проскакивает, хотя и редко. Но то, что я говорю си-шарп, а не до-диез (и даже не це-решётка), это точно. Вот «эйч-ти-эм-эл» сказать обычно не получается — в конце откуда-то вылезает мягкий знак («эйч-ти-эм-эль»), хотя я французского не учил.
                                        +12
                                        как java-разработчику, мне больно смотреть на этот стереотип…
                                          +9
                                          К большому сожалению это не стереотип. Еще хватает людей кто придерживается подобного стиля.
                                            +2
                                            Это Java-EE.
                                              +3
                                              Для ЕЕ надо хотя бы разнести
                                                      if n % 15 == 0:
                                                          value = 'FizzBuzz';
                                                      elif n % 3 == 0:
                                                          value = 'Fizz';
                                                      elif n % 5 == 0:
                                                          value = 'Buzz';
                                              
                                              на два разных класса: в одном проверки, в другом строки.
                                                +5
                                                VisitorPattern самое оно здесь…
                                                  +4
                                                  и фабрику по созданию объктов в зависимости от кратности числа
                                              –3
                                              А вы говорите «ява» или «джава»? :)
                                                +6
                                                это вы так тонко пытаетесь продолжить холивар из первого коментария?
                                                  +2
                                                  В речи — «жаба», в формальном тексте — java
                                                    +1
                                                    В зависимости от контекста. Шутливо — «жаба». Серьёзно, но при устном общении «со своими» — Ява. В письменном тексте и официальном обсуждении — «Джава/Java»
                                                  +18
                                                  Все варианты неэффективны — по меньшей мере одно лишнее сравнение
                                                    +4
                                                    Лишнее сравнение? Да после обилия операций взятия остатка от деления лишнее сравнение вообще ни разу не критично :)

                                                    Уж для двух заранее известных делителей можно было бы завести по отдельной переменной, инкрементирующейся на каждой итерации, и в них хранить остаток.
                                                    –4
                                                      +8
                                                      А это какой Пайтон?

                                                      [['FizzBuzz', 'Fizz', 'Buzz'][max(enumerate([not num % 15, not num % 3, not num % 5]), key=lambda x:x[1])[0]] if sum([not num % 15, not num % 3, not num % 5]) else num for num in xrange(1, 101)]
                                                      
                                                        +6
                                                        Перлово-хакерский, нет?
                                                          +11
                                                          Перловый.
                                                            +7
                                                            Я бы сказал, что это не перловый, а просто заявка на конкурс по obfuscated code. :)

                                                            Питоновский вот:
                                                            print map (
                                                                    lambda _:
                                                                    (
                                                                            _ % 15 == 0 and 'FizzBuzz'
                                                                                    or _ % 3 == 0 and 'Fizz'
                                                                                    or _ % 5 == 0 and 'Buzz'
                                                                                    or _
                                                                    ),
                                                                    range( 1, 101 )
                                                            )
                                                            
                                                              +2
                                                              s/Питоновский/Перловый/, конечно.
                                                                +5
                                                                Как-то недостаточно запутанно для Перла :) Должно быть как-то так:

                                                                print(map(lambda _:('Fizz'*(not _%5)+'Buzz'*(not _%3))or _, range(1,101)))
                                                                
                                                                  +1
                                                                  Гм. Ниже предложили очень похожий на этот вариант. Не увидел.
                                                              +1
                                                              А принта нет. Не получается однострочник.
                                                                +1
                                                                Ну так поставьте впереди :)
                                                                  +1
                                                                  Нууууу, так не интересно. Но ладно, засчитывается.
                                                              +34
                                                              Я вот такой придумал, только не знаю что это за стиль :)

                                                              def fizzbuzz(number):
                                                                  return {
                                                                      0: number,
                                                                      number % 3: 'Fizz',
                                                                      number % 5: 'Buzz',
                                                                      number % 15: 'FizzBuzz',
                                                                  }[0]
                                                              
                                                              for number in range(1, 101):
                                                                  print fizzbuzz(number)
                                                              
                                                                0
                                                                Гениальный :)
                                                                Хотя использование диктов для реализации Switch Statement рекомендовано как раз в питоне.
                                                                  +4
                                                                  Тут не совсем они. Обычно словари используются для выборки по индексу, а тут дело в том, что при срабатывании индекс затирается :)
                                                                    +6
                                                                    {…}[case] — у вас просто ключ всегда равен нулю — да, switch происходит на стадии формирования дикта. Блин, как клево! :)
                                                                      +1
                                                                      А гарантируется такое поведение словаря?
                                                                        +1
                                                                        Что затираться будет? Сейчас это так, по крайней мере.
                                                                        Но да, полагаться на такое, наверное, неправильно. Но можно добавить пару строчек и делать апдейт словаря по ключу в нужном нам порядке.
                                                                          +1
                                                                          Вот это (принудительно гарантировать порядок) и будет правильным решением для нормального кода. Иначе, в будущем это место может стать источником трудноуловимых багов. Может отличаться работа на разгых версиях Питон или на разных архитектурах, или разных системных библиотеках.
                                                                            +3
                                                                            Порядок гарантирован:

                                                                            If a comma-separated sequence of key/datum pairs is given, they are evaluated from left to right to define the entries of the dictionary: each key object is used as a key into the dictionary to store the corresponding datum. This means that you can specify the same key multiple times in the key/datum list, and the final dictionary’s value for that key will be the last one given.


                                                                            . То же самое написано в документации для Python 3.4.0. Так что нормальный способ. Только учтите, что вычисляться будут все выражения. Без lambda это ни в коем случае не замена switch.
                                                                              +1
                                                                              Ради интереса проверил, как работает {1: 1, 1: 2, 1: 3} не в CPython. PyPy-2.0.2 и jython-2.5.3-r3 выдают {1: 3}.
                                                                                +1
                                                                                Спасибо за то, что нашли в доках. Я поленился копаться.
                                                                                Ну тогда, конечно, пользоваться можно. Хотя лично мое мнение, что для решения олимпиадной задачи ну или вопроса на интервью такой метод работы со словарем подходит неплохо, но в продакшен коде — ни в коем случае.
                                                                        +3
                                                                        А теперь представим ситуацию, если бы питоновский интерпретатор создавал элементы словаря не в том порядке, в каком они записаны в коде, а в каком-нибудь другом.
                                                                        Хранит же он их в довольно произвольном порядке:
                                                                        >>> {x*x:x*x*x for x in range(1,11)}
                                                                        {16: 64, 1: 1, 4: 8, 49: 343, 81: 729, 9: 27, 64: 512, 25: 125, 100: 1000, 36: 216}
                                                                        >>> {x*x+1:x*x*x for x in range(1,11)}
                                                                        {17: 64, 2: 1, 50: 343, 82: 729, 5: 8, 65: 512, 26: 125, 101: 1000, 10: 27, 37: 216}
                                                                        

                                                                        Какой-то Race-Condition-driven development может получиться.
                                                                          0
                                                                          Он обязан создавать их именно в порядке записи. Это прямо написано в документации. Так что не надо представлять.
                                                                      +5
                                                                      Минуту врубался… Очень круто, спасибо :)
                                                                        +1
                                                                        Очень круто! Вот только вместо {…}[0] наверное лучше сделать {…}.get(0), так логичнее, и читать проще…
                                                                        +6
                                                                        А я такой придумал. Тоже затрудняюсь сказать какой это стиль.
                                                                        True/False переводятся в числа, складываются по основанию два и этой суммой индексируется массив выходных значений.

                                                                        fizzbuzz = [None, 'Fizz', 'Buzz', 'FizzBuzz']
                                                                        
                                                                        for number in range(1, 101):
                                                                          print fizzbuzz[(number % 3 == 0) + (number % 5 == 0) * 2] or number
                                                                        
                                                                          +5
                                                                          Ассемблерный %)
                                                                            +1
                                                                            Компактнее, но кортеж создаётся заново каждый раз.

                                                                            for number in range(1, 101):
                                                                              print (number, 'Fizz', 'Buzz', 'FizzBuzz')[(not number % 3) + (not number % 5) * 2]
                                                                            
                                                                              +2
                                                                              Был такой вариант, но совесть не позволила написать.
                                                                            +7
                                                                            Больше всего понравился вариант с генератором:

                                                                            fizzbuzz = ((not x % 3) * 'Fizz' + (not x % 5) * 'Buzz' or x for x in range(1, 101))
                                                                            
                                                                            for x in fizzbuzz:
                                                                                print(x)
                                                                            
                                                                              +2
                                                                              Отличный вариант!
                                                                              Можно даже еще больше за-однострочить (хотя из-за list() теряется преимущество генератора):
                                                                              print(list((not x%3)*'Fizz'+(not x%5)*'Buzz' or x for x in range(1,101)))
                                                                              
                                                                                +1
                                                                                Тогда уж проще «скобки поменять» ))
                                                                                [(not x % 3) * 'Fizz' + (not x % 5) * 'Buzz' or x for x in range(1, 101)]
                                                                                
                                                                              +5
                                                                              Кто сделает реализацию в 30 строк на чистом JavaScript?
                                                                                0
                                                                                for(var i=1; i<101; i++){if ((!(i%15))) {console.log("FizzBuzz")} else if(!(i%3)) {console.log("Fizz")} else if (!(i%5)) {console.log("Buzz")} else {console.log(i)}}
                                                                                

                                                                                Одна строка
                                                                                Проверяем на 15 потому, что если число делиться и на 3 и на 5, то оно автоматом делиться на 3*5 = 15
                                                                                  +17
                                                                                  в одну строку каждый сможет. нужно в 30.
                                                                                    +7
                                                                                    Ну, если благородный дон настаивает:
                                                                                    То не вижу, почему бы другому благородному дону не сделать это
                                                                                    var i=1;
                                                                                    var flag=true;
                                                                                    while (flag)
                                                                                    {
                                                                                      if (!(i%15))
                                                                                      {
                                                                                        console.log("FizzBuzz");
                                                                                      }
                                                                                      else
                                                                                      {
                                                                                        if (!(i%3))
                                                                                        {
                                                                                          console.log("Fizz");
                                                                                        }
                                                                                        else
                                                                                        {
                                                                                          if (!(i%5))
                                                                                          {
                                                                                            console.log("Buzz");
                                                                                          }
                                                                                          else
                                                                                          {
                                                                                            console.log(i);
                                                                                          }
                                                                                        }
                                                                                      }
                                                                                      i++;
                                                                                      if (i > 100)
                                                                                      { flag = false}
                                                                                    }
                                                                                    

                                                                                      +6
                                                                                      Совсем другое дело! =)
                                                                                    +3
                                                                                    А еще
                                                                                    golang
                                                                                    package main
                                                                                    
                                                                                    import "fmt"
                                                                                    
                                                                                    func main() {
                                                                                    	var i int
                                                                                    	for i < 101 {
                                                                                    		flag := true
                                                                                    		if i%3 == 0 {
                                                                                    			fmt.Printf("Fizz")
                                                                                    			flag = false
                                                                                    		}
                                                                                    		if i%5 == 0 {
                                                                                    			fmt.Printf("Buzz")
                                                                                    			flag = false
                                                                                    		}
                                                                                    		if flag {
                                                                                    			fmt.Printf("%v", i)
                                                                                    		}
                                                                                    		fmt.Printf("\n")
                                                                                    		i++
                                                                                    	}
                                                                                    }
                                                                                    


                                                                                    ruby
                                                                                    puts (1..100).map{|i|  s = ""; s += "Fizz" if (i % 3 == 0);  s += "Buzz" if (i % 5 ==0); s = i.to_s if s.empty?; s; }.join(" ")
                                                                                    



                                                                                    Собственно питон
                                                                                    for i in range(1,101): print(((not i%3)*'Fizz' +(not i%5)*'Buzz') or i)
                                                                                    



                                                                                    PHP
                                                                                    <?php foreach(range(1,100) as $i){if($i%15 == 0){echo "FizzBuzz";}else{if($i%3 == 0){echo "Fizz";}else if($i%5 == 0){echo "Buzz";}else{echo $i;}};echo "\n";} ?>
                                                                                    



                                                                                    Спасибо, немного размялся
                                                                                      +4
                                                                                      Простите, но это у вас не Гоу, а Си какой-то. Гоу вот:

                                                                                      package main
                                                                                      
                                                                                      func main() {
                                                                                          for i := 0; i<101; i++ {
                                                                                              switch {
                                                                                              case i % 3 == 0:
                                                                                                  print("Fizz")
                                                                                                  fallthrough
                                                                                              case i % 5 == 0:
                                                                                                  print("Buzz")
                                                                                              default:
                                                                                                  print(i)
                                                                                              }
                                                                                              print("\n")
                                                                                          }
                                                                                      }
                                                                                      
                                                                                        0
                                                                                        Да, только про FizzBuzz забыли.
                                                                                          +8
                                                                                          fallthrough
                                                                                            +3
                                                                                            Ох, тонко. Извините.
                                                                                          +2
                                                                                          Снимаю шляпу
                                                                                        +1
                                                                                        for(var i = 1, s = ''; i < 101; i++) (s = (i % 3 ? '' : 'Fizz') + (i % 5 ? '' : 'Buzz')) && console.log(s);
                                                                                      +5
                                                                                      А как насчет Scala Пайтона:

                                                                                      from fn import F, _
                                                                                      from operator import add, mul
                                                                                      
                                                                                      # F(f, *args) means partial application
                                                                                      # same as functools.partial but returns fn.F instance
                                                                                      assert F(add, 1)(10) == 11
                                                                                      
                                                                                      # F << F means functions composition,
                                                                                      # so (F(f) << g)(x) == f(g(x))
                                                                                      f = F(add, 1) << F(mul, 100)
                                                                                      assert list(map(f, [0, 1, 2])) == [1, 101, 201]
                                                                                      assert list(map(F() << str << (_ ** 2) << (_ + 1), range(3))) == ["1", "4", "9"]
                                                                                      
                                                                                        +2
                                                                                        Так а FizzBuzz где?
                                                                                        +2
                                                                                        Сишный у вас получился какой-то несишный :)
                                                                                        Откуда в Си операторы elif?
                                                                                        Тут switch направшивается.
                                                                                          +3
                                                                                          Ну да и выделение памяти под строки. Только в Пайтоне нет ни того, ни другого :)
                                                                                            +2
                                                                                            Да-а-аааа… зарапортовался…
                                                                                            Прошу прощения, в голове каша, вы абсолютно правы.
                                                                                            Хотя switch питону всё-таки не помешал бы :)
                                                                                              +1
                                                                                              Хотя switch питону всё-таки не помешал бы :)

                                                                                              Мы уже давно это требуем :)
                                                                                          +2
                                                                                          JS Python:

                                                                                          n = 0
                                                                                          while n - 100:
                                                                                          	n = -~n
                                                                                          	print (not n % 3 and 'Fizz' or '') + (not n % 5 and 'Buzz' or '') or n
                                                                                          


                                                                                          Жаль, синтаксис не позволяет обернуть всё это в самовызывающуюся лямбду.
                                                                                            +9
                                                                                            Не нашел самой простой и быстрой реализации, она, ИМХО, должна быть такая:
                                                                                            i = 1
                                                                                            while True:
                                                                                                print i,; i += 1        # 1
                                                                                                print i,; i += 1        # 2
                                                                                                print "Fizz",; i += 1   # 3
                                                                                                print i,; i += 1        # 4
                                                                                                print "Buzz",; i += 1   # 5
                                                                                                print "Fizz",; i += 1   # 6
                                                                                                print i,; i += 1        # 7
                                                                                                print i,; i += 1        # 8
                                                                                                print "Fizz",; i += 1   # 9    
                                                                                                print "Buzz",; i += 1   # 10
                                                                                                if i > 100:
                                                                                                    break
                                                                                                print i,; i += 1        # 11
                                                                                                print "Fizz",; i += 1   # 12
                                                                                                print i,; i += 1        # 13
                                                                                                print i,; i += 1        # 14
                                                                                                print "FizzBuzz",; i += 1   # 15
                                                                                            
                                                                                              +2
                                                                                              Раз вы используете Python 2, то должно быть while 1, не while True.
                                                                                                +4
                                                                                                Ну, вообще-то да, но мне не нравится, как «while 1» выглядит.
                                                                                                +2
                                                                                                Про простую Вы пошутили?
                                                                                                Я всегда считал, что «просто» — это когда человек, не знающий языка, все равно поймет, что происходит.
                                                                                                  +1
                                                                                                  Пардон, а что непонятно? Трудно догадаться, какая исходно была поставлена задача из текста программы? Возможно. Это же фактически таблица. Реализация-то простая и легко можно реализовать любую логику. А поставленную задачу при такой реализации, думаю нужно писать в комментах. Как раз тот случай, когда комменты уместны.
                                                                                                    +1
                                                                                                    Ну лично мне не ясен смысл рядом стоящих ,;
                                                                                                    И поскольку Вы пишнте инкремент в одной строчке с выводом, не совсем ясно, является ли точка с запятой разделителем или ",;" — это оператор отдельный.

                                                                                                    А насчет комментариев согласен, но стоило хотя бы сверху написать, что все выводится группами по 15, тогда бы подобных сомнений не возникло.

                                                                                                    Разумеется, я понял смысл кода, но, каюсь, не без труда
                                                                                                      +3
                                                                                                      А, запятая! :) Пардон, нужно было при печати убрать. Она для смысла не имеет значения. Моя вина.
                                                                                                      Это для того, чтобы print не добавлял при печати перевод строки, и печатал подряд а не столбиком. Я проверял в ipython notebook и хотел, чтобы было видно сразу все 100 выводов, а если столбиком печатать, влезает мало.
                                                                                                      Точка с запятой это разделитель.
                                                                                                      Еще раз извиняюсь.
                                                                                                    +4
                                                                                                    Насчет реализаций, я б сделал с помощью массива:
                                                                                                    a = [i for i in range(101)]  # лишний элемент для удобства 
                                                                                                    for i in range(3, 100, 3):
                                                                                                        a[i] = "Fizz"
                                                                                                    
                                                                                                    for i in range(5, 101, 5):
                                                                                                        a[i] = "Buzz"
                                                                                                    
                                                                                                    for i in range(15, 101, 15):
                                                                                                        a[i] = "FizzBuzz"
                                                                                                    
                                                                                                    a.pop(0)
                                                                                                    print(*a)
                                                                                                    

                                                                                                    +1
                                                                                                    Или такая. Это правда не пайтон, а REXX, но тоже без выяснения остатка от деления. Оно-же, с нормальной подсветкой на pastebin.com
                                                                                                    /* REXX */
                                                                                                    collector3 = 3
                                                                                                    collector5 = 5
                                                                                                    fizz.  = 0
                                                                                                    buzz.  = 0
                                                                                                    fizz.3 = collector3
                                                                                                    buzz.5 = collector5
                                                                                                    
                                                                                                    DO count=1 TO 100
                                                                                                     SELECT
                                                                                                            WHEN count = fizz.count & count = buzz.count THEN
                                                                                                                 DO
                                                                                                                  say 'FizzBuzz'
                                                                                                                  collector3 = collector3 + 3
                                                                                                                  collector5 = collector5 + 5
                                                                                                                  fizz.collector3 = collector3
                                                                                                                  buzz.collector5 = collector5
                                                                                                                 END
                                                                                                            WHEN count = fizz.count THEN
                                                                                                                 DO
                                                                                                                  say 'Fizz'
                                                                                                                  collector3 = collector3 + 3
                                                                                                                  fizz.collector3 = collector3
                                                                                                                 END
                                                                                                            WHEN count = buzz.count THEN
                                                                                                                 DO
                                                                                                                  say 'Buzz'
                                                                                                                  collector5 = collector5 + 5
                                                                                                                  buzz.collector5 = collector5
                                                                                                                 END
                                                                                                     OTHERWISE
                                                                                                      say count
                                                                                                     END
                                                                                                    END
                                                                                                    
                                                                                                    –4
                                                                                                    Вчера неплохую команду узнал для Bash'а

                                                                                                    :~$ factor 105
                                                                                                    105: 3 5 7
                                                                                                    
                                                                                                      +2
                                                                                                      Это не команда Баша.
                                                                                                        +1
                                                                                                        Может не Баш, но точно линукс.
                                                                                                          +3
                                                                                                          С Линуксом я не спорил. Я написал, что это не команда Баша.
                                                                                                      +2
                                                                                                      Немного олдскульного ABAPа:
                                                                                                      OldSchool ABAP FizzBuzz
                                                                                                      *&---------------------------------------------------------------------*
                                                                                                      *& Report  ZFIZZBUZZ
                                                                                                      *&
                                                                                                      *&---------------------------------------------------------------------*
                                                                                                      *&
                                                                                                      *&
                                                                                                      *&---------------------------------------------------------------------*
                                                                                                      
                                                                                                      REPORT  zfizzbuzz.
                                                                                                      
                                                                                                      DATA: lv_text TYPE string.
                                                                                                      DO 100 TIMES.
                                                                                                        PERFORM fizzbuzz USING sy-index
                                                                                                                         CHANGING lv_text.
                                                                                                      
                                                                                                        WRITE / lv_text.
                                                                                                      ENDDO.
                                                                                                      
                                                                                                      *&---------------------------------------------------------------------*
                                                                                                      *&      Form  fizzbuzz
                                                                                                      *&---------------------------------------------------------------------*
                                                                                                      *       text
                                                                                                      *----------------------------------------------------------------------*
                                                                                                      *      -->IV_INDEX   text
                                                                                                      *      -->CV_TEXT    text
                                                                                                      *----------------------------------------------------------------------*
                                                                                                      FORM fizzbuzz USING    iv_index
                                                                                                                    CHANGING cv_text.
                                                                                                        DATA lv_rem TYPE i.
                                                                                                        CLEAR cv_text.
                                                                                                      
                                                                                                        COMPUTE lv_rem = iv_index mod 3.
                                                                                                        IF lv_rem EQ 0.
                                                                                                          COMPUTE cv_text = 'Fizz'.
                                                                                                        ENDIF.
                                                                                                      
                                                                                                        COMPUTE lv_rem = iv_index mod 5.
                                                                                                        IF lv_rem EQ 0.
                                                                                                          CONCATENATE cv_text 'Buzz' INTO cv_text.
                                                                                                        ENDIF.
                                                                                                      
                                                                                                        IF cv_text EQ ''.
                                                                                                          COMPUTE  cv_text = iv_index.
                                                                                                        ENDIF.
                                                                                                      
                                                                                                      ENDFORM.                                         "fizzbuzz
                                                                                                      

                                                                                                        +1
                                                                                                        Вы меня переплюнули по олдскульности. REXX конечно появился чуть раньше, но судя по википедии ABAP это такой продвинутый COBOL.
                                                                                                        +3
                                                                                                        Кстати, эта (и много других интересных задач) есть здесь: checkio.org. Осторожно, затягивает.
                                                                                                          0
                                                                                                          Подумал еще немного. Не хватает КМК, еще одного варианта, с логикой, зашитой не в код, а в данные, вот, набросал наскоро, думаю идея понятна. Думаю, это более «промышленный» вариант:
                                                                                                          MAX = 100
                                                                                                          MIN_LOGIC = 15
                                                                                                          arr_1 = [0,3,6,9,12]
                                                                                                          arr_2 = [0,5,10]
                                                                                                          logic = {(1,0):"Fizz",(0,1):"Buzz",(1,1):"FizzBuzz"}
                                                                                                          for i in range(1,MAX + 1):
                                                                                                              j = i % MIN_LOGIC
                                                                                                              var_1 = j in arr_1
                                                                                                              var_2 = j in arr_2
                                                                                                              key = (var_1,var_2)
                                                                                                              try:
                                                                                                                  out = logic[key]
                                                                                                              except KeyError:
                                                                                                                  out = i
                                                                                                              print out,
                                                                                                          

                                                                                                          Жду оценок.
                                                                                                            +1
                                                                                                            Из комментариев в личку со сторонних сайтов:

                                                                                                            Здравствуйте, Анатолий! Хотел бы прокомментировать Ваш пост:
                                                                                                            habrahabr.ru/post/218981/

                                                                                                            Конечно, самое правильное решение там уже предложили:
                                                                                                            for i in xrange(1,101): print ((not i%3)*'Fizz'+(not i%5)*'Buzz') or i


                                                                                                            Я, просто чтобы показать другой (и весьма кривой) алгоритм, извратился так:

                                                                                                            from itertools import cycle, izip, chain
                                                                                                            S = 1, 3, 5, 15
                                                                                                            W = xrange(1,101), ['Fizz'], ['Buzz'], ['FizzBuzz']
                                                                                                            print dict(chain(*(izip(xrange(s,101,s), cycle(w)) for (s,w) in izip(S,W)))).values()


                                                                                                            Мой ник на Хабре — adugin
                                                                                                              +2
                                                                                                              >number % 3 == 0 and number % 5 == 0
                                                                                                              number % 3 ==  number % 5 == 0
                                                                                                              
                                                                                                                +1
                                                                                                                Enumerable.Range(1, 100).Select(x => x%15 == 0 ? "FizzBuzz" : x%3 == 0 ? "Fizz" : x%5 == 0 ? "Buzz" : x.ToString()).ToList().ForEach(Console.WriteLine);
                                                                                                                
                                                                                                                  0
                                                                                                                  Вообще говоря, все предложенные решения могут оказаться неверными. В задаче не сказано, что нужно для каждого числа вывести только одну строчку. Для числа 15 их вполне может быть три, причем это только один из вариантов (т.к. требуемый порядок вывода в данном случае тоже неизвестен):
                                                                                                                  Fizz
                                                                                                                  Buzz
                                                                                                                  FizzBuzz
                                                                                                                    +1
                                                                                                                    Если оно делится как на 3, так и 5, выведите FizzBuzz.

                                                                                                                    Из этого следует, что для такого числа должна быть выведена только эта строка. Вполне однозначно следует, что для каждого числа выводится только одна строка. Можно придираться к формулировке, но она достаточно четкая, чтобы придирки так и остались необоснованными.
                                                                                                                      0
                                                                                                                      Не вижу, с чего бы это должно следовать. Из этого следует только, что должна быть выведена эта строка. То, что остальные не должны — вопрос открытый. Чисто интуитивно, на уровне обычной разговорной речи, я конечно склоняюсь к мысли, что все три варианта взаимоисключающие, но формально в условии этого не сказано.

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

                                                                                                                  Самое читаемое