Pythonで実現!Case文代わりの7つの手法とその使い方詳解

PythonでCase文を代替する7つの手法の説明とサンプルコード Python
この記事は約15分で読めます。

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

基本的な知識があればサンプルコードを活用して機能追加、目的を達成できるように作ってあります。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を凌駕する現役のプログラマチームによって監修されています。

サイト内のコードを共有する場合は、参照元として引用して下さいますと幸いです

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

はじめに

Pythonでプログラミングをしていると、Case文がないことに困った経験はありませんか?

Pythonには他のプログラミング言語にあるようなCase文(またはSwitch文)がありませんが、それを補う様々な手法が存在します。

この記事では、PythonでCase文の代替となる7つの手法を詳しく解説します。サンプルコードとともに学んでいきましょう。

●PythonとCase文

○Case文とは

Case文(またはSwitch文)は、一連の条件に基づいてプログラムの制御フローを切り替える構造を提供する制御文です。

これは、特定の変数の値に基づいて複数の異なるアクションを実行するために使用されます。

多くのプログラミング言語、例えばJavaやC++などにはこのCase文が存在します。

○PythonでのCase文の代替手法

しかし、PythonにはCase文が存在しません。

Pythonの設計者たちは、Case文よりも単純明快なif文を優先しました。

しかし、それによりCase文のような使い方が必要な場面では工夫が必要となります。

そこで、ここではPythonでCase文のような機能を補うための7つの手法を紹介します。

●if文を使った手法

○基本的な使い方

最初の方法は、Pythonの基本的な制御文であるif文を使用する方法です。

if文は、指定した条件が真である場合に指定したコードを実行します。

複数の条件を判断する場合には、elif文を使用して、それぞれの条件に対して異なるアクションを実行することができます。

○サンプルコード1:if文を使った例

例えば、次のようなコードでif文を使ってCase文のような挙動を実現できます。

このコードでは、入力値を受け取り、それが1ならば「One」、2ならば「Two」、それ以外ならば「Other」を出力します。

value = int(input())
if value == 1:
    print('One')
elif value == 2:
    print('Two')
else:
    print('Other')

このコードを実行すると、例えば入力値に3を入力すれば、「Other」が出力されることでしょう。

これは、入力値が1でも2でもない場合に、else文内のコードが実行されるからです。

●辞書を使った手法

○基本的な使い方

次に、Pythonのデータ構造である辞書を使った手法を紹介します。

Pythonの辞書は、キーと値をペアとして保存することができます。

この特性を利用して、キーに条件、値にそれぞれの条件に対するアクションを保存することで、Case文のような挙動を実現できます。

○サンプルコード2:辞書を使った例

下記のコードでは、キーとして整数、値として文字列を持つ辞書を定義しています。

入力値に応じて辞書から値を取り出し、それを出力します。

value = int(input())
switch = {
    1: 'One',
    2: 'Two',
}
print(switch.get(value, 'Other'))

このコードを実行すれば、入力値に3を入力すれば、「Other」が出力されます。

これは、入力値が辞書のキーに存在しない場合、getメソッドの第二引数で指定したデフォルト値が返されるためです。

●関数を使った手法

○基本的な使い方

関数を使う方法もあります。

Pythonの関数は、特定の処理を行うコードの塊で、必要なときに何度でも呼び出すことができます。

これにより、異なるアクションを行うための関数をそれぞれ定義し、条件に応じて適切な関数を呼び出すことで、Case文のような制御を行うことができます。

○サンプルコード3:関数を使った例

下記のコードでは、それぞれ値を出力する関数を定義し、それらを辞書で管理しています。

入力値に応じて、適切な関数を辞書から取り出して実行します。

def print_one():
    return 'One'

def print_two():
    return 'Two'

value = int(input())
switch = {
    1: print_one,
    2: print_two,
}
func = switch.get(value, lambda: 'Other')
print(func())

このコードを実行すれば、入力値に3を入力すれば、「Other」が出力されます。

これは、入力値が辞書のキーに存在しない場合、getメソッドの第二引数で指定したデフォルト関数(ここでは匿名関数であるlambda関数)が呼び出されるためです。

●クラスを使った手法

Pythonには、クラスを使用した独自のCase文代替手法が存在します。

オブジェクト指向プログラミングの一部としてクラスを使用すると、コードの再利用性が向上し、コードが読みやすく、保守性が高まります。

それでは、基本的なクラスを使用したCase文代替手法について詳述します。

○基本的な使い方

クラスを使ったCase文代替手法では、各Caseに対応するメソッドを持つクラスを作成します。

各メソッドは、それぞれのケースの振る舞いを定義します。

そして、判定したい値に基づいて適切なメソッドを呼び出すことで、Case文のような振る舞いを模倣します。

○サンプルコード4:クラスを使った例

クラスを使用したCase文代替手法のサンプルコードを紹介します。

