r_min = min(itertools.chain(GetOurIter(), [gGreaterThanAny]))
if r_min is gGreaterThanAny :
print"it was empty..."
r_max = max(itertools.chain(GetOurIter(), [gLesserThanAny]))
if r_max is gLesserThanAny :
print"it was empty..."
Вот такой вопрос: требуется найти min (или max) последовательности, генерируемой функцией-генератором, что-то вроде
def foo(bar):
for i in bar:
.....
yield buzz
x = min(foo(y))
Проблема в том, что foo() может генерировать и пустую последовательность, т.е. вывалиться без единого захода в ветку содержащую yield. Поскольку min (и max) от пустой последовательности — это полный нонсенс , то в этом случае вылетаем с исключением ValueError:
ValueError: min() arg is an empty sequence
Можно конечно сделать вот так:
x = ()
try:
x = min(foo(y))
except ValueError:
pass
Но это как-то не того
Еще вариант:
def foo(bar):
for i in bar:
.....
yield buzz
yield ()
x = max(foo(y))
Пустая последовательность, сгенерированная на выходе из foo(), насколько я понимаю, меньше любой другой последовательности. Отмечу также, что в этом случае потребовалось слегка переработать алгоритм с тем, чтобы потребовалось искать не min а max (min в таком варианте, очевидно, даст нам пустую последовательность). Если алгоритм не допускает такую переработку — тем хуже для алгоритма.
А есть ли более кошерные варианты решения задачи?
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
_>Вот такой вопрос: требуется найти min (или max) последовательности, генерируемой функцией-генератором, что-то вроде
_>Проблема в том, что foo() может генерировать и пустую последовательность, т.е. вывалиться без единого захода в ветку содержащую yield. Поскольку min (и max) от пустой последовательности — это полный нонсенс , то в этом случае вылетаем с исключением ValueError:
И какой результат вы ожидаете от min от пустой последовательности? Пустой тупл?
try:
x = min(foo())
except ValueError:
x = ()
К сожалению, она поймает не только ValueError max, но и любой другой ValueError, который могла кинуть, в т.ч. и функция foo.
Здравствуйте, Temoto, Вы писали:
T>И какой результат вы ожидаете от min от пустой последовательности? Пустой тупл?
Потому и "полный нонсенс". В конкретном случае ситуация, когда генератор создает пустую последовательность должна обрабатываться особо (в примере — да, пустой кортеж). Если бы к генератору можно было применить len(), то:
gen = foo(y)
if (len(gen)):
x = min(gen)
else:
x = ()
Но это не прокатит ни разу.
T>
T>try:
T> x = min(foo())
T>except ValueError:
T> x = ()
T>
T>К сожалению, она поймает не только ValueError max, но и любой другой ValueError, который могла кинуть, в т.ч. и функция foo.
Потому и было сказано, что это не есть хорошо.
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
T>>И какой результат вы ожидаете от min от пустой последовательности? Пустой тупл? _>Потому и "полный нонсенс". В конкретном случае ситуация, когда генератор создает пустую последовательность должна обрабатываться особо (в примере — да, пустой кортеж). Если бы к генератору можно было применить len(), то:
То есть вам сначала надо определить пустой ли генератор, и обработать этот случай особо, а потом найти минимум, если он таки не пустой?
Здравствуйте, Temoto, Вы писали:
T>То есть вам сначала надо определить пустой ли генератор, и обработать этот случай особо, а потом найти минимум, если он таки не пустой?
Вообще да, как уже писал выше, функция может дать пустой генератор, а может и непустой. Если генератор пустой, то return в вызывающий код, если же нет — найти min, обработать его и затем уже return.
Что-то вроде такого:
g = foo(y)
ifg пустой:
return
else:
x = min(foo(y))
# Обработка х
...
return
Можно конечно забить на генераторы, и сделать вот так:
L = [i for i in foo(y)]
if not L :
return
else:
x = min(L)
# Обработка х
...
return
ИМХО, list comprehension добавит тормозов.
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
T>>То есть вам сначала надо определить пустой ли генератор, и обработать этот случай особо, а потом найти минимум, если он таки не пустой?
_>Вообще да, как уже писал выше, функция может дать пустой генератор, а может и непустой. Если генератор пустой, то return в вызывающий код, если же нет — найти min, обработать его и затем уже return.
_>Можно конечно забить на генераторы, и сделать вот так: _>
_>L = [i for i in foo(y)]
_>
_>ИМХО, list comprehension добавит тормозов.
Именно компрехеншон здесь не нужен. Можно просто L = list(foo(y)).
Да, в любом случае (list или list comprehension) создание нового списка займёт какое-то время и память. И, скорее всего, для вашей задачи это абсолютно приемлимо.
Но если действительно нужно непременно сохранить процессор и память, то можно сделать так:
g = foo() # запускаем генераторtry:
first = g.next()
except StopIteration:
# специальный случай - пустой итераторreturn
x = min(itertools.chain([first], g))
# обработка минимального значения
И это будет эффективнее *только если* реализация min() сама не делает list().