Python - возврат, возврат None и вообще никакого возврата

Рассмотрим три функции:

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

def my_func2():
  print "Hello World"
  return

def my_func3():
  print "Hello World"

Все они, кажется, возвращают None. Существуют ли различия между поведением возвращаемых значений этих функций? Есть ли причины отдавать предпочтение одному другому?

4 ответа

Решение

По фактическому поведению разницы нет. Они все возвращаются None и это все. Тем не менее, есть время и место для всего этого. Следующие инструкции в основном показывают, как должны использоваться различные методы (или, по крайней мере, как меня учили, что их следует использовать), но они не являются абсолютными правилами, поэтому вы можете смешивать их, если считаете нужным.

С помощью return None

Это говорит о том, что функция действительно предназначена для возврата значения для последующего использования, и в этом случае она возвращает None, Это значение None затем может быть использован в другом месте. return None никогда не используется, если нет других возможных возвращаемых значений из функции.

В следующем примере мы возвращаем person"s mother если person дано человеку. Если это не человек, мы вернемся None так как person не имеет mother (допустим, это не животное или около того).

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

Примечание: вы никогда не должны делать var = get_mother(), так как давайте предположим, что var - это словарь, и вы итерируете с помощью var.items(), это выдаст ошибку, указав, что None не имеет метода items(). Если вы намеренно вернете None, то об этом нужно надлежащим образом позаботиться в вызывающей функции.

С помощью return

Это используется по той же причине, что и break в петлях. Возвращаемое значение не имеет значения, и вы хотите выйти только из всей функции. Это очень полезно в некоторых местах, даже если вам это не нужно так часто.

Мы получили 15 prisoners и мы знаем, что у одного из них есть нож. Мы проходим через каждый prisoner один за другим, чтобы проверить, есть ли у них нож. Если мы ударим человека ножом, мы можем просто выйти из функции, потому что мы знаем, что есть только один нож, и нет причины проверять остальную часть prisoners, Если мы не найдем prisoner с ножом мы поднимаем тревогу. Это можно сделать разными способами и используя return это, вероятно, даже не лучший способ, но это просто пример, чтобы показать, как использовать return для выхода из функции.

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()

Примечание: вы никогда не должны делать var = find_prisoner_with_knife(), поскольку возвращаемое значение не предназначено для перехвата.

Использование нет return совсем

Это также вернется None, но это значение не предназначено для использования или обнаружения. Это просто означает, что функция завершилась успешно. Это в основном так же, как return в void функции на таких языках, как C++ или Java.

В следующем примере мы устанавливаем имя матери человека, а затем функция завершается после успешного завершения.

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

Примечание: вы никогда не должны делать var = set_mother(my_person, my_mother), поскольку возвращаемое значение не предназначено для перехвата.

Да, они все одинаковые.

Мы можем просмотреть интерпретированный машинный код, чтобы убедиться, что они все делают одно и то же.

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      

Как ответили другие, результат точно такой же, None возвращается во всех случаях.

Разница стилистическая, но обратите внимание, что PEP8 требует согласованного использования:

Будьте последовательны в ответах. Либо все операторы return в функции должны возвращать выражение, либо ни одно из них не должно. Если какой-либо оператор return возвращает выражение, любые операторы return, в которых не возвращено значение, должны явно указывать это как return None, а явный оператор return должен присутствовать в конце функции (если он доступен).

Да:

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)

Нет:

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/


В принципе, если вы когда-нибудь вернете не-Nonevalue в функции, это означает, что возвращаемое значение имеет смысл и предназначено для перехвата вызывающими абонентами. Итак, когда вы вернетесьNone, он также должен быть явным, чтобы передавать None в данном случае имеет значение, это одно из возможных возвращаемых значений.

Если вам вообще не нужен return, ваша функция в основном работает как процедура, а не функция, поэтому просто не включайте return заявление.

Если вы пишете функцию, подобную процедуре, и есть возможность вернуться раньше (т.е. вы уже закончили на этом этапе и вам не нужно выполнять оставшуюся функцию), вы можете использовать пустой returns сигнализировать читателю, что это всего лишь раннее завершение исполнения и None значение, возвращаемое неявно, не имеет никакого значения и не предназначено для перехвата (функция, подобная процедуре, всегда возвращает None тем не мение).

Каждый из них возвращает один и тот же синглтон None - Функциональной разницы нет.

Я думаю, что это разумно идиоматично return заявление, если вам не нужно, чтобы выйти из функции рано (в этом случае голый return является более распространенным), или вернуть что-то другое, чем None, Это также имеет смысл и кажется идиоматичным, чтобы написать return None когда он находится в функции, которая имеет другой путь, который возвращает что-то другое, чем None, Пишу return None out out - это визуальный сигнал читателю, что есть еще одна ветвь, которая возвращает что-то более интересное (и что вызывающий код, вероятно, должен будет обрабатывать оба типа возвращаемых значений).

Часто в Python, функции, которые возвращают None используются как void функции в C - их цель, как правило, работать с входными аргументами на месте (если вы не используете глобальные данные (дрожь)). возврате None обычно делает более явным, что аргументы были видоизменены. Это делает его немного более понятным, почему имеет смысл отказаться от return утверждение с точки зрения "языковых соглашений".

Тем не менее, если вы работаете в кодовой базе, в которой уже есть заранее заданные соглашения по этим вопросам, я бы определенно следовал этому примеру, чтобы помочь кодовой базе оставаться единообразной...

С точки зрения функциональности все они одинаковы, разница между ними заключается в удобочитаемости и стиле кода (что важно учитывать)

Другие вопросы по тегам