1717

入力インデックスの値に基づいて異なる固定値を返す関数を Python で作成したいと考えています。

他の言語ではswitchorcaseステートメントを使用しますが、Python にはステートメントがないようswitchです。このシナリオで推奨される Python ソリューションは何ですか?

4

44 に答える 44

1935

以下の元の回答は 2008 年に書かれました。それ以来、Python 3.10 (2021) は、Python の「スイッチ」のファースト クラスの実装を提供するmatch-ステートメントを導入しました。case例えば:

def f(x):
    match x:
        case 'a':
            return 1
        case 'b':
            return 2
        case _:        
            return 0   # 0 is the default case if x is not found

match-ステートメントは、caseこの単純な例よりもかなり強力です。


辞書を使用できます:

def f(x):
    return {
        'a': 1,
        'b': 2,
    }[x]
于 2008-09-13T00:38:24.353 に答える
1540

get(key[, default])デフォルトが必要な場合は、辞書関数を使用できます。

def f(x):
    return {
        'a': 1,
        'b': 2
    }.get(x, 9)    # 9 will be returned default if x is not found
于 2008-09-19T15:45:15.207 に答える
470

私はいつもこのようにするのが好きでした

result = {
  'a': lambda x: x * 5,
  'b': lambda x: x + 7,
  'c': lambda x: x - 2
}[value](x)

ここから

于 2008-09-13T00:41:46.123 に答える
441

ディクショナリ メソッド (私はとても気に入っています) に加えて、if- elif-を使用して/ /機能elseを取得することもできます。switchcasedefault

if x == 'a':
    # Do the thing
elif x == 'b':
    # Do the other thing
if x in 'bc':
    # Fall-through by not using elif, but now the default case includes case 'a'!
elif x in 'xyz':
    # Do yet another thing
else:
    # Do the default

もちろん、これは switch/case と同じではありません。ステートメントを除外するほど簡単にフォールスルーすることはできませんbreakが、より複雑なテストを行うことはできます。ifそのフォーマットは、機能的にはそれに近いものですが、ネストされた一連のs よりも優れています。

于 2008-09-13T01:10:58.597 に答える
320

Python >= 3.10

うわー、Python 3.10+ にはmatch/case構文がswitch/case追加されました。

PEP 634 -- 構造パターンマッチング

の選択された機能match/case

1 - 一致する値:

switch/case値のマッチングは、別の言語のシンプルに似ています。

match something:
    case 1 | 2 | 3:
        # Match 1-3.

2 - 構造パターンの一致:

match something:
    case str() | bytes():  
        # Match a string like object.
    case [str(), int()]:
        # Match a `str` and an `int` sequence 
        # (`list` or a `tuple` but not a `set` or an iterator). 
    case [_, _]:
        # Match a sequence of 2 variables.
        # To prevent a common mistake, sequence patterns don’t match strings.
    case {"bandwidth": 100, "latency": 300}:
        # Match this dict. Extra keys are ignored.

3 - 変数をキャプチャする

オブジェクトを解析します。変数として保存します。

match something:
    case [name, count]
        # Match a sequence of any two objects and parse them into the two variables.
    case [x, y, *rest]:
        # Match a sequence of two or more objects, 
        # binding object #3 and on into the rest variable.
    case bytes() | str() as text:
        # Match any string like object and save it to the text variable.

キャプチャ変数は、さまざまなパターンのいずれかになる可能性があるデータ (JSON や HTML など) を解析するときに役立ちます。

キャプチャ変数は機能です。COLOR.REDただし、ドット付き定数 (例: ) のみを使用する必要があることも意味します。それ以外の場合、定数はキャプチャ変数として扱われ、上書きされます。

より多くの使用例:

match something:
    case 0 | 1 | 2:
        # Matches 0, 1 or 2 (value).
        print("Small number")
    case [] | [_]:
        # Matches an empty or single value sequence (structure).
        # Matches lists and tuples but not sets.
        print("A short sequence")
    case str() | bytes():
        # Something of `str` or `bytes` type (data type).
        print("Something string-like")
    case _:
        # Anything not matched by the above.
        print("Something else")

Python <= 3.9

switch/case の私のお気に入りの Python レシピは次のとおりです。

choices = {'a': 1, 'b': 2}
result = choices.get(key, 'default')

単純なシナリオでは短くて単純です。

11 行以上の C コードと比較してください。

// C Language version of a simple 'switch/case'.
switch( key ) 
{
    case 'a' :
        result = 1;
        break;
    case 'b' :
        result = 2;
        break;
    default :
        result = -1;
}

