if句を終了する方法


104

if句を途中で終了するためにどのような方法が存在しますか?

コードを書いていて、break文をif句の中に入れたい場合があります。それらはループにしか使用できないことを覚えておいてください。

例として次のコードを見てみましょう:

if some_condition:
   ...
   if condition_a:
       # do something
       # and then exit the outer if block
   ...
   if condition_b:
       # do something
       # and then exit the outer if block
   # more code here

これを行う1つの方法を考えることができます。ネストされたifステートメント内で終了ケースが発生すると想定して、残りのコードを大きなelseブロックでラップします。例:

if some_condition:
   ...
   if condition_a:
       # do something
       # and then exit the outer if block
   else:
       ...
       if condition_b:
           # do something
           # and then exit the outer if block
       else:
           # more code here

これの問題は、より多くの出口位置がより多くのネスト/インデントされたコードを意味することです。

あるいは、if節をできるだけ小さくして出口を必要としないようにコードを書くこともできます。

誰かがif句を終了するための良い/より良い方法を知っていますか?

関連するelse-ifおよびelse句がある場合、終了するとそれらがスキップされると思います。


2
2番目のコードサンプルについて、知っていますかelif
クレイグマックイーン

2
「あるいは、if句をできるだけ小さくし、exitを必要としないようにコードを書くこともできます。」-そして確かに、これは最善の行動方針でしょう。:-)
のMichałMarczyk

2
@Craig McQueen:そうですが、条件ステートメント間でコードを実行したいと言いましたか?たとえばif a: #stuff; #stuff_inbetween; if b: #stuff;、中間コードはにnot a依存しbますが、依存しません。
ローマ

こんにちは忘れないでくださいelif stackoverflow.com/a/2069680/7045119
kerbrose

回答:


99

(この方法は、ifs、複数のネストされたループ、およびbreak簡単には作成できないその他の構成要素に対して機能します。)

独自の関数でコードをラップします。の代わりにbreak、を使用してくださいreturn

例:

def some_function():
    if condition_a:
        # do something and return early
        ...
        return
    ...
    if condition_b:
        # do something else and return early
        ...
        return
    ...
    return

if outer_condition:
    ...
    some_function()
    ...

4
私はあなたのプログラマーのトリックのバッグに加えてうれしいです。私の経験では、このアプローチは、前進するgotoを使いたくなったときはいつでも機能します。(そして、単一の関数が大きくなりすぎる状況を示唆し、それに対処します)
Drew Dormann

2
理想的には両方を達成できますが、優れたコードを優れたパフォーマンスと交換する必要がある場合があります。特にPythonの使用を検討している場合は、これらの時間はまれです。つまり、関数呼び出しのオーバーヘッドについてはそれほど心配する必要はありません。
ephemient

17
古い逸話があります。「デニスリッチーは、関数呼び出しが本当にCで本当に安かったことをすべてと雑貨に告げることでモジュール性を奨励しました。誰もが小さな関数を記述してモジュール化し始めました。数年後、PDP-11では関数呼び出しが依然として高価であることがわかりました。 、そしてVAXコードはCALLS命令でその時間の50%を費やすことが多かった。デニスは私たちに嘘をついていた!しかし遅すぎた;私たちはみんな夢中になっていた...」
ephemient

1
@ephemient:おもしろい、話はもっとある?全部読みたいのですが。
ローマ

4
この引用は、The Art of Unix Programming(オンラインのfaqs.org/docs/artu)の4章から引用しています。まだ読んでいない場合は、全体を読む必要があります。
ephemient

55
以下からのgoto輸入後藤、ラベル

some_conditionの場合:
   ...
   condition_aの場合:
       #何かをする
       #その後、外側のifブロックを終了します
       後藤末
   ...
   if condition_b:
       #何かをする
       #その後、外側のifブロックを終了します
       後藤末
   #ここにコードを追加

ラベルの終わり

(実際には使用しないでください。)


35
これは面白いので+1。グーグル検索で、これがエイプリルフールのジョークモジュールであることがわかりました。
ローマ

2
私もそれにリンクしました。最初のをクリックしgotoます。
ephemient

