Python эквивалентно методам программирования C (в то время как петли)
На языке программирования C я часто делал следующее:
while ((c = getch()) != EOF) {
/* do something with c */
}
В Python я не нашел ничего подобного, так как мне не разрешено устанавливать переменные внутри оцениваемого выражения. Обычно мне приходится настраивать оцениваемое выражение дважды!
c = sys.stdin.read(1)
while not (c == EOF):
# Do something with c
c = sys.stdin.read(1)
В моих попытках найти лучший способ, я нашел способ, который требует только установки и оцениваемого выражения один раз, но это становится более уродливым...
while True:
c = sys.stdin.read(1)
if (c == EOF): break
# do stuff with c
До сих пор я применил следующий метод для некоторых из моих случаев, но это далеко не оптимально для обычных циклов...:
class ConditionalFileObjectReader:
def __init__(self,fobj, filterfunc):
self.filterfunc = filterfunc
self.fobj = fobj
def __iter__(self):
return self
def next(self):
c = self.fobj.read(1)
if self.filterfunc(c): raise StopIteration
return c
for c in ConditionalFileObjectReader(sys.stdin,lambda c: c == EOF):
print c
Все мои решения для решения простой основной проблемы программирования стали слишком сложными...
У кого-нибудь есть предложение, как это сделать надлежащим образом?
Ответы
Ответ 1
Я считаю, что вы хотите использовать функцию iter
.
for c in iter(getch, EOF):
#inner loop
Iter - очень универсальная функция. В этом случае вы говорите ему, чтобы он повторно вызывал getch
(без аргументов) в верхней части каждого цикла до тех пор, пока getch
не вернет значение счетчика, EOF.
Ответ 2
Обычно вы используете цикл for
в Python:
for c in sys.stdin.read():
# whatever
Если вы не хотите сразу буферировать весь stdin в памяти, вы также можете добавить некоторую буферизацию с меньшим буфером.
Обратите внимание, что константа EOF
не существует в Python. read()
просто вернет пустую строку, если в потоке не осталось данных.
Ответ 3
Можно записать гораздо более простой код вместо вашего ConditionalFileObjectReader, считая, что EOF, похоже, вас интересует, а не любое произвольное условие:
def readbytes(file):
while True:
c = file.read(1)
if c == '':
return
yield c
for c in readbytes(sys.stdin):
print c
Итак, у вас все еще есть "while True... break", который, кажется, является предпочтительным циклом в Python [*], но по крайней мере у вас есть только один раз, чтобы решить весь класс проблем ", как итератировать байты в файлоподобном объекте без блокировки/буферизации каждой строки", и у вас есть он в коротком цикле, который не "делает материал с помощью c" - это отдельная проблема.
Вдохновленный примером Wallacoloo с iter
, как и выше, вы можете создать нечто более общее, чем iter
:
def until(nextvalue, pred):
while True:
value = nextvalue()
if pred(value):
return
yield value
for c in until(lambda: sys.stdin.read(1), lambda x: x == ''):
print c
Я не уверен, нравится мне это или нет, но, возможно, стоит поиграть. Он пытается решить общую проблему "итерации над возвращаемыми значениями некоторой функции, пока возвращаемое значение не удовлетворяет некоторому условию".
[*] осмелюсь сказать, что питоновский эквивалент синтаксиса fancy loop на других языках?