Cześć, więc zastanawiałem się, dlaczego podczas tworzenia funkcji make_song () faktycznie działała, pomyślałem, że wersja, którą pokażę poniżej, nie będzie działać tak, jak działała:

def make_song(count = 99, beverage = "soda"):
    while count > 0:
            if count > 1:
                yield "{} bottles of {} on the wall.".format(count, beverage)
                count -=1
            elif count == 1:
                yield "Only {} bottle of {} left!".format(count, beverage)
                count -= 1
                yield "No more {}!".format(beverage)

hey = make_song(5, "coke")
print(next(hey))
print(next(hey))
print(next(hey))
print(next(hey))
print(next(hey))
print(next(hey))

Mój wniosek był taki, że kiedy count == 1 to wypisze:

Została tylko 1 butelka coli!

Nigdy więcej koksu!

Ponieważ oba znajdowały się pod tą samą instrukcją if . Ku mojemu zdziwieniu działało tak, jak chciałem, drukując tylko „Została tylko 1 butelka coli!” gdy licznik == 1, a potem, gdy użyję next () ponownie, wyświetli się „Nigdy więcej koksu!”, nie spodziewałem się, że ten zadziała,

Dlaczego nie wypisuje obu wydajności, gdy count == 1, mimo że były one objęte tym samym wyrażeniem if?

0
Juan Garcia 2 kwiecień 2020, 18:52

3 odpowiedzi

Najlepsza odpowiedź

Część kodu, która określa, kiedy generator poda coś, to yield, a nie if. if tylko określa, które wiersze są wykonywane w zależności od warunku.

W praktyce generator jest uogólnieniem funkcji. Funkcja zwraca wartość raz, podczas gdy generator zwraca tyle razy, ile zostanie osiągnięta instrukcja yield. Po każdym yield wykonanie jest zawieszane, a przy następnym wywołaniu next() wykonywanie jest wznawiane i trwa aż do znalezienia następnego yield.

Alternatywą dla wywołania next() jest użycie iteratora bezpośrednio w pętli for, która wyczerpuje wszystkie możliwe punkty końcowe yield.

Na przykład:

for s in make_song(5, "coke"):
    print(s)

Da tobie:

5 bottles of coke on the wall.
4 bottles of coke on the wall.
3 bottles of coke on the wall.
2 bottles of coke on the wall.
Only 1 bottle of coke left!
No more coke!
1
norok2 2 kwiecień 2020, 16:09

Tak jest

  • każdy yield daje wartość do zwrócenia
  • każde wywołanie next pobiera następną wartość podaną przez yield

Więc ponieważ 1 left i no more są podane przez inne yield ciebie 2 next, aby je otrzymać

1
azro 2 kwiecień 2020, 15:57

Powód, dla którego wraca "Została tylko 1 butelka coli!" przedostatni i „Nigdy więcej koksu!” ostatnia następna jest taka, że gdy wywołasz next () w metodzie, która zwraca kod, metoda będzie działać do momentu uzyskania zysku.

Powiedzmy, że liczysz się == 2:

 while count > 0:
     if count > 1:
         yield "{} bottles of {} on the wall.".format(count, beverage)

Kod sprawdza, czy count > 0 i przechodzi do następnej instrukcji count > 1, ponieważ count == 2 wchodzi do instrukcji if. Następnym wierszem jest instrukcja yield, co oznacza, że zwróci łańcuch (a wiersz count -= 1 nie zostanie wykonany aż do następnego next()).

Kiedy next zostanie ponownie wywołane, kod będzie kontynuował zmniejszanie licznika do 1, opuszcza instrukcję if i wraca do instrukcji while. Instrukcja while nadal zawiera True, count > 1 teraz jest False, dlatego przechodzi do instrukcji elif, która jest True. Pierwsza instrukcja to yield, która zwraca yield "Only 1 bottle of coke left!. Następujące next() zmniejszają liczbę i zyski No more coke!

0
Marco Aguiar 2 kwiecień 2020, 16:18