1
これは、あらゆる種類の分岐を伴うアセンブリコードを思い出します:)
phunehehe

2
@ephemient:ああ、リンクに気づかなかった。コードの強調表示であると考えました。しかし、今、私はあなたのコードを見ていることを、私は...実在のハイライトが起こって表示されていない
ローマ

1
PHPがgotoを導入したとき、私はPython php.net/manual/en/control-structures.goto.php
Marc

25
while some_condition:
   ...
   if condition_a:
       # do something
       break
   ...
   if condition_b:
       # do something
       break
   # more code here
   break

3
ああ、ちょっと私はこのアイデアが本当に好きです。これは私の本来の欲求を正確に解決すると思います。ただし、これは良い習慣ではないというしつこい感じがあります(そのため、良いコーディングスタイルを促進するため、現在受け入れられている回答は今のところ保持します)。
ローマ

6
場合は元のままにして、全体をでラップすることができますwhile True:。必ずbreak最後にステートメントを入れてください!言語のためのDO-ながら構築体は、それを行うのは、よりidomaticです:do { code that can conditionally break out } while (false);
トーマスEding

10

例外を除いて、gotoの機能をエミュレートできます。

try:
    # blah, blah ...
    # raise MyFunkyException as soon as you want out
except MyFunkyException:
    pass

免責事項:私はあなたにこの方法で物事を行う可能性をあなたに注意を向けることを意味するだけですが、私は通常の状況下でそれを合理的であると決して保証しません。質問へのコメントで述べたように、そもそもビザンチンの条件文を回避するようにコードを構造化することがはるかに望ましいです。:-)


ハハ、私はこの創造的な解決策が好きです。私はあなたの免責事項を遵守し、そのようなファンキーなコードを使用しませんが。
ローマ

@Roman:Shmooptyの横に別のトリックを追加して喜んで-たとえ私が比較でいたずらを感じているときでも。;-)
のMichałMarczyk

8

これかもしれない?

if some_condition and condition_a:
       # do something
elif some_condition and condition_b:
           # do something
           # and then exit the outer if block
elif some_condition and not condition_b:
           # more code here
else:
     #blah
if

1
ええ、それはうまくいくかもしれません。私elifがこれを書いている間、私の心は一種の空白になっていると思います。これは、ネストされたifステートメントの間にコードを実行したい状況では機能しないと思いますが。
ローマ

これは実際には正しい答えです。人々がこれをお勧めしないのはなぜですか?:)
kerbrose

6

実際に尋ねられたことについて、私のアプローチは、これらifのを1ループのループ内に置くことです

while (True):
    if (some_condition):
        ...
        if (condition_a):
            # do something
            # and then exit the outer if block
            break
        ...
        if (condition_b):
            # do something
            # and then exit the outer if block
            break
        # more code here
    # make sure it is looped once
    break

試して:

conditions = [True,False]
some_condition = True

for condition_a in conditions:
    for condition_b in conditions:
        print("\n")
        print("with condition_a", condition_a)
        print("with condition_b", condition_b)
        while (True):
            if (some_condition):
                print("checkpoint 1")
                if (condition_a):
                    # do something
                    # and then exit the outer if block
                    print("checkpoint 2")
                    break
                print ("checkpoint 3")
                if (condition_b):
                    # do something
                    # and then exit the outer if block
                    print("checkpoint 4")
                    break
                print ("checkpoint 5")
                # more code here
            # make sure it is looped once
            break

1
正直なところ、これは最もクリーンなソリューションです。コードがいつ終了するかは非常に明確です。関数内での関数スコープについて心配する必要はなく、パフォーマンスや論理的負担はありません。
トレント

2
for _ in range(1):代わりに使用することを検討するかもしれませんwhile True:。(1)単一の反復ループの意図をよりよく伝え、(2)ループを終了する最後のbreakステートメントがない(後で偶然に削除される可能性があります)
Bernhard Kausler

3

一般的に言って、しないでください。「ifs」を入れ子にし、そこから分岐する場合、それは間違っています。

ただし、次のことが必要な場合:

if condition_a:
   def condition_a_fun():
       do_stuff()
       if we_wanna_escape:
           return
   condition_a_fun()