class Switcher(object):
    def case_1(self):
        return "この処理はCase 1に対応します"
    def case_2(self):
        return "この処理はCase 2に対応します"
    def default(self):
        return "この処理はデフォルト(それ以外のケース)に対応します"

def switch_case(case_id):
    switcher = Switcher()
    method_name = f'case_{case_id}'
    method = getattr(switcher, method_name, switcher.default)
    return method()

print(switch_case(1))  # 出力:この処理はCase 1に対応します
print(switch_case(2))  # 出力:この処理はCase 2に対応します
print(switch_case(3))  # 出力:この処理はデフォルト(それ以外のケース)に対応します

このコードではSwitcherというクラスを作成しています。

このクラスには、case_1、case_2、defaultという3つのメソッドが定義されています。

switch_case関数内では、Switcherクラスのインスタンスを作成し、case_idを元に適切なメソッドを呼び出しています。

該当するメソッドが存在しない場合、デフォルトのメソッドが呼び出されます。

このように、Pythonのgetattr関数を使って動的にメソッドを呼び出すことで、Case文のような振る舞いを実現しています。

●Lambda関数を使った手法

次に、Lambda関数を使用したCase文代替手法について説明します。

Lambda関数は、Pythonの高度な特徴の一つで、名前を持たない一時的な小さな関数を定義することができます。

これを利用して、簡潔なCase文のような振る舞いを実現することが可能です。

○基本的な使い方

Lambda関数を使ったCase文代替手法では、各Caseに対応するLambda関数を辞書に格納します。

そして、判定したい値に基づいて辞書から適切なLambda関数を取り出し、それを実行することで、Case文のような振る舞いを模倣します。

○サンプルコード5:Lambda関数を使った例

Lambda関数を使用したCase文代替手法のサンプルコードを紹介します。

case_dict = {
    1: lambda: "この処理はCase 1に対応します",
    2: lambda: "この処理はCase 2に対応します",
    'default': lambda: "この処理はデフォルト(それ以外のケース)に対応します"
}

def switch_case(case_id):
    return case_dict.get(case_id, case_dict['default'])()

print(switch_case(1))  # 出力:この処理はCase 1に対応します
print(switch_case(2))  # 出力:この処理はCase 2に対応します
print(switch_case(3))  # 出力:この処理はデフォルト(それ以外のケース)に対応します

このコードでは〇〇を使って〇〇をするコードを紹介しています。

この例では、case_dictという辞書に、各ケースに対応するLambda関数を格納しています。

そして、switch_case関数では、case_idに対応するLambda関数を辞書から取り出し、それを実行しています。

該当するLambda関数が存在しない場合、デフォルトのLambda関数が呼び出されます。

このように、Pythonの辞書とLambda関数を組み合わせることで、Case文のような振る舞いを実現しています。

●エラーハンドリングを使った手法

エラーハンドリングは通常、プログラムのエラーを管理するために使用されますが、PythonでのCase文の代替手法として活用することも可能です。

具体的には、関数内で特定の条件に合致する場合にエラーを発生させ、それを捕捉して処理を分岐させるという手法です。

○基本的な使い方

この手法の基本的な使用方法は、関数を作成し、その中で特定の条件を満たす場合にエラー(例外)を発生させるというものです。

例えば、次のようなコードが考えられます。

def handle_error(value):
    if value == "option1":
        raise ValueError("Option1")
    elif value == "option2":
        raise TypeError("Option2")
    else:
        raise Exception("Default")

try:
    handle_error("option1")
except ValueError:
    print("This is option 1.")
except TypeError:
    print("This is option 2.")
except Exception:
    print("This is the default option.")

このコードでは、まず関数handle_errorを定義しています。

この関数内で、引数valueの値に応じて異なる種類のエラーを発生させています。

その後、try-exceptブロックを使用してこれらのエラーを捕捉し、それぞれのエラーに対して異なる処理を行っています。

ここで注意すべきは、この手法はあくまでCase文の代替として、という特定の状況下での使用を前提としていることです。

一般的なエラーハンドリングの方法としては推奨されません。

○サンプルコード6:エラーハンドリングを使った例

次に、このエラーハンドリングを用いたCase文代替手法を具体的な例で見てみましょう。

def case_error(value):
    if value == "apple":
        raise ValueError("Apple")
    elif value == "banana":
        raise TypeError("Banana")
    else:
        raise Exception("Default")

try:
    case_error("apple")
except ValueError:
    print("Apple is delicious.")
except TypeError:
    print("Banana is also good.")
except Exception:
    print("I like all fruits.")

上記のコードは、関数case_error内で引数valueの値によって異なるエラーを発生させ、それぞれのエラーに対するメッセージを出力するものです。

引数に”apple”を指定した場合、ValueErrorが発生し、”Apple is delicious.”というメッセージが出力されます。

