Powrót i wydajność w tej samej funkcji

Co dokładnie się dzieje, gdy yield I return są używane w tej samej funkcji w Pythonie, jak ta?

def find_all(a_str, sub):
    start = 0
    while True:
        start = a_str.find(sub, start)
        if start == -1: return
        yield start
        start += len(sub) # use start += 1 to find overlapping matches
Czy to nadal generator?
Author: nekomimi, 2014-10-27

4 answers

Tak, to wciąż generator. return jest (prawie) odpowiednikiem podnoszenia StopIteration.

PEP 255 pisze:

Specyfikacja: Return

Funkcja generatora może również zawierać deklaracje zwrotne w postaci:

"return"

Zauważ, że expression_list nie jest dozwolone w poleceniach return w ciała generatora (choć oczywiście mogą pojawić się w ciała funkcji nie-generatorowych zagnieżdżonych w generatorze).

W przypadku napotkania instrukcji return, Kontrola przebiega tak, jak w każdym funkcja zwraca, wykonując odpowiednie klauzule finally (jeśli exist). Następnie pojawia się wyjątek Stopiteracji, sygnalizujący, że iterator jest wyczerpany. Wyjątek Stopiteracji jest również podniesiony, jeśli sterowanie wypływa z końca generatora bez powrotu.

Zauważ, że powrót oznacza " skończyłem i nie mam nic ciekawego do return", zarówno dla funkcji generatora, jak i nie-generatora funkcje.

Zauważ, że zwrot nie zawsze jest równoznaczny z podnoszeniem Stopiteracji: różnica polega na tym, w jaki sposób konstruuje się try/except leczony. Na przykład,

>>> def f1():
...     try:
...         return
...     except:
...        yield 1
>>> print list(f1())
[]

Ponieważ, jak w każdej funkcji, return po prostu kończy, ale

>>> def f2():
...     try:
...         raise StopIteration
...     except:
...         yield 42
>>> print list(f2())
[42]

Ponieważ Stopiteracja jest uchwycona przez gołe "except", jak każdy wyjątek.

 76
Author: NPE,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-30 16:42:51

Tak, to wciąż generator. Pusty return lub return None może być użyty do zakończenia funkcji generatora. Jest to równoznaczne z podnoszeniem StopIteration (Zobacz @ NPE ' s answer po szczegóły).

Zauważ, że w Pythonie w wersjach poprzedzających 3.3 zwracany argument nie-None jest SyntaxError.

Jak zauważył @BrenBarn w komentarzach począwszy od Pythona 3.3 wartość zwracana jest teraz przekazywana do StopIteration.

Z PEP 380:

W generatorze, twierdzenie

return value

Jest semantycznie równoważne

raise StopIteration(value)
 31
Author: Ashwini Chaudhary,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:03:07

Istnieje sposób na uzyskanie metody wydajności i zwrotu w funkcji, która pozwala zwrócić wartość lub generator.

Prawdopodobnie nie jest tak czysty, jak byś chciał, ale robi to, czego oczekujesz.

Oto przykład:

def six(how_many=None):
    if how_many is None or how_many < 1:
        return None  # returns value

    if how_many == 1:
        return 6  # returns value

    def iter_func():
        for count in range(how_many):
            yield 6
    return iter_func()  # returns generator
 11
Author: William Rusnack,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-17 20:31:33

Uwaga: nie dostajesz StopIteration wyjątku z poniższego przykładu.

def odd(max):
    n = 0
    while n < max:
        yield n
        n = n + 1
    return 'done'


for x in odd(3):
    print(x)

Pętla for łapie go. To jest jego sygnał do zatrzymania

Ale można go złapać w ten sposób:

g = odd(3)

while True:
    try:
        x = next(g)
        print(x)
    except StopIteration as e:
        print("g return value:", e.value)
        break
 0
Author: Rick,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-02-09 08:29:54