if condition_b:
   def condition_b_fun():
       do_more_stuff()
       if we_wanna_get_out_again:
           return
   condition_b_fun()

ifステートメントで関数を宣言する必要はありません。事前に宣言できます。)これは、後で醜いif / thenをリファクタリングする必要がないため、より良い選択です。


答えてくれてありがとう。「ループをネストする」という意味がわかりません。キーワード「break」についての私の言及を参照している場合、ループ出口の存在と比較することで、if-exitの検索を動機づけようとしているだけです。私の例が持っていたとしても、私は、あなたのコードは、問題を解決する方法がわからないだif condition_aif condition_b内部にネストif some_condition。から抜け出せるようになりたいif some_condition
ローマ

人々がifを入れ子にしてそれらを壊したい理由はおそらく彼らがそれを間違っているからではなく、多分彼らがきれいでシンプルなDRYコードを書きたいからかもしれません。単純なケースは、条件_aと条件_bの両方が満たされたときにプログラムがx()を実行する必要があり、条件_aに対してのみy()を実行し、条件_bに対してのみz()を実行する必要がある場合です。そして、コーダーはx()の複数回の書き込みを拒否します
izzulmakin

1

効果的に説明しているのはgotoステートメントであり、一般的にかなりパンニングされます。2番目の例は、はるかに理解しやすくなっています。

ただし、クリーナーは次のようになります。

if some_condition:
   ...
   if condition_a:
       your_function1()
   else:
       your_function2()

...

def your_function2():
   if condition_b:
       # do something
       # and then exit the outer if block
   else:
       # more code here

1

関数の定義に依存しない別の方法があります(小さいコードスニペットでは読みにくい場合があるため)、余分な外側のwhileループを使用しない(一目で理解できるようにコメントに特別な理解が必要になる場合があります) 、goto(...)を使用せず、最も重要なのは、入れ子を開始する必要がない場合は、アウターのインデントレベルを維持できるようにすることです。

if some_condition:
   ...
   if condition_a:
       # do something
       exit_if=True # and then exit the outer if block
if some condition and not exit_if: # if and only if exit_if wasn't set we want to execute the following code
   # keep doing something
   if condition_b:
       # do something
       exit_if=True # and then exit the outer if block
if some condition and not exit_if:
   # keep doing something

はい、これも読みやすさを再確認する必要がありますが、コードのスニペットが小さい場合、これは決して繰り返されないwhileループを追跡する必要がなく、中間のifが何であるかを理解した後、すべてを簡単に読み取ることができます1つの場所と同じインデント。

そして、それはかなり効率的でなければなりません。


0

だからここで私はあなたがコードブロックの場合は外側から抜け出そうとしていることを理解しています

if some_condition:
    ...
    if condition_a:
       # do something
       # and then exit the outer if block
       ...
    if condition_b:
       # do something
       # and then exit the outer if block
# more code here

これからの1つの方法は、外側のifブロックでfalse条件をテストして、コードブロックから暗黙的に終了し、elseブロックを使用して他のifsをネストして何か行うことです

if test_for_false:
    # Exit the code(which is the outer if code)

else:
    if condition_a:
        # Do something

    if condition_b:
        # Do something

0

追加のメソッドなしでこれを適用する唯一のものはelif、次の例のようになります

a = ['yearly', 'monthly', 'quartly', 'semiannual', 'monthly', 'quartly', 'semiannual', 'yearly']
# start the condition
if 'monthly' in b: 
    print('monthly') 
elif 'quartly' in b: 
    print('quartly') 
elif 'semiannual' in b: 
    print('semiannual') 
elif 'yearly' in b: 
    print('yearly') 
else: 
    print('final') 

-1

これを処理する別の方法を次に示します。ループを1つ使用するだけで、続行を使用できます。それは理由もなく余分な機能を持つ必要のない必要性を防ぎます。さらに、潜在的な無限whileループを排除します。

if something:
    for _ in [0]:
        # Get x
        if not x:
            continue

        # Get y
        if not y:
            continue

        # Get z
        if not z:
            continue

        # Stuff that depends on x, y, and z

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.