Pythonの「 operator 」ライブラリをご紹介します。
operator ライブラリは、その名のとおり「演算子」のライブラリ。組み込みで用意されているさまざまな演算子を関数で実現したものが含まれたライブラリとなっています。
まずは基本的な使い方から。
基本的な使い方
基本的には、本来演算子に渡しているリテラルや変数を operator で用意されている関数にそのまま渡せばOKです。
# ライブラリの読み込み
import operator
# + と同じ処理を行う関数 add と __add__
print operator.add(2, 3) # => 5
print operator.__add__(2, 3) # => 5
ここで add と add は同じふるまいをする関数です。 add 以外の関数でも、ほとんどのものには abc というバージョンと abc というアンダースコアつきバーションの2バージョンが用意されています。
以下、代表的な関数をグループ別に見ていきます。
- 四則演算
- 数学単項演算
- 比較演算
- 論理演算
- シフト演算
- 要素アクセス
- アトリビュートアクセス
- メソッド呼び出し
四則演算
四則演算その他の数学二項演算はそれぞれ次のような関数として用意されています。
print operator.add(2, 3) # +
print operator.sub(2, 3) # -
print operator.mul(2, 3) # *
print operator.div(2, 3) # /
print operator.mod(2, 3) # %
print operator.pow(2, 3) # **
数学単項演算
- と - 、数値処理で使うふたつの演算子はそれぞれ pos と neg に相当します。
print operator.pos(-2) # +
print operator.neg(-2) # -
比較演算
各種比較演算子の関数版も用意されています。いずれも less than 、 less equal 、 greater than などの略ですね。
print operator.lt(2, 3) # <
print operator.le(2, 3) # <=
print operator.eq(2, 3) # ==
print operator.ne(2, 3) # !=
print operator.ge(2, 3) # >=
print operator.gt(2, 3) # >
print operator.is_([], []) # is
print operator.is_not([], []) # is not
論理演算
論理演算を行う演算子として not_ truth などが用意されています。 ```pythonprint operator.not_(False) # notprint operator.truth(True) # bool```
シフト演算
ビットシフト演算 << >> に相当する関数は lshift rshift という名前です。
print operator.lshift(9, 1) # <<
print operator.rshift(9, 1) # >>
要素アクセス 基本版
リストやタプルの要素アクセスに使う [] の関数版も用意されています。セッタ、ゲッタがそれぞれ getitem setitem で、要素を削除する delitem もあります。
li = [7, 5, 3]
print operator.getitem(li, 1) # []
# => 5
operator.setitem(li, 1, 10) # [] =
print li # => [7, 10, 3]
operator.delitem(li, 0)
print li # => [10, 3]
要素アクセス 関数版
上述の getitem setitem delitem は直接処理を行うものでしたが、処理は直接行わず「アクセスするための関数」を返してくるものも用意されています。
li = [7, 5, 3]
myfunc = operator.itemgetter(0)
print myfunc(li) # li[0]
# => 7
この itemgetter の使いどころとしては、たとえば、高階関数に渡して使うケースが考えられます。
from operator itemgetter
li = [('C', 1972), ('Java', 1995), ('Go', 2009)]
print map(itemgetter(-1), li) # => [1972, 1995, 2009]
これを getitem で書こうとすると次のような感じになってしまいます。
from operator itemgetter
li = [('C', 1972), ('Java', 1995), ('Go', 2009)]
print map(lambda x: getitem(x, -1), li) # => [1972, 1995, 2009]
アトリビュートアクセス 関数版
こちらはオブジェクトのアトリビュートを取得するための関数。
class MyClass(object):
pass
myobj = MyClass()
myobj.name = "p"
myobj.age = 54
mygetter1 = operator.attrgetter("name") # name を取得する関数
print mygetter1(myobj) # => "p"
mygetter2 = operator.attrgetter("name", "age") # name と age を取得する関数
print mygetter2(myobj) # => ("p", 54)
この attrgetter を使うと、通常は . に続けて直接書かないといけないアトリビュート名を文字列で指定することができます。
メソッド呼び出し
メソッド呼び出しを行うための関数も用意されています。
s1 = "abracadabra"
mycaller = operator.methodcaller("split", "a") # obj に対して obj.split("a") を行う関数
print mycaller(s1) # => ['', 'br', 'c', 'd', 'br', '']
上述のアトリビュートの場合と同じく、通常は obj.somemethod(*args) という形で呼び出すメソッドを関数化して、別のスタイルで呼び出すことが可能です 。
Rubyでいう send メソッドのような感じですかね。
以上です。
用意されている関数は他にもまだまだあるので、詳しくは公式ドキュメントをご参照ください。