zwrot, zwrot brak, i nie ma powrotu w ogóle?

Rozważmy trzy funkcje:

def my_func1():
  print "Hello World"
  return None

def my_func2():
  print "Hello World"
  return

def my_func3():
  print "Hello World"

Wszystkie wydają się nie zwracać żadnych. Czy są jakieś różnice między zachowaniem zwracanej wartości tych funkcji? Czy są jakieś powody, by preferować jedno z drugim?

Author: HashRocketSyntax, 2013-03-08

5 answers

W rzeczywistym zachowaniu, nie ma różnicy. Wszyscy wracają None i tyle. Jednak jest na to czas i miejsce. Poniższe instrukcje są w zasadzie jak różne metody powinny być używane( lub przynajmniej jak zostałem nauczony, że powinny być używane), ale nie są to bezwzględne zasady, więc możesz je mieszać, jeśli uważasz, że jest to konieczne.

Używanie return None

To mówi, że funkcja rzeczywiście ma zwracać wartość do późniejszego użycia, a w tym przypadku zwraca None. Wartość None może być użyta gdzie indziej. return None nie jest nigdy używane, jeśli nie ma innych możliwych wartości zwracanych z funkcji.

W poniższym przykładzie zwracamy person's mother Jeśli person jest człowiekiem. Jeśli nie jest to człowiek, zwracamy None, Ponieważ person nie ma mother (Załóżmy, że nie jest to zwierzę lub coś).

def get_mother(person):
    if is_human(person):
        return person.mother
    else:
        return None

Za Pomocą return

Jest to używane z tego samego powodu co break w pętlach. Wartość zwracana nie ma znaczenia i chcesz tylko zamknąć całą funkcję. Jest to niezwykle przydatne w niektórych miejscach, mimo że nie potrzebujesz go tak często.

Mamy 15 prisoners i wiemy, że jeden z nich ma nóż. Przechodzimy przez każdy prisoner jeden po drugim, aby sprawdzić, czy mają nóż. Jeśli uderzymy osobę nożem, możemy po prostu wyjść z funkcji, ponieważ wiemy, że jest tylko jeden nóż i nie ma powodu, aby sprawdzić resztę prisoners. Jeśli nie znajdziemy prisoner z nożem, ogłosimy alarm. Można to zrobić w wielu różne sposoby i używanie return prawdopodobnie nie jest nawet najlepszym sposobem, ale jest to tylko przykład, aby pokazać, jak używać return do wyjścia z funkcji.

def find_prisoner_with_knife(prisoners):
    for prisoner in prisoners:
        if "knife" in prisoner.items:
            prisoner.move_to_inquisition()
            return # no need to check rest of the prisoners nor raise an alert
    raise_alert()

Uwaga: nigdy nie powinieneś tego robić var = find_prisoner_with_knife(), ponieważ wartość zwracana nie jest przeznaczona do przechwytywania.

Użycie nie return w ogóle

Zwróci również None, ale ta wartość nie jest przeznaczona do użycia ani przechwycenia. Oznacza to po prostu, że funkcja zakończyła się pomyślnie. Jest to w zasadzie to samo co return w void funkcje w językach takich jak C++ czy Java.

W poniższym przykładzie ustawiamy imię matki osoby, a następnie funkcja kończy się po pomyślnym zakończeniu.

def set_mother(person, mother):
    if is_human(person):
        person.mother = mother

Uwaga: nigdy nie powinieneś tego robić var = set_mother(my_person, my_mother), ponieważ wartość zwracana nie jest przeznaczona do przechwytywania.

 565
Author: jshd,
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
2019-11-18 11:26:25

Tak, wszystkie są takie same.

Możemy przejrzeć zinterpretowany kod maszynowy, aby potwierdzić, że wszyscy robią dokładnie to samo.

import dis

def f1():
  print "Hello World"
  return None

def f2():
  print "Hello World"
  return

def f3():
  print "Hello World"

dis.dis(f1)
    4   0 LOAD_CONST    1 ('Hello World')
        3 PRINT_ITEM
        4 PRINT_NEWLINE

    5   5 LOAD_CONST    0 (None)
        8 RETURN_VALUE

