HZK
@HZK (Ritoku Sakamae)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

Python: if文単独の条件分岐について

解決したいこと

フラグによる分岐に、連続した処理を組み込めないかと考えています。if, elif, elseを試していますが、if文のみで試してみました。

発生している問題・エラー

if文だけで分岐を作り、分岐の最後に、特定の関数を紐づけました。なぜかフラグが最初からだと、その関数がループ処理されてしまいます。
理由が分からず困っております。改善策や、if文単独の条件分岐の問題点等について、教えて頂ければ助かります。

該当するソースコード

#!/usr/bin/env python
# -*- coding: utf-8 -*-
def setEvent():  
    global flag
    if flag ==1:
        print(1)
        flag =2
        setEvent()
    if flag ==2:
        print(2)
        flag = 3
        setEvent()
    if flag ==3:
        print(3)
        flag = 0
        setEvent()
    if flag ==0:
        print(0)
        main_pro()

def main_pro():
    print("main")

flag = 1
setEvent()   

出力)

1
2
3
0
main
0
main
0
main
0
main

0

2Answer

関数の再帰呼び出しが意図的なのかどうかがまず疑問ですが、それはいいとして、その呼び出しから帰ってきた後に処理が下に進むわけですが、それはおそらく意図どおりでないのでは?

下記の結果は理解できますか?

flag = 1

def f():  
    global flag
    if flag == 1:
        print(1)
        flag = 2
    if flag == 2:
        print(2)

f()

結果

1
2
1Like

Comments

  1. @HZK

    Questioner

    >その呼び出しから帰ってきた後に処理が下に進むわけですが、
    意図していない再帰であり、このご指摘で解決しました。あらためてif文並列の処理の意味を、理解致しました。
    的確な回答ありがとうございました。

@itagagakiさんの答えで解決するので、蛇足です。
再帰関数を用いるならglobal flag を使わない方が良いです。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
def setEvent(flag):  
    ##global flag##
    print(flag)
    if flag == 1:
        setEvent(2)
    if flag == 2:
        setEvent(3)
    if flag == 3:
        setEvent(0)
    if flag == 0:
        main_pro()
    return           ....蛇足

def main_pro():
    print("main")

flag = 1
setEvent(flag)

if flag == 2:
   setEvent(3)
   return    
if flag == 3:

※判定を継続するのか?
 returnして呼び出された関数へ戻るのか?
 明確な意識決定が必要です。

elif flag == 2:
   setEvent(3)
elif flag == 3:

※私は嫌いですが、常套手段としてelifでreturnを記述しない方法も有効です。

global flag宣言の理解不足より、関数のif,elif,elseが使い慣れていないように思えます。慣れるまでは、蛇足ですがreturnを記述しましょう!

ここから、更に蛇足ですみません。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
def main_pro():
    print("main")

def 関数(flag):
   if flag == 3:
       print(3)
   elif flag == 2:
       print(2)
   elif flag == 1:
       print(1)
   elif flag == 0:
       print(0)
       main_pro()
   else:
       print("Error")

def setEvent(flag):  
    関数(flag)
    if flag < 1:
        return
    setEvent(flag - 1)
    return

flag = 3
setEvent(flag)

3 2 1 0のカウントダウンの再帰関数の例です。

1Like

Comments

  1. @HZK

    Questioner

    ご指摘のとおり、global変数、if, elifについての理解が不十分でした。また、普段あまりreturnを意識したことはありませんでしたが、if文並列におけるreturnの効果を認識できました。
    その他の助言については、以下のように考えました。
    再帰関数を用いるなら、global flagは使う必要がなく、むしろ使った場合に不必要に書き換えてしまうリスクがある。それ故、globalは使わない方が良い。
    また、再帰関数を定義する場合には、1つの関数で処理するのではなく、2つの関数に分け、一つは引数の場合分けの関数、もう一つは引数の増減を処理する再帰的な関数に分けた方が良い。
    少し悩みましたが、非常に含蓄のある指摘であり、とても感謝しております。

Your answer might help someone💌