タプルを使用して、複数の変数を割り当てることもできます。

choices = {'a': (1, 2, 3), 'b': (4, 5, 6)}
(result1, result2, result3) = choices.get(key, ('default1', 'default2', 'default3'))
于 2015-06-17T02:25:10.860 に答える
111
class switch(object):
    value = None
    def __new__(class_, value):
        class_.value = value
        return True

def case(*args):
    return any((arg == switch.value for arg in args))

使用法:

while switch(n):
    if case(0):
        print "You typed zero."
        break
    if case(1, 4, 9):
        print "n is a perfect square."
        break
    if case(2):
        print "n is an even number."
    if case(2, 3, 5, 7):
        print "n is a prime number."
        break
    if case(6, 8):
        print "n is an even number."
        break
    print "Only single-digit numbers are allowed."
    break

テスト:

n = 2
#Result:
#n is an even number.
#n is a prime number.
n = 11
#Result:
#Only single-digit numbers are allowed.
于 2011-07-07T06:09:09.443 に答える
65

私のお気に入りは本当に素敵なレシピです。これは、特に機能において、実際の switch case ステートメントに最も近いものです。

class switch(object):
    def __init__(self, value):
        self.value = value
        self.fall = False

    def __iter__(self):
        """Return the match method once, then stop"""
        yield self.match
        raise StopIteration
    
    def match(self, *args):
        """Indicate whether or not to enter a case suite"""
        if self.fall or not args:
            return True
        elif self.value in args: # changed for v1.5, see below
            self.fall = True
            return True
        else:
            return False

次に例を示します。

# The following example is pretty much the exact use-case of a dictionary,
# but is included for its simplicity. Note that you can include statements
# in each suite.
v = 'ten'
for case in switch(v):
    if case('one'):
        print 1
        break
    if case('two'):
        print 2
        break
    if case('ten'):
        print 10
        break
    if case('eleven'):
        print 11
        break
    if case(): # default, could also just omit condition or 'if True'
        print "something else!"
        # No need to break here, it'll stop anyway

# break is used here to look as much like the real thing as possible, but
# elif is generally just as good and more concise.

# Empty suites are considered syntax errors, so intentional fall-throughs
# should contain 'pass'
c = 'z'
for case in switch(c):
    if case('a'): pass # only necessary if the rest of the suite is empty
    if case('b'): pass
    # ...
    if case('y'): pass
    if case('z'):
        print "c is lowercase!"
        break
    if case('A'): pass
    # ...
    if case('Z'):
        print "c is uppercase!"
        break
    if case(): # default
        print "I dunno what c was!"

# As suggested by Pierre Quentel, you can even expand upon the
# functionality of the classic 'case' statement by matching multiple
# cases in a single shot. This greatly benefits operations such as the
# uppercase/lowercase example above:
import string
c = 'A'
for case in switch(c):
    if case(*string.lowercase): # note the * for unpacking as arguments
        print "c is lowercase!"
        break
    if case(*string.uppercase):
        print "c is uppercase!"
        break
    if case('!', '?', '.'): # normal argument passing style also applies
        print "c is a sentence terminator!"
        break
    if case(): # default
        print "I dunno what c was!"

一部のコメントは、with foo as caseよりもむしろを使用したコンテキスト マネージャー ソリューションの方for case in fooがクリーンであり、大きな switch ステートメントの場合は、2 次ではなく 1 次の動作が良いタッチになる可能性があることを示しています。forループを使用したこの回答の価値の一部は、ブレークとフォールスルーを持つ機能です。キーワードの選択を少し試してみたい場合は、コンテキストマネージャーでもそれを取得できます。

class Switch:
    def __init__(self, value):
        self.value = value
        self._entered = False
        self._broken = False
        self._prev = None

    def __enter__(self):
        return self

    def __exit__(self, type, value, traceback):
        return False # Allows a traceback to occur

    def __call__(self, *values):
        if self._broken:
            return False
        
        if not self._entered:
            if values and self.value not in values:
                return False
            self._entered, self._prev = True, values
            return True
        
        if self._prev is None:
            self._prev = values
            return True
        
        if self._prev != values:
            self._broken = True
            return False
        
        if self._prev == values:
            self._prev = None
            return False
    
    @property
    def default(self):
        return self()

次に例を示します。

