Вложенные выражения генератора в список аргументов для вызова функции python - PullRequest
1 голос
/ 25 октября 2009

Мне нравится использовать следующую идиому для объединения списков, иногда:

>>> list(itertools.chain(*[[(e, n) for e in l] for n, l in (('a', [1,2]),('b',[3,4]))]))
[(1, 'a'), (2, 'a'), (3, 'b'), (4, 'b')]

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

>>> list(itertools.chain(*(((e, n) for e in l) for n, l in (('a', [1,2]),('b',[3,4])))))
[(1, 'b'), (2, 'b'), (3, 'b'), (4, 'b')]

Здесь происходит то, что выражения внутреннего генератора передаются в качестве аргументов itertools.chain, поэтому во время их вычисления выражение внешнего генератора завершено, и n фиксируется в своем окончательном значении, 'b'. Мне интересно, думал ли кто-нибудь о способах избежать такого рода ошибок, кроме как "не делай этого".

Ответы [ 3 ]

6 голосов
/ 25 октября 2009

не будет ли более подходящим понимание вложенного списка?

>>> tt = (('a', [1,2]),('b',[3,4]))
>>> [(s, i) for i, l in tt for s in l]
[(1, 'a'), (2, 'a'), (3, 'b'), (4, 'b')]
2 голосов
/ 25 октября 2009

Ваш подход почти работает, вам просто нужно сгладить генераторы. Посмотрите, как for e in l сместился вправо

>>> list(itertools.chain((e, n) for n, l in (('a', [1,2]),('b',[3,4])) for e in l ))
[(1, 'a'), (2, 'a'), (3, 'b'), (4, 'b')]

Вот как сделать то же самое, используя itertools.product

>>> X=itertools.chain(*(itertools.product(*i[::-1]) for i in (('a', [1,2]),('b',[3,4]))))
>>> print list(X)
[(1, 'a'), (2, 'a'), (3, 'b'), (4, 'b')]

или если вам разрешено переключать кортежи вокруг

>>> X=itertools.chain(*(itertools.product(*i) for i in (([1,2],'a'),([3,4],'b'))))
>>> print list(X)
[(1, 'a'), (2, 'a'), (3, 'b'), (4, 'b')]
0 голосов
/ 25 октября 2009

Я собираюсь предложить

data = (('a', [1,2]), ('b', [3,4]))

result = []
for letter, numbers in data:
     for number in numbers:
         result.append((number, letter))

Это намного более читабельно, чем ваша семья решений. Фантазии не очень хорошая вещь.

...