486

次の3つの関数について考えてみます。

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

def my_func2():
  print "Hello World"
  return

def my_func3():
  print "Hello World"

それらはすべてNoneを返すように見えます。これらの関数の戻り値の動作に違いはありますか?どちらか一方を好む理由はありますか?

4

5 に答える 5

651

実際の動作では、違いはありません。彼ら全員が戻っNoneてきて、それだけです。しかし、これらすべてのための時間と場所があります。次の手順は、基本的にさまざまな方法の使用方法(または、少なくとも私が教えられた方法)ですが、絶対的なルールではないため、必要に応じてそれらを混同することができます。

使用するreturn None

これは、関数が実際に後で使用するために値を返すことを意図しており、この場合はを返すことを示していますNone。この値Noneは、他の場所で使用できます。return None関数から他に可能な戻り値がない場合は使用されません。

次の例では、与えられたものが人間の場合はperson'sを返します。人間でない場合は、がないので戻ってきます(動物などではないとしましょう)。motherpersonNonepersonmother

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

使用するreturn

breakこれは、ループの場合と同じ理由で使用されます。戻り値は重要ではなく、関数全体を終了したいだけです。それほど頻繁には必要ありませんが、場所によっては非常に便利です。

私たちは15を持ってprisonersいます、そして私たちはそれらの1つがナイフを持っていることを知っています。それぞれを1つずつループしprisonerて、ナイフがあるかどうかを確認します。ナイフで人を殴った場合、ナイフが1つしかないことがわかっているので、関数を終了できます。残りの部分をチェックする理由はありません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ますが、その値は使用またはキャッチされることを意図していません。これは単に、関数が正常に終了したことを意味します。基本的には、C++やJavaなどの言語の関数returnと同じです。void

次の例では、人の母親の名前を設定し、正常に完了した後に関数を終了します。

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

注:var = set_mother(my_person, my_mother)戻り値はキャッチされることを意図していないため、絶対に実行しないでください。

于 2013-03-08T18:19:21.737 に答える
45

はい、それらはすべて同じです。

解釈されたマシン コードを調べて、それらがすべてまったく同じことを行っていることを確認できます。

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      
于 2013-03-08T18:23:10.773 に答える
21

それらはそれぞれ同じシングルトンを返しますNone-- 機能的な違いはありません。

関数を早期に中断するreturn必要がない限り (この場合は裸returnがより一般的です)、またはNone. return None以外の何かを返す別のパスを持つ関数内にある場合にも、それを書くのは理にかなっていて、慣用的なようですNone。明示return None的に書き出すことは、より興味深いものを返す別のブランチがあることを読者に視覚的に示しています (そして、呼び出しコードはおそらく両方のタイプの戻り値を処理する必要があるでしょう)。

多くの場合、Python では、返される関数は C の関数のNoneように使用されます。その目的は、通常、入力引数適切に操作することです (グローバル データ (震え) を使用している場合を除きます)。戻ると、通常、引数が変更されたことがより明確になります。これにより、「言語規則」の観点からこのステートメントを省略することが理にかなっている理由が少し明確になります。voidNonereturn

とは言うものの、これらのことに関して既に事前に設定された規則があるコードベースで作業している場合、コードベースが統一されたままになるのを助けるために、私は間違いなくそれに続きます...

于 2013-03-08T18:13:33.033 に答える
11

他の人が答えたように、結果はまったく同じで、Noneすべての場合に返されます。

違いは文体ですが、PEP8では一貫した使用が要求されることに注意してください。

return ステートメントに一貫性を持たせます。関数内のすべての 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/#programming-recommendations


基本的にNone、関数で値以外を返す場合、それは戻り値に意味があり、呼び出し元によってキャッチされることを意味します。したがって、 を返すときも明示的である必要があります。この場合に意味があることNoneを伝えるには、可能な戻り値の 1 つです。None

return がまったく必要ない場合、関数は基本的に関数ではなくプロシージャとして機能するため、returnステートメントを含めないでください。

プロシージャのような関数を書いていて、もっと早く戻る機会がある場合 (つまり、その時点ですでに完了しており、残りの関数を実行する必要がない場合)、空のreturns を使用してリーダーに通知することができます。これは実行の早期終了にすぎず、None暗黙的に返された値には意味がなく、キャッチされることを意図していません (プロシージャのような関数はNoneとにかく常に返されます)。

于 2019-12-04T23:36:46.743 に答える