2016-01-30 12 views
5

Próbuję uzyskać wiele nazw oddzielonych przez znaki nowej linii od konsoli i umieścić je w zmiennej. Załóżmy, że chcę uzyskać dane wejściowe z terminala na zawsze (dodam kod, aby później przerwać pętlę). Wiem, jak to zrobić z pętlą while i rekurencją, ale chciałbym móc to zrobić z pętlą for.Python iteruje po linii standardowej wiersz po linii używając input()

W poniższym przykładzie, gdy dostaję "peter" jako wejścia z terminala dostaję każdą literę, a nie całej linii naraz:

for name in input(): 
    print(name) 

Teraz, jeśli mogę użyć sys.stdin zmienna name staje "peter\n":

for name in sys.stdin: 
    print(name) 

Czy istnieje łatwy sposób uzyskać input() dać "name" całą linię zamiast pojedynczych znaków? Lub po prostu z natury przy użyciu for in zamierzam być iteracyjne przez znaki w danych wejściowych? Czy istnieją jakieś nieodłączne ryzyko/problemy z uzyskaniem danych wejściowych w ten sposób? Czy istnieje "standardowy" sposób uzyskania danych wejściowych w takiej sytuacji?

Używam Python 3.5.1 na Ubuntu 15.10.

+0

'input()' zwraca ciąg znaków, który jest iterowalny, dlatego też przy próbie iteracji nad nim dostajesz po kolei każdą znak. –

+0

OK, co ma sens. input() zwraca ciąg znaków. Czy też sys.stdin zwraca bufor, który jest iterowany linia po linii? – PeterH

+0

Ponieważ sys.stdin zwraca plik podobny do obiektu, który, po iteracji przez, będzie zawierał każdą pojedynczą linię danych wejściowych. –

Odpowiedz

5

Można owinąć stdin rozebrać się nowe linie; czy można rozebrać wszystkie końcowe białe znaki (zwykle w porządku), to jest to po prostu:

for name in map(str.rstrip, sys.stdin): 
    ... 

Jesteś na Py3, dzięki czemu działa jak jest; jeśli używasz Py2, musisz dodać import, from future_builtins import map, więc otrzymasz leniwy, oparty na generatorze map (który daje linie, gdy są wymagane, zamiast sypania stdin, aż się skończy, a następnie zwraca list wszystkich linii).

Jeśli trzeba ograniczyć do nowej linii, wyrażenie generator może to zrobić:

for name in (line.rstrip("\r\n") for line in sys.stdin): 
    ... 

lub z importu umożliwienia map pchnąć prace do C warstwy dla (nieznacznie) szybsze kodu (kwestia 30 -Niektóre nanosekund na linię szybszym niż genexpr, ale nadal 40 ns na linię wolniej niż opcja argumentless w górnej części tej odpowiedzi):

from operator import methodcaller 

for name in map(methodcaller('rstrip', '\r\n'), sys.stdin): 
    ... 

Podobnie jak w przypadku pierwszego rozwiązania, na Py2, upewnij się, aby uzyskać map od future_builtins.

0

I nie można polecić, ale można stworzyć generator do wykorzystania w for pętli iterację linii wejściowej przez line:

def getlines(): 
    while True: 
     yield input() 

for name in getlines(): 
    print(name) 
    ## Remember to break out of the loop at some point 
+0

Przepraszam, jeśli byłem niejasny. Próbuję zrobić to więcej niż jeden raz, z każdym nazwiskiem oddzielonym znakiem nowej linii w terminalu. – PeterH

+0

@PeterH Zaktualizowałem swoją odpowiedź –