dis.dis(f2)
    9   0 LOAD_CONST    1 ('Hello World')
        3 PRINT_ITEM
        4 PRINT_NEWLINE

    10  5 LOAD_CONST    0 (None)
        8 RETURN_VALUE

dis.dis(f3)
    14  0 LOAD_CONST    1 ('Hello World')
        3 PRINT_ITEM
        4 PRINT_NEWLINE            
        5 LOAD_CONST    0 (None)
        8 RETURN_VALUE      
 37
Author: David Marx,
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
2013-03-08 18:36:09

Każdy zwraca ten sam singleton None - nie ma różnicy funkcjonalnej.

Myślę, że rozsądnie idiomatycznym jest opuszczenie return, chyba że potrzebujesz go, aby wcześniej wyłączyć funkcję (w tym przypadku nagie return jest bardziej powszechne), lub zwrócenie czegoś innego niż None. Zapis return None ma również sens i wydaje się idiomatyczny, gdy jest w funkcji, która ma inną ścieżkę, która zwraca coś innego niż None. Wypisanie return None jawnie jest wizualny sygnał do czytnika, że jest inna gałąź, która zwraca coś ciekawszego (i że kod wywołujący prawdopodobnie będzie musiał obsłużyć oba typy zwracanych wartości).

Często w Pythonie funkcje zwracające None są używane jak void funkcje w C - ich celem jest generalnie operowanie na argumentach wejściowych zamiast (chyba że używasz danych globalnych ( shudders)). Zwracanie None Zwykle uwidacznia, że argumenty zostały zmutowane. To sprawia, że jest trochę bardziej jasne, dlaczego ma sens pomijanie return z punktu widzenia "konwencji językowych".

To powiedziawszy, jeśli pracujesz w bazie kodu, która ma już wstępnie ustawione konwencje wokół tych rzeczy, zdecydowanie zastosowałbym się do tego, aby pomóc bazie kodu pozostać jednolitym...

 20
Author: mgilson,
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-09 02:24:34

Jak inni odpowiedzieli, wynik jest dokładnie taki sam, None jest zwracany we wszystkich przypadkach.

Różnica jest stylistyczna, ale proszę zauważyć, że PEP8 wymaga, aby użycie było spójne:

Bądź spójny w wyrażeniach zwrotnych. Albo wszystkie polecenia return w funkcja powinna zwracać wyrażenie lub żadne z nich nie powinno. Jeśli w ogóle Instrukcja return zwraca wyrażenie, każde polecenie return, gdzie nie zwracana wartość powinna być jawnie podać jako return None, oraz jawne polecenie return powinno być obecne na końcu funkcji (jeśli osiągalny).

Tak:

def foo(x):
    if x >= 0:
        return math.sqrt(x)
    else:
        return None

def bar(x):
    if x < 0:
        return None
    return math.sqrt(x)

Nie:

def foo(x):
    if x >= 0:
        return math.sqrt(x)

def bar(x):
    if x < 0:
        return
    return math.sqrt(x)

Https://www.python.org/dev/peps/pep-0008/#programming-recommendations


Zasadniczo, jeśli kiedykolwiek zwrócisz wartość nie - None w Funkcji, Oznacza to, że zwracana wartość ma znaczenie i ma zostać przechwycona przez wywołujące. Więc kiedy wrócisz None, musi być również explicit, aby przekazać None w tym przypadku ma znaczenie, jest jedną z możliwych wartości zwracanych.

Jeśli w ogóle nie potrzebujesz return, funkcja działa w zasadzie jako procedura zamiast funkcji, więc nie dołączaj instrukcji return.

Jeśli piszesz funkcję podobną do procedury i istnieje możliwość wcześniejszego powrotu (tzn. już to zrobiłeś i nie musisz wykonywać pozostałej funkcji) możesz użyć empty an returns, aby zasygnalizować reader jest to tylko wczesne zakończenie wykonania i wartość None zwracana domyślnie nie ma żadnego znaczenia i nie jest przeznaczona do przechwycenia(funkcja podobna do procedury zawsze zwraca None w każdym razie).

 9
Author: Fabiano,
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
2019-12-04 23:36:46

Pod względem funkcjonalności wszystkie są takie same, różnica między nimi polega na czytelności kodu i stylu (co należy wziąć pod uwagę)

 4
Author: Yehuda Schwartz,
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
2018-10-31 20:13:17