# Prints 'bar' then 'baz'.
with Switch(2) as case:
    while case(0):
        print('foo')
    while case(1, 2, 3):
        print('bar')
    while case(4, 5):
        print('baz')
        break
    while case.default:
        print('default')
        break
于 2011-07-07T06:12:47.830 に答える
64
class Switch:
    def __init__(self, value):
        self.value = value

    def __enter__(self):
        return self

    def __exit__(self, type, value, traceback):
        return False # Allows a traceback to occur

    def __call__(self, *values):
        return self.value in values


from datetime import datetime

with Switch(datetime.today().weekday()) as case:
    if case(0):
        # Basic usage of switch
        print("I hate mondays so much.")
        # Note there is no break needed here
    elif case(1,2):
        # This switch also supports multiple conditions (in one line)
        print("When is the weekend going to be here?")
    elif case(3,4):
        print("The weekend is near.")
    else:
        # Default would occur here
        print("Let's go have fun!") # Didn't use case for example purposes
于 2015-05-03T09:05:43.523 に答える
50

Twisted Python コードから学んだパターンがあります。

class SMTP:
    def lookupMethod(self, command):
        return getattr(self, 'do_' + command.upper(), None)
    def do_HELO(self, rest):
        return 'Howdy ' + rest
    def do_QUIT(self, rest):
        return 'Bye'

SMTP().lookupMethod('HELO')('foo.bar.com') # => 'Howdy foo.bar.com'
SMTP().lookupMethod('QUIT')('') # => 'Bye'

トークンをディスパッチし、拡張されたコードを実行する必要があるときはいつでも使用できます。ステート マシンでは、state_メソッドがあり、 でディスパッチされself.stateます。do_このスイッチは、基本クラスから継承して独自のメソッドを定義することで、きれいに拡張できます。多くの場合do_、基底クラスにはメソッドさえありません。

編集:それはどのように正確に使用されていますか

SMTPの場合はHELO有線で受信します。関連するコード (からtwisted/mail/smtp.py、私たちの場合に合わせて変更) は次のようになります。

class SMTP:
    # ...

    def do_UNKNOWN(self, rest):
        raise NotImplementedError, 'received unknown command'

    def state_COMMAND(self, line):
        line = line.strip()
        parts = line.split(None, 1)
        if parts:
            method = self.lookupMethod(parts[0]) or self.do_UNKNOWN
            if len(parts) == 2:
                return method(parts[1])
            else:
                return method('')
        else:
            raise SyntaxError, 'bad syntax'

SMTP().state_COMMAND('   HELO   foo.bar.com  ') # => Howdy foo.bar.com

を受け取ります' HELO foo.bar.com '(または または を'QUIT'受け取る場合もあります'RCPT TO: foo')。これは としてトークン化さparts['HELO', 'foo.bar.com']ます。実際のメソッド ルックアップ名は から取得されparts[0]ます。

(元のメソッドはstate_COMMAND、同じパターンを使用してステート マシンを実装するため、とも呼ばれますgetattr(self, 'state_' + self.mode))

于 2008-09-13T01:26:26.827 に答える
30

私はちょうどここに私の 2 セントをドロップするつもりです。Python に case/switch ステートメントがない理由は、Python が「何かを行う正しい方法は 1 つしかない」という原則に従っているからです。したがって、スイッチ/ケース機能を再作成するさまざまな方法を思い付くことができますが、これを実現する Python の方法は if/elif 構造です。すなわち、

if something:
    return "first thing"
elif somethingelse:
    return "second thing"
elif yetanotherthing:
    return "third thing"
else:
    return "default thing"

PEP 8はここでうなずくに値すると感じました。Python の美しい点の 1 つは、その単純さと優雅さです。これは主に、PEP 8 で定められた原則 (「何かを行うには正しい方法は 1 つしかない」など) に由来します。

于 2017-08-14T22:19:38.337 に答える
29

値を返すだけではなく、オブジェクトの何かを変更するメソッドを使用したいとします。ここに記載されているアプローチを使用すると、次のようになります。

result = {
  'a': obj.increment(x),
  'b': obj.decrement(x)
}.get(value, obj.default(x))

ここで、Python はディクショナリ内のすべてのメソッドを評価します。

したがって、値が「a」であっても、オブジェクトはxだけインクリメントおよびデクリメントされます。

解決:

func, args = {
  'a' : (obj.increment, (x,)),
  'b' : (obj.decrement, (x,)),
}.get(value, (obj.default, (x,)))

result = func(*args)

したがって、関数とその引数を含むリストを取得します。このように、関数ポインタと引数リストのみが返され、評価されません。'result' は、返された関数呼び出しを評価します。

