2D-список попался ... но здесь все в порядке, потому что повторные ссылки игнорируются ... Я думаю, это просто прекрасно.

я есть что-то, что очень похоже на понимание списка в Python, за исключением того, что оно разделяет изменяемое состояние между итерациями. Есть ли способ сделать это с пониманием списка?

def f(x):
    """ 5-bit LFSR """
    return (x >> 1) ^ (0x12*(x&1))

def batch(f, x, n):
    result = [x]
    for _ in xrange(1,n):
        x = f(x)
        result.append(x)
    return result

batch(f, 1, 5)

который возвращается[1, 18, 9, 22, 11], Здесь важно то, чтоbatch функция, а неf(x) который здесь просто простой пример, чтобы проиллюстрировать проблему.

В качестве альтернативы я мог бы реализовать с помощью генератора:

def batch(f, x, n):
    yield x
    for _ in xrange(1,n):
        x = f(x)
        yield x

list(batch(f, 1, 5))

Но пахнет немного неловко. Я ищу что-то вроде этого ...

batch = [??? for _ in xrange(n)]
 Jason S13 дек. 2017 г., 23:39
нет, но монады с состоянием
 juanpa.arrivillaga13 дек. 2017 г., 23:29
«кроме того, что он разделяет изменяемое состояние между итерациями. Есть ли способ сделать это с помощью понимания списка», может быть какой-то хакерский способ, но если он задействует изменяющееся состояние, то, вероятно,не должно быть списка-понимания
 Jason S13 дек. 2017 г., 23:23
это пахнет подозрительно, как если бы я только мог это понять, одна из тех надоедливых монад Хаскелла была бы полезна.
 Mad Physicist13 дек. 2017 г., 23:40
Вы можете определить рекурсивный генератор, используяyield from.
 juanpa.arrivillaga13 дек. 2017 г., 23:32
Кроме того, «разделение изменяемого состояния между итерациями» в Haskell не похоже ни на что.

Ответы на вопрос(3)

Вымог сделать это в одной строке, используя, например,reduce (или жеfunctools.reduce в Python 3):

>>> f = lambda x: (x >> 1) ^ (0x12*(x&1))
>>> x, n = 1, 5
>>> functools.reduce(lambda lst, _: lst + [f(lst[-1])], range(1, n), [x])
[1, 18, 9, 22, 11]

Но это не только уродливо, но и неэффективно, так как будет создавать новый список в каждой итерации. Или способом, подобным подходу Стефана, без создания промежуточных списков:

>>> functools.reduce(lambda lst, _: lst.append(f(lst[-1])) or lst, range(1, n), [x])
[1, 18, 9, 22, 11]

Или, как уже было указано в другом ответе, вы можете использоватьitertools.accumulate, что намного лучше, но все же немного неправильное использование, так как оно на самом деле ожидает двоичную функцию, тогда как здесь мы не используем ни второй параметр, ни фактическую итерацию, передаваемую в функцию, за исключением самого первого значения.

>>> list(itertools.accumulate([x] * n, lambda y, _: f(y)))
[1, 18, 9, 22, 11]
 Stefan Pochmann14 дек. 2017 г., 23:58
Ха, как насчет:reduce(lambda lst, _: lst.append(f(lst[-1])) or lst, [[x]] * n), Я на самом деле смеялся над этим ... используя общий[[x]] * n 2D-список попался ... но здесь все в порядке, потому что повторные ссылки игнорируются ... Я думаю, это просто прекрасно.
 tobias_k14 дек. 2017 г., 09:43
@StefanPochmann Хорошая точка зрения, исправлена, но это делает ее еще страшнее.
 Stefan Pochmann14 дек. 2017 г., 23:43
Заreduce Вы также можете использоватьlst.__iadd__([f(lst[-1])])хотя я предпочитаюappend+or lst (несмотря на то, что это на три символа длиннее! :-)
 user235711213 дек. 2017 г., 23:51
Хотя я думаю об использованииitertools.accumulate для того, чтобы это было некрасиво, рекуррентные отношения явно перечислены как вариант использования вaccumulate документыс примером кода.
 Stefan Pochmann14 дек. 2017 г., 11:01
@tobias_k Ну тогда сделай этопохорошела вместо этого :-). Если бы вы следовали документации, вы бы использовалиrepeat(x, n), И так как вы готовы создать список, вы можете просто использовать[x] * n.

Я ищу что-то вроде этого ...

batch = [??? for _ in xrange(n)]

Конечно, нет проблем:

>>> x = 1
>>> n = 5
>>> [prev.append(f(prev[0])) or prev.pop(0) for prev in [[x]] for _ in xrange(n)]
[1, 18, 9, 22, 11]
Примечание: это плохая идея.(Я только сделал это, потому что user2357112 сказал, что нет никакого способа)
 juanpa.arrivillaga13 дек. 2017 г., 23:45
Святой ад, это подлый.
 tobias_k13 дек. 2017 г., 23:48
Я не уверен, должен ли я повышать или понижать это ...
 user235711214 дек. 2017 г., 00:18
Хотя это, пожалуй, самая чистая, лучше всего инкапсулированная форма переменных состояния в представлении списка, которое я видел (нет утечки переменной состояния в окружающую область видимости, по крайней мере, в Python 3), есть причина, по которой я не публиковал что-то вроде этого: каждый экземпляр такого рода кода в Stack Overflow, получение голосов с повышением, увеличивает риск того, что люди сочтут подобные вещи хорошей идеей и фактически используют их в своем коде.
 Stefan Pochmann13 дек. 2017 г., 23:49
@tobias_k Так и то и другое. Но, пожалуйста, сначала.
 Stefan Pochmann14 дек. 2017 г., 00:19
@ user2357112 Лучше сейчас? :-)
Решение Вопроса

itertools.accumulate, что ближе всего к Официально Рекомендованному способу реализации рекуррентных отношений функциональным способом, но его нет в 2.7. Вы можете скопировать "примерно эквивалентную" реализацию Python издокументы если ты хочешь.

 Jason S13 дек. 2017 г., 23:40
... или просто использовать мойbatch функция. Хорошо спасибо!

Ваш ответ на вопрос