2013-05-10 14 views
55

Szukałem kodu, aby obrócić kursor w terminalu i znalazłem to. Zastanawiałem się, co dzieje się w kodzie. W szczególności for c in spinning_cursor(): Nigdy nie widziałem tej składni. Czy to dlatego, że zwracam jeden element z generatora na raz z yield, a to jest przypisane do c? Czy są jakieś inne przykłady tego dla x w y()?dla x w y(): jak to działa?

import sys 
import time 

def spinning_cursor(): 
    cursor='/-\|' 
    i = 0 
    while 1: 
     yield cursor[i] 
     i = (i + 1) % len(cursor) 

for c in spinning_cursor(): 
    sys.stdout.write(c) 
    sys.stdout.flush() 
    time.sleep(0.1) 
    sys.stdout.write('\b') 
+2

Inny przykład? dla i w zakresie (10): print (i) – antoyo

+0

możesz znaleźć wszystko tutaj: http://stackoverflow.com/questions/231767/the-python-yield-keyword-explained – pylover

+0

Kolejny przykład, jak wydajność działała z funkcja tutaj ... Nie potrzebuję teraz przykładu, który rozumiem. Ponadto, dzięki @pylover – Paul

Odpowiedz

38

Korzystanie yield włącza funkcję w generator. Generator jest wyspecjalizowanym typem iterator. for zawsze pętle nad iterabelami, biorąc po kolei każdy element i przypisując go do wymienionych nazw.

spinning_cursor() zwraca generator, kod wewnątrz spinning_cursor() faktycznie nie działa, dopóki nie rozpoczniesz iteracji nad generatorem. Iteracja po generatorze oznacza, że ​​kod w funkcji jest wykonywany, dopóki nie natrafi na instrukcję yield, w którym to punkcie wynik wyrażenia zostanie zwrócony jako następna wartość, a wykonanie zostanie ponownie wstrzymane.

Pętla for nie tylko, że on zadzwoni równowartość next() na generatorze, dopóki generator sygnalizuje to odbywa się poprzez podniesienie StopIteration (co zdarza się, gdy funkcja zwraca). Każdej zwróconej wartości next() przypisuje się z kolei do c.

Widać to poprzez stworzenie generatora na w wierszu Python:

>>> def spinning_cursor(): 
...  cursor='/-\|' 
...  i = 0 
...  while 1: 
...   yield cursor[i] 
...   i = (i + 1) % len(cursor) 
... 
>>> sc = spinning_cursor() 
>>> sc 
<generator object spinning_cursor at 0x107a55eb0> 
>>> next(sc) 
'/' 
>>> next(sc) 
'-' 
>>> next(sc) 
'\\' 
>>> next(sc) 
'|' 

Ten specyficzny generator nigdy nie wraca, więc StopIteration nie jest podnoszony i pętla for będzie trwać wiecznie, jeśli nie zabić skrypt.

+5

Waaaay zbyt szybko. – pcalcao

+0

Dzięki Martijn. Chodzi o to, aby wywołać funkcję i podczas jej przetwarzania wyświetlić kursor. Po zakończeniu przetwarzania jest zatrzymany. Więc nad tym popracuję. Dzięki za wspaniałą odpowiedź. – Paul

2

Funkcja spinning_cursor zwraca wartość iterowalną (generator z plonu).

for c in spinning_cursor(): 

byłaby taka sama jak

for i in [1, 2, 3, 4]: 
4

w Pythonie, instrukcji for umożliwia iteracyjne nad elementami.

Według documentation:

Pythona dla iteruje rachunku ponad elementów o dowolnej kolejności (listy lub łańcuch), w kolejności, w jakiej pojawiają się one w kolejności

Tutaj element będzie wartością zwracaną z spinning_cursor().

3

Składnia for c in spinning_cursor() to pętla for-each. Będzie iterować przez każdy element iteratora zwracany przez spinning_cursor().

Wewnątrz pętli będzie:

  1. Napisz znak na standardowe wyjście i równo tak wyświetla.
  2. Spać przez jedną dziesiątą sekundy
  3. Napisz \b, która jest interpretowana jako backspace (usuwa ostatni znak).Zauważ to dzieje się pod koniec pętli, więc nie będą zapisywane podczas pierwszej iteracji, i że podziela spłukiwania połączenie w kroku 1.

spinning_cursor() ma zamiar powrócić do generator, co nie faktycznie działa, dopóki nie rozpoczniesz iteracji. Wygląda na to, że zapętli się przez '/-\|', w kolejności, na zawsze. To tak jakby mieć nieskończoną listę do iteracji.

Ostatnim wyjściem będzie spinner ASCII. Zobaczysz te znaki (w tym samym miejscu) powtarzające się, aż zabijesz skrypt.

/ 
- 
\ 
| 
2

Wyjaśnienie Martijn Pieters jest doskonałe. Poniżej znajduje się kolejna implementacja tego samego kodu, który miałeś w pytaniu. używa itertools.cycle, aby uzyskać taki sam wynik, jak spinning_cursor. itertools zawiera doskonałe przykłady iteratorów i funkcji ułatwiających tworzenie własnych iteratorów. To może pomóc lepiej zrozumieć iteratory.

import sys, time, itertools 

for c in itertools.cycle('/-\|'): 
    sys.stdout.write(c) 
    sys.stdout.flush() 
    time.sleep(0.1) 
    sys.stdout.write('\b') 
+0

Wielkie rzeczy dziękuję. – Paul

Powiązane problemy