于 2010-09-30T08:31:55.040 に答える
21

複雑なケースブロックがある場合は、関数辞書ルックアップテーブルの使用を検討できます...

これまでにこれを行ったことがない場合は、デバッガーにステップインして、辞書が各関数をどのように検索するかを正確に確認することをお勧めします。

注:ケース/ディクショナリ ルックアップ内で "()" を使用しないでください。ディクショナリ/ケース ブロックが作成されるときに、各関数が呼び出されます。ハッシュ スタイルのルックアップを使用して各関数を 1 回だけ呼び出したいため、これを覚えておいてください。

def first_case():
    print "first"

def second_case():
    print "second"

def third_case():
    print "third"

mycase = {
'first': first_case, #do not use ()
'second': second_case, #do not use ()
'third': third_case #do not use ()
}
myfunc = mycase['first']
myfunc()
于 2012-04-22T21:43:03.307 に答える
20

「switch」などの余分なステートメントを検索している場合は、Python を拡張する Python モジュールを作成しました。ESPYは "Enhanced Structure for Python" と呼ばれ、Python 2.x と Python 3.x の両方で使用できます。

たとえば、この場合、switch ステートメントは次のコードで実行できます。

macro switch(arg1):
    while True:
        cont=False
        val=%arg1%
        socket case(arg2):
            if val==%arg2% or cont:
                cont=True
                socket
        socket else:
            socket
        break

これは次のように使用できます。

a=3
switch(a):
    case(0):
        print("Zero")
    case(1):
        print("Smaller than 2"):
        break
    else:
        print ("greater than 1")

espy は Python で次のように翻訳します。

a=3
while True:
    cont=False
    if a==0 or cont:
        cont=True
        print ("Zero")
    if a==1 or cont:
        cont=True
        print ("Smaller than 2")
        break
    print ("greater than 1")
    break
于 2010-12-06T15:08:12.703 に答える
19

「dict as switch」のアイデアを拡張します。スイッチにデフォルト値を使用する場合:

def f(x):
    try:
        return {
            'a': 1,
            'b': 2,
        }[x]
    except KeyError:
        return 'default'
于 2008-09-19T15:37:15.053 に答える
17

一般的なスイッチ構造が見つかりました:

switch ...parameter...
case p1: v1; break;
case p2: v2; break;
default: v3;

Python では次のように表現できます。

(lambda x: v1 if p1(x) else v2 if p2(x) else v3)

またはより明確な方法でフォーマットされています:

(lambda x:
     v1 if p1(x) else
     v2 if p2(x) else
     v3)

Python バージョンはステートメントではなく、値に評価される式です。

于 2015-01-02T18:01:25.527 に答える
15

私が使用するソリューション:

ここに掲載されている 2 つのソリューションの組み合わせで、比較的読みやすく、デフォルトをサポートしています。

result = {
  'a': lambda x: x * 5,
  'b': lambda x: x + 7,
  'c': lambda x: x - 2
}.get(whatToUse, lambda x: x - 22)(value)

どこ

.get('c', lambda x: x - 22)(23)

辞書を調べて"lambda x: x - 2"、それを使用しますx=23

.get('xxx', lambda x: x - 22)(44)

dict でそれを見つけられず、デフォルトの"lambda x: x - 22"withを使用しますx=44

于 2010-06-28T01:32:33.703 に答える
12
# simple case alternative

some_value = 5.0

# this while loop block simulates a case block

# case
while True:

    # case 1
    if some_value > 5:
        print ('Greater than five')
        break

    # case 2
    if some_value == 5:
        print ('Equal to five')
        break

    # else case 3
    print ( 'Must be less than 5')
    break
于 2015-08-13T17:40:47.160 に答える
10

受け入れられた回答を読んだ後、私はかなり混乱しましたが、これですべて解決しました。

def numbers_to_strings(argument):
    switcher = {
        0: "zero",
        1: "one",
        2: "two",
    }
    return switcher.get(argument, "nothing")

このコードは次のコードに似ています。

function(argument){
    switch(argument) {
        case 0:
            return "zero";
        case 1:
            return "one";
        case 2:
            return "two";
        default:
            return "nothing";
    }
}

関数へのディクショナリ マッピングの詳細については、ソースを確認してください。

于 2017-06-14T12:39:34.030 に答える
9

Mark Biesの答えが気に入りました

変数は 2 回使用する必要があるためx、ラムダ関数をパラメーターなしに変更しました。

