2015-08-08 1 views
3

Я играю с нажатием Python (2.7, через интерпретатор iOS pythonista), чтобы сделать некоторые странные функциональные вещи. В частности, я пытаюсь реализовать однострочный fizzbuzz, используя вложенные if-else lambdas и map. Но я новичок в этом грязном трюке, и все идет не так хорошо.Вложенные if-else lambdas в python, возвращающем функциональный объект, а не значение (передавая переменную через?)

Возьмем следующий код:

alist = [1, 2, 3, 15, 5] 
claw = map(lambda x: 'Fizzbuzz' if x % 15 == 0 else lambda x: 'Fizz' if x % 3 == 0 else lambda x: 'Buzz' if x % 5 == 0 else x, alist) 
print "claw" 
print claw 
print 
claw2 = map(lambda x: 'scratch' if x == 1 else 2, alist) 
print "claw2" 
print claw2 

Этот код производит следующий вывод:

claw 
[<function <lambda> at 0x3f19fb4>, <function <lambda> at 0x36ba534>, <function <lambda> at 0x3ffa3e4>, 'Fizzbuzz', <function <lambda> at 0x3ffaa74>] 

claw2 
['scratch', 2, 2, 2, 2] 

После поиска вокруг, вполне вероятно, что проблема в коготь является то, что элементы списка не являются прошли через внутренние лямбды (на это СО: Scope of python lambda functions and their parameters). Итак, я попытался вложенности карты в тоже:

claw3 = map(lambda x: 'Fizzbuzz' if x % 15 == 0 else map(lambda x: 'Fizz' if x % 3 == 0 else map(lambda x: 'Buzz' if x % 5 == 0 else x, alist), alist), alist) 
print "claw3" 
print claw3 

Это, по крайней мере, полученные значения, но, очевидно, не совсем то, что я пытаюсь достичь:

claw3 
[[[1, 2, 3, 'Buzz', 'Buzz'], [1, 2, 3, 'Buzz', 'Buzz'], 'Fizz', 'Fizz', [1, 2, 3, 'Buzz', 'Buzz']], [[1, 2, 3, 'Buzz', 'Buzz'], [1, 2, 3, 'Buzz', 'Buzz'], 'Fizz', 'Fizz', [1, 2, 3, 'Buzz', 'Buzz']], [[1, 2, 3, 'Buzz', 'Buzz'], [1, 2, 3, 'Buzz', 'Buzz'], 'Fizz', 'Fizz', [1, 2, 3, 'Buzz', 'Buzz']], 'Fizzbuzz', [[1, 2, 3, 'Buzz', 'Buzz'], [1, 2, 3, 'Buzz', 'Buzz'], 'Fizz', 'Fizz', [1, 2, 3, 'Buzz', 'Buzz']]] 

А теперь мой мозг исчерпал , Очевидно, что повторные вызовы на карту постоянно проверяют весь список, но если нет возможности получить переменные для вложенных лямбда без него, я застрял? Я предполагаю, что может быть какое-то решение, связанное с изменением списка, например удаление элемента списка каждый раз, когда лямбда возвращает значение, но это кажется необоснованно сложным, а также полностью нефункциональным. Я так близок к однострочному функциональному fizzbuzz! У кого-нибудь есть какие-то подсказки?

EDIT: Спасибо, y'all. Для вашего коллективного развлечений/награды, некоторые полностью реализована одна линия fizzbuzzes:

https://gist.github.com/paultopia/d360116128c787e22ce8

ответ

2

Проблема заключается в том, что вы не вызывая внутренние лямбды. Выражение вроде a if b else lambda: ... просто возвращает сам лямбда (т. Е. Объект функции), если условие ложно. Вы можете получить свой результат с этим:

>>> claw = map(lambda x: 'Fizzbuzz' if x % 15 == 0 else (lambda x: 'Fizz' if x % 3 == 0 else (lambda x: 'Buzz' if x % 5 == 0 else x)(x))(x), alist) 
>>> claw 
[1, 2, 'Fizz', 'Fizzbuzz', 'Buzz'] 

Однако, вам даже не нужно делать все, что только, чтобы получить одну строку FizzBuzz. Вы можете просто прямо гнездо if/else выражения внутри друг друга в одном лямбда:

>>> claw = map(lambda x: 'Fizzbuzz' if x % 15 == 0 else 'Fizz' if x % 3 == 0 else 'Buzz' if x % 5 == 0 else x, alist) 
>>> claw 
[1, 2, 'Fizz', 'Fizzbuzz', 'Buzz'] 

И вам не нужны какие-либо лямбды вообще, вы могли бы просто список понимания:

>>> claw = ['Fizzbuzz' if x % 15 == 0 else 'Fizz' if x % 3 == 0 else 'Buzz' if x % 5 == 0 else x for x in alist] 
>>> claw 
[1, 2, 'Fizz', 'Fizzbuzz', 'Buzz'] 
1

Я считаю, что вы хотите:

claw = map(lambda x: 'fizzbuz' if x%15==0 else 'fizz' if x%3==0 else 'buzz' if x%5==0 else x, alist) 
1

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

>>> alist = [1, 2, 3, 15, 5] 
>>> claw = map(lambda x: ('Fizzbuzz' if (x % 15 == 0) else "LAMBDA_FIZZ" if (x % 3 == 0) else "LAMBDA_BUZZ" if (x % 5 == 0) else x), alist) 
>>> claw 
[1, 2, 'LAMBDA_FIZZ', 'Fizzbuzz', 'LAMBDA_BUZZ'] 

BrenBarn уже отправил ответ, который показывает способ сделать это с несколькими лямбды, но лучше способ сделать это, пока все еще используя карту и лямбда только это:

claw = map(lambda x: 'FizzBuzz' if (x % 15 == 0) else 'Fizz' if (x % 3 == 0) else 'Buzz' if (x % 5 == 0) else x, alist) 

Хотя я предпочел бы использовать список понимание, даже если вы настаиваете на использовании однострочник:

claw = ['FizzBuzz' if (x % 15 == 0) else 'Fizz' if (x % 3 == 0) else 'Buzz' if (x % 5 == 0) else x for x in alist] 

Это как бы я на самом деле сделать это:

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

claw = [fizzbuzz(x) for x in alist] 
2

Если бы я мог предложить несколько иной подход, который я бы рассмотреть более питоновски. Перечисление списков также выражает функциональные операции, но менее словесно в python. Попробуйте выполнить следующие действия:

claw = ['Fizzbuzz' if x % 15 == 0 
     else 'Fizz' if x % 3 == 0 
     else 'Buzz' if x % 5 == 0 
     else x for x in alist] 

Это делает более ясным, что происходит, на мой взгляд.

Смежные вопросы