Я не мог найти никакого действительного примера в Интернете, где я вижу разницу между ними и почему выбирать один из них.
В чем разница между цепочкой и цепочкой. В зависимости от типа itertools?
Ответ 1
Первый принимает 0 или более аргументов, каждый из которых является итерируемым, второй - один аргумент, который, как ожидается, создаст итерируемые:
from itertools import chain
chain(list1, list2, list3)
iterables = [list1, list2, list3]
chain.from_iterable(iterables)
но iterables
могут быть любыми итераторами, которые дают итерации:
def gen_iterables():
for i in range(10):
yield range(i)
itertools.chain.from_iterable(gen_iterables())
Использование второй формы обычно удобно для удобства, но поскольку она циклически повторяется во входных итерациях, это также единственный способ связать бесконечное число конечных итераторов:
def gen_iterables():
while True:
for i in range(5, 10):
yield range(i)
chain.from_iterable(gen_iterables())
Приведенный выше пример даст вам итерацию, которая дает циклический шаблон чисел, который никогда не остановится, но никогда не будет занимать больше памяти, чем требуется для одного вызова range()
.
Ответ 2
Они делают очень похожие вещи. Для небольшого числа итераций itertools.chain(*iterables)
и itertools.chain.from_iterable(iterables)
выполняются аналогично.
Основное преимущество from_iterables
заключается в способности обрабатывать большое (потенциально бесконечное) количество итераций, поскольку все они не должны быть доступны во время вызова.
Ответ 3
Я не смог найти ни одного действительного примера... где я вижу разницу между ними [
chain
иchain.from_iterable
] и почему нужно выбирать один над другим
Принятый ответ является тщательным. Для тех, кто ищет быстрое приложение, рассмотрите сглаживание нескольких списков:
list(itertools.chain(["a", "b", "c"], ["d", "e"], ["f"]))
# ['a', 'b', 'c', 'd', 'e', 'f']
Вы можете захотеть использовать эти списки позже, поэтому вы создаете итерируемые списки:
iterable = (["a", "b", "c"], ["d", "e"], ["f"])
попытка
Тем не менее, передача итерируемой по chain
приводит к непредсказуемому результату:
list(itertools.chain(iterable))
# [['a', 'b', 'c'], ['d', 'e'], ['f']]
Зачем? Вы передали один предмет (кортеж). chain
нужен каждый список в отдельности.
Решения
По возможности вы можете распаковать итерацию:
list(itertools.chain(*iterable))
# ['a', 'b', 'c', 'd', 'e', 'f']
list(itertools.chain(*iter(iterable)))
# ['a', 'b', 'c', 'd', 'e', 'f']
В более общем случае используйте .from_iterable
(поскольку он также работает с бесконечными итераторами):
list(itertools.chain.from_iterable(iterable))
# ['a', 'b', 'c', 'd', 'e', 'f']
g = itertools.chain.from_iterable(itertools.cycle(iterable))
next(g)
# "a"
Ответ 4
Еще один способ увидеть это:
chain(iterable1, iterable2, iterable3,...)
предназначена для chain(iterable1, iterable2, iterable3,...)
когда вы уже знаете, какие у вас есть итерируемые элементы, поэтому вы можете записать их в качестве аргументов, разделенных запятыми.
chain.from_iterable(iterable)
предназначен для случаев, когда ваши итерируемые объекты (например, iterable1, iterable2, iterable3) получены из другого итерируемого элемента.