Функции генератора - это не сами генераторы, а «фабрики генераторов» - каждый раз, когда вы вызываете batch_generator(...)
, он возвращает новый генератор, готовый к повторному запуску. IOW, вы хотите:
gen = batch_generator(...)
for batch in gen:
do_something_with(batch)
Также:
1 / то, как вы написали свою функцию генератора, создаст бесконечный генератор - внешний цикл while будет повторяться вечно - что может быть или не быть что ты ожидал (подумал, что лучше предупредить тебя).
2 / в вашем коде есть две логические ошибки: сначала вы не сбрасываете список batch_labels
, затем в последнем yield
вы получаете только batch_imgs
, который не согласуется с внутренним yield
]. FWIW, вместо того, чтобы поддерживать два списка (один для изображений и другой для меток), вам, возможно, будет лучше использовать один единственный список (img, label)
кортежей.
И последнее замечание: вам не нужно использовать range(len(lst))
для итерации по списку - цикл for
в Python имеет тип foreach
, он напрямую перебирает элементы итерируемого, то есть: [ 1115]
for path image_paths:
print(path)
работает точно так же, более читабельно и немного быстрее ...
Ну, Вы могли обоснованно легко записать дополнительный метод, чтобы сделать это. Что-то вроде этого (только протестированный очень немного):
public static T[,] ToRectangularArray<T>(this IEnumerable<T[]> source)
{
if (!source.Any())
{
return new T[0,0];
}
int width = source.First().Length;
if (source.Any(array => array.Length != width))
{
throw new ArgumentException("All elements must have the same length");
}
T[,] ret = new T[source.Count(), width];
int row = 0;
foreach (T[] array in source)
{
for (int col=0; col < width; col++)
{
ret[row, col] = array[col];
}
row++;
}
return ret;
}
Это - небольшой позор, что вышеупомянутый код использует T [] как тип элемента. Из-за универсальной инвариантности я не могу в настоящее время делать источник IEnumerable<IEnumerable<T>>
который был бы хорош. Альтернатива могла бы быть должна начать новый параметр типа с ограничения:
public static T[,] ToRectangularArray<T,U>(this IEnumerable<U> source)
where U : IEnumerable<T>
Несколько волосатый, но это должно работать. (Очевидно, для реализации нужны некоторые изменения также, но основной принцип является тем же.)
Единственный способ сделать это состоял бы в том, чтобы реализовать ToArray()
функция самостоятельно. Вы могли реализовать его в своем собственном наборе (т.е. StringTupleCollection
). Это могло работать то же как ArrayList
(т.е. внутренний массив, увеличивающийся в размере по мере необходимости).
Однако я не уверен преимущество [x,2]
[x][2]
(или даже List<string[2]>
было бы достаточно значительным для гарантирования усилия.
Вы могли также записать a StringTupple
класс как:
public class StringTupple : KeyValuePair<string, string>
{
}
Это не возможно с a List<string[]>
, как тип string[,]
отличается от string[]
.