Вернуть, вернуть нет, и нет возврата вообще?

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

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

def my_func2():
  print "Hello World"
  return

def my_func3():
  print "Hello World"

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

Ответ 1

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

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

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

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

def get_mother(person):
    if is_human(person):
        return person.mother
    else:
        return 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), так как возвращаемое значение не предназначено для перехвата.

Ответ 2

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

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

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      

Ответ 3

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

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

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

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

Ответ 4

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