私は一緒に走らなければならない results[value](value)

In [2]: result = {
    ...:   'a': lambda x: 'A',
    ...:   'b': lambda x: 'B',
    ...:   'c': lambda x: 'C'
    ...: }
    ...: result['a']('a')
    ...: 
Out[2]: 'A'

In [3]: result = {
    ...:   'a': lambda : 'A',
    ...:   'b': lambda : 'B',
    ...:   'c': lambda : 'C',
    ...:   None: lambda : 'Nothing else matters'

    ...: }
    ...: result['a']()
    ...: 
Out[3]: 'A'

編集:None辞書で type を使用できることに気付きました。したがって、これはエミュレートしますswitch ; case else

于 2014-11-30T10:12:36.020 に答える
8
def f(x):
     return 1 if x == 'a' else\
            2 if x in 'bcd' else\
            0 #default

短くて読みやすく、デフォルト値があり、条件と戻り値の両方で式をサポートします。

ただし、辞書を使用したソリューションよりも効率的ではありません。たとえば、Python はデフォルト値を返す前にすべての条件をスキャンする必要があります。

于 2012-11-05T20:05:12.600 に答える
6

定義:

def switch1(value, options):
  if value in options:
    options[value]()

ケースをマップにまとめて、かなり単純な構文を使用できます。

def sample1(x):
  local = 'betty'
  switch1(x, {
    'a': lambda: print("hello"),
    'b': lambda: (
      print("goodbye," + local),
      print("!")),
    })

「ラムダ:」を取り除けるような方法でスイッチを再定義しようとし続けましたが、あきらめました。定義の微調整:

def switch(value, *maps):
  options = {}
  for m in maps:
    options.update(m)
  if value in options:
    options[value]()
  elif None in options:
    options[None]()

複数のケースを同じコードにマップし、デフォルトのオプションを提供することができました:

def sample(x):
  switch(x, {
    _: lambda: print("other") 
    for _ in 'cdef'
    }, {
    'a': lambda: print("hello"),
    'b': lambda: (
      print("goodbye,"),
      print("!")),
    None: lambda: print("I dunno")
    })

レプリケートされた各ケースは、独自のディクショナリにある必要があります。switch() は、値を検索する前に辞書を統合します。これはまだ私が望むよりも醜いですが、すべてのキーをループするのではなく、式でハッシュされたルックアップを使用するという基本的な効率があります。

于 2013-07-25T18:23:33.470 に答える
6

Python 言語のイディオムを使用して、コードをテスト可能に保つことが最善の方法だと思います。以前の回答で示したように、私は辞書を使用してPython の構造と言語を利用し、「ケース」コードをさまざまな方法で分離します。その下にクラスがありますが、モジュール、グローバル、および関数を直接使用できます。このクラスには、isolation でテストできるメソッドがあります。

必要に応じて、静的メソッドと属性で遊ぶこともできます。

class ChoiceManager:

    def __init__(self):
        self.__choice_table = \
        {
            "CHOICE1" : self.my_func1,
            "CHOICE2" : self.my_func2,
        }

    def my_func1(self, data):
        pass

    def my_func2(self, data):
        pass

    def process(self, case, data):
        return self.__choice_table[case](data)

ChoiceManager().process("CHOICE1", my_data)

「__choice_table」のキーとしてクラスも使用することで、この方法を利用することができます。このようにして、 isinstance の乱用を回避し、すべてをクリーンでテスト可能な状態に保つことができます。

ネットまたは MQ からの大量のメッセージまたはパケットを処理する必要があるとします。すべてのパケットには、独自の構造と管理コードがあります (一般的な方法で)。

上記のコードを使用すると、次のようなことが可能です。

class PacketManager:

    def __init__(self):
        self.__choice_table = \
        {
            ControlMessage : self.my_func1,
            DiagnosticMessage : self.my_func2,
        }

    def my_func1(self, data):
        # process the control message here
        pass

    def my_func2(self, data):
        # process the diagnostic message here
        pass

    def process(self, pkt):
        return self.__choice_table[pkt.__class__](pkt)

pkt = GetMyPacketFromNet()
PacketManager().process(pkt)


# isolated test or isolated usage example
def test_control_packet():
    p = ControlMessage()
    PacketManager().my_func1(p)

そのため、複雑さはコード フローに分散するのではなく、コード構造にレンダリングされます

于 2016-03-18T08:01:35.393 に答える
4