同様に、”banana”を指定した場合はTypeErrorが発生し、”Banana is also good.”というメッセージが出力されます。

それ以外の値を指定した場合は、デフォルトのExceptionが発生し、”I like all fruits.”というメッセージが出力されます。

●モジュールを使った手法

PythonでCase文の代替手法として考えられるものの一つに、モジュールを利用するという方法があります。

特定のモジュール内に各ケースに対応する関数を定義し、それを呼び出すことでCase文のような動作を再現します。

○基本的な使い方

この方法の基本的な使い方は、まず特定のモジュール内に各ケースに対応する関数を定義するところから始まります。

次に、その関数を呼び出すためのメインのスクリプトを作成します。

メインのスクリプトでは、実行したい関数名を文字列として受け取り、getattr関数を用いて該当する関数を呼び出します。

# case_module.py
def case1():
    print("This is case 1.")

def case2():
    print("This is case 2.")

def default():
    print("This is the default case.")

# main_script.py
import case_module

def handle_case(case_name):
    case_function = getattr(case_module, case_name, case_module.default)
    case_function()

handle_case("case1")
handle_case("case2")
handle_case("nonexistent_case")

上記のコードでは、case_module.pyというモジュール内にcase1case2defaultという3つの関数を定義しています。

それぞれの関数は異なるメッセージを出力します。

一方、メインのスクリプトであるmain_script.pyでは、handle_caseという関数を定義し、その中でgetattr関数を使用して各ケースに対応する関数を呼び出しています。

引数case_nameに指定した関数が存在しない場合は、デフォルトの関数を呼び出します。

○サンプルコード7:モジュールを使った例

それでは、具体的な例を見てみましょう。

ここでは、フルーツに応じて異なるメッセージを出力するプログラムを作成します。

# fruits_module.py
def apple():
    print("Apple is delicious.")

def banana():
    print("Banana is also good.")

def default():
    print("I like all fruits.")

# main_script.py
import fruits_module

def handle_fruit(fruit_name):
    fruit_function = getattr(fruits_module, fruit_name, fruits_module.default)
    fruit_function()

handle_fruit("apple")
handle_fruit("banana")
handle_fruit("grape")

上記のコードでは、fruits_module.pyというモジュール内にapplebananadefaultという3つの関数を定義しています。

それぞれの関数は異なるメッセージを出力します。一方、メインのスクリプトであるmain_script.pyでは、handle_fruitという関数を定義し、その中でgetattr関数を使用して各フルーツに対応する関数を呼び出しています。

引数fruit_nameに指定した関数が存在しない場合は、デフォルトの関数を呼び出します。

●注意点と対処法

モジュールを使ったPythonでのCase文の代替手法には、いくつかの注意点があります。

まず、前述のように関数名とケースの名前が一致する必要があります。

そのため、事前に全てのケースを列挙し、それぞれに対応する関数を定義する必要があります。

この作業は、ケースの数が多い場合には特に大変な作業となる可能性があります。

さらに、この手法では、各関数が他のスクリプトから直接参照される可能性があるため、モジュール内の関数名の衝突に注意する必要があります。

同名の関数が存在すると、意図しない関数が呼び出される可能性があります。

対処法としては、独自のモジュールを作成し、その中にケースごとの関数を定義するという方法があります。

これにより、関数名の衝突を防ぎつつ、独立したスペースで関数を管理することができます。

具体的には次のように実装します。

# my_cases.py
def case1():
    print("This is case 1.")

def case2():
    print("This is case 2.")

def default():
    print("This is the default case.")

# main_script.py
import my_cases

def handle_case(case_name):
    case_function = getattr(my_cases, case_name, my_cases.default)
    case_function()

handle_case("case1")
handle_case("case2")
handle_case("nonexistent_case")

ここでは、my_cases.pyという独自のモジュールを作成し、その中にケースに対応する関数を定義しました。

このようにすることで、関数名の衝突を防ぎつつ、独立したスペースで関数を管理することができます。

ただし、この手法も一定の制限があります。

例えば、新たなケースが追加された場合、都度対応する関数をモジュールに追加する必要があります。

また、ケースの数が増えると、モジュール内の関数が増えて管理が難しくなる可能性があります。

これらの制限を理解した上で、最適な手法を選択することが重要です。

まとめ

この記事では、PythonでCase文の代替手法としてモジュールを利用する方法を詳しく解説しました。

各ケースに対応する関数をモジュール内に定義し、それを呼び出すことでCase文のような動作を再現することができます。

しかし、関数名とケースの名前が一致する必要があり、またケースの数が多いと管理が難しくなるという制限があることも覚えておきましょう。

この手法は特定の状況下で有効であり、状況に応じて適切な手法を選択することが重要です。

PythonでCase文の代わりとなる手法を知ることで、より効率的なコーディングが可能になります。

Pythonでのプログラミングを楽しみながら、自分のスキルを磨きましょう。