Python の演算子記号またはキーワードの 1 つをstring として受け取り、オペランドとともに評価して結果を返す関数が必要です。このような:
>>> string_op('<=', 3, 3)
True
>>> string_op('|', 3, 5)
7
>>> string_op('and', 3, 5)
True
>>> string_op('+', 5, 7)
12
>>> string_op('-', -4)
4
文字列が安全であると想定することはできません。二項演算子をマッピングするだけで十分ですが、それらすべてを取得できればさらに嬉しいです。
私の現在の実装では、シンボルをoperator モジュールの関数に手動でマップします。
import operator
def string_op(op, *args, **kwargs):
"""http://docs.python.org/2/library/operator.html"""
symbol_name_map = {
'<': 'lt',
'<=': 'le',
'==': 'eq',
'!=': 'ne',
'>=': 'ge',
'>': 'gt',
'not': 'not_',
'is': 'is_',
'is not': 'is_not',
'+': 'add', # conflict with concat
'&': 'and_', # (bitwise)
'/': 'div',
'//': 'floordiv',
'~': 'invert',
'%': 'mod',
'*': 'mul',
'|': 'or_', # (bitwise)
'pos': 'pos_',
'**': 'pow',
'-': 'sub', # conflicts with neg
'^': 'xor',
'in': 'contains',
'+=': 'iadd', # conflict with iconcat
'&=': 'iand',
'/=': 'idiv',
'//=': 'ifloordiv',
'<<=': 'ilshift',
'%=': 'imod',
'*=': 'imul',
'|=': 'ior',
'**=': 'ipow',
'>>=': 'irshift',
'-=': 'isub',
'^=': 'ixor',
}
if op in symbol_name_map:
return getattr(operator, symbol_name_map[op])(*args, **kwargs)
else:
return getattr(operator, op)(*args, **kwargs)
このソリューションは、オーバーロードされた演算子 ( add
/concat
およびsub
/ ) で失敗しますneg
。これらのケースを検出し、型を検出したり、引数をカウントして正しい関数名を選択したりするためのチェックを追加できますが、それは少し見苦しく感じます。ここで良いアイデアが得られない場合は、これを使用します。
私を悩ませているのは、Pythonがすでにこれを行っていることです。シンボルを演算子関数にマップする方法は既にわかっていますが、私が知る限り、その機能はプログラマーに公開されていません。ピクルス化プロトコルに至るまで、 Pythonの他のすべてがプログラマーに公開されているようです。それで、これはどこですか?またはなぜそうではないのですか?