ほとんどの人が dict を使用して示しているように、いくつかのキーをいくつかのコードにマッピングすることは実際には問題ではありません。本当の秘訣は、ドロップスルー全体をエミュレートして物事を壊そうとすることです. その「機能」を使用したケースステートメントを書いたことはないと思います。これがドロップスルーです。

def case(list): reduce(lambda b, f: (b | f[0], {False:(lambda:None),True:f[1]}[b | f[0]]())[0], list, False)

case([
    (False, lambda:print(5)),
    (True, lambda:print(4))
])

私は本当にそれを単一のステートメントとして想像していました。ばかげた書式設定をご容赦いただければ幸いです。

reduce(
    initializer=False,
    function=(lambda b, f:
        ( b | f[0]
        , { False: (lambda:None)
          , True : f[1]
          }[b | f[0]]()
        )[0]
    ),
    iterable=[
        (False, lambda:print(5)),
        (True, lambda:print(4))
    ]
)

それが有効な Python コードであることを願っています。それはあなたにドロップスルーを与えるはずです。もちろん、ブールチェックは式にすることができ、それらを遅延評価したい場合は、それらすべてをラムダでラップできます。リスト内のいくつかの項目を実行した後に受け入れさせるのも難しくありません。2番目のboolがブレークまたはドロップスルーするかどうかを示すタプル(bool、bool、function)を作成するだけです。

于 2013-02-04T14:21:46.897 に答える
4

Mark Biek's answer のマイナー バリエーションとして、この重複のようなまれなケースでは、ユーザーがパックする引数を使用して遅延する関数呼び出しが多数ある場合 (そして、一連の関数をアウトオブラインで構築する価値はありません)、これの代わりに:

d = {
    "a1": lambda: a(1),
    "a2": lambda: a(2),
    "b": lambda: b("foo"),
    "c": lambda: c(),
    "z": lambda: z("bar", 25),
    }
return d[string]()

… あなたはこれを行うことができます:

d = {
    "a1": (a, 1),
    "a2": (a, 2),
    "b": (b, "foo"),
    "c": (c,)
    "z": (z, "bar", 25),
    }
func, *args = d[string]
return func(*args)

これは確かに短いですが、より読みやすいかどうかは未解決の問題です…</p>


この特定の用途のためにからlambdaに切り替える方が読みやすいかもしれません (簡潔ではありませんが) :partial

d = {
    "a1": partial(a, 1),
    "a2": partial(a, 2),
    "b": partial(b, "foo"),
    "c": c,
    "z": partial(z, "bar", 25),
    }
return d[string]()

…これには、キーワード引数でもうまく機能するという利点があります。

d = {
    "a1": partial(a, 1),
    "a2": partial(a, 2),
    "b": partial(b, "foo"),
    "c": c,
    "k": partial(k, key=int),
    "z": partial(z, "bar", 25),
    }
return d[string]()
于 2018-06-04T18:41:10.330 に答える
4

Python ドキュメントからの次の回答が最も役立つことがわかりました。

のシーケンスでこれを簡単に行うことができますif... elif... elif... else。switch ステートメントの構文についてはいくつかの提案がありましたが、範囲テストを行うかどうか、および行う方法については (まだ) 合意がありません。完全な詳細と現在のステータスについては、PEP 275 を参照してください。

非常に多くの可能性から選択する必要がある場合は、呼び出す関数にケース値をマッピングするディクショナリを作成できます。例えば:

def function_1(...):
    ...

functions = {'a': function_1,
             'b': function_2,
             'c': self.method_1, ...}

func = functions[value]
func()

オブジェクトのメソッドを呼び出す場合、組み込みの getattr() を使用して特定の名前のメソッドを取得することで、さらに単純化できます。

def visit_a(self, ...):
    ...
...

def dispatch(self, value):
    method_name = 'visit_' + str(value)
    method = getattr(self, method_name)
    method()

この例のように、メソッド名にプレフィックスを使用することをお勧めしますvisit_。このようなプレフィックスがないと、値が信頼できないソースから来ている場合、攻撃者はオブジェクトの任意のメソッドを呼び出すことができます。

于 2018-03-19T16:32:29.423 に答える
2

あらかじめ決められた固定値を返すだけの場合は、可能なすべての入力インデックスをキーとして、対応する値とともにディクショナリを作成できます。また、何らかの方法で戻り値を計算している場合を除き、関数でこれを実行したくない場合もあります。

ああ、スイッチのようなことをしたい場合は、ここを参照してください。

于 2008-09-13T00:43:49.300 に答える