Python3.0でswitch文を作りました
エイプリルフールなので嘘みたいなことをやってみた。
for x in range(5): print(x) MESSAGE = "The value is" class _(switch(x)): @case(0) def _(): print(MESSAGE, "zero!") @case(1) def _(): print(MESSAGE, "one!") @case(2) def _(): print(MESSAGE, "twei!") @case_else def _(): print(MESSAGE, "something else!!")
MESSAGEはちゃんと外のスコープを見れていることを示すためにあえてclassの外に置いてみた。まあnested_scopes以降なら動いて当たり前なのだけど。
実行するとこうなる。
0 The value is zero! 1 The value is one! 2 The value is twei! 3 The value is something else!! 4 The value is something else!!
実装はこちら:
def switch(val): case.cases = [] case_else.func = lambda :None class SwitchMetaclass(type): def __init__(cls, name, bases, dct): if not case.cases: return for (v, func) in case.cases: if v == val: func() break else: case_else.func() class Switch(metaclass=SwitchMetaclass): pass return Switch def case(x): def foo(f): case.cases.append((x, f)) return foo def case_else(f): case_else.func = f
メタクラスのコンストラクタ__init__は、メタクラスのインスタンス(つまりクラス)がインスタンシエイトされるタイミングで呼ばれるので、デコレータで関数と値のマッピングを作っておいてそのタイミングでマッピングから順にマッチするものを探して実行するってだけ。
このまえid:moriyoshi に言われた「class Foo(lambda: ...)で何か実用的なことができないか」をやろうとしていたのだが、結局lambdaじゃないものになってしまった。