Pythonのoperatorモジュールの使い方(itemgetterなど)
Pythonの標準ライブラリのoperatorモジュールでは、+
や<
などの演算子に対応する関数や、オブジェクトの要素・属性を取得したりメソッドを実行したりする呼び出し可能オブジェクトを生成する関数が提供されている。
呼び出し可能オブジェクトを指定する引数にoperatorの関数を使うと、シンプルに書けたり、より高速に処理できたりする。
operator.itemgetter()
, attrgetter()
, methodcaller()
はsorted()
関数などの引数key
に使われることが多い。具体例などの詳細は以下の記事を参照。
組み込み演算子に対応するoperatorモジュールの関数
operatorモジュールでは組み込み演算子に対応する関数が提供されている。
ここでは代表的なものをいくつか紹介する。本記事で扱っていないものもあるので、一覧は以下の公式ドキュメントの対応表を参照されたい。
算術演算子
Pythonには+
や*
などの算術演算子がある。
例えば+
演算子はoperator.add()
で実現できる。a + b
はoperator.add(a, b)
と等価。
import operator
print(2 + 3)
# 5
print(operator.add(2, 3))
# 5
そのほか、-
, *
, /
, //
演算子に対応する関数も提供されている。
print(operator.sub(2, 3)) # 2 - 3
# -1
print(operator.mul(2, 3)) # 2 * 3
# 6
print(operator.truediv(2, 3)) # 2 / 3
# 0.6666666666666666
print(operator.floordiv(2, 3)) # 2 // 3
# 0
比較演算子
<
や==
などの比較演算子に対応する関数も提供されている。
print(operator.lt(2, 3)) # 2 < 3
# True
print(operator.le(2, 3)) # 2 <= 3
# True
print(operator.gt(2, 3)) # 2 > 3
# False
print(operator.ge(2, 3)) # 2 >= 3
# False
print(operator.eq(2, 3)) # 2 == 3
# False
print(operator.ne(2, 3)) # 2 != 3
# True
論理演算子
ビット単位の論理演算子である&
(AND)や|
(OR), ^
(XOR)などに対応する関数も提供されている。
ここでは0b
を使って整数int
を2進数で表し、結果をbin()
で2進数に変換して出力している。
print(bin(0b1100 & 0b1010))
# 0b1000
print(bin(operator.and_(0b1100, 0b1010)))
# 0b1000
print(bin(0b1100 | 0b1010))
# 0b1110
print(bin(operator.or_(0b1100, 0b1010)))
# 0b1110
print(bin(0b1100 ^ 0b1010))
# 0b110
print(bin(operator.xor(0b1100, 0b1010)))
# 0b110
そのほか、~
(反転)やビットシフト<<
, >>
に対応する関数もある。
なお、operator.and_()
やoperator.or_()
という名前だが、ブール演算子のand
やor
とは違うので注意。
print(bin(0b1100 and 0b1010))
# 0b1010
print(bin(0b1100 or 0b1010))
# 0b1100
and
やor
では左右のオブジェクトを真か偽か判定した上で、左か右のいずれかの値が返されるので上のような結果となる。詳細は以下の記事を参照。
Python3.11時点ではand
やor
に対応する関数は提供されていない。
オブジェクトの要素を取得: operator.itemgetter()
operator.itemgetter()
は対象となるオブジェクトの要素を取得する呼び出し可能オブジェクトを生成する。
[]
を使ったインデックス指定などに相当する処理を実行できる。
l = [0, 10, 20, 30, 40, 50]
print(l[3])
# 30
f = operator.itemgetter(3)
print(f(l))
# 30
operator.add()
などとは異なり、operator.itemgetter()
が生成するのは呼び出し可能オブジェクト。さらに対象を括弧()
で指定して呼び出すことで実行される。
()
が連続して奇妙に感じるかもしれないが、続けて書くと以下のようになる。
print(operator.itemgetter(3)(l))
# 30
以降、動作を紹介するために()
を連続した書き方を用いる場合がある。
通常の[]
によるインデックス指定と同じく、負の値で後ろからの位置で指定することも可能。
print(l[-1])
# 50
print(operator.itemgetter(-1)(l))
# 50
スライスにも対応している。slice()
関数を利用する。
print(l[1:4])
# [10, 20, 30]
print(operator.itemgetter(slice(1, 4))(l))
# [10, 20, 30]
print(l[1::2])
# [10, 30, 50]
print(operator.itemgetter(slice(1, None, 2))(l))
# [10, 30, 50]
operator.itemgetter()
の引数には複数の値を指定可能。それぞれの結果を要素とするタプルが返される。
print(operator.itemgetter(0, slice(1, 4), -1)(l))
# (0, [10, 20, 30], 50)
print(type(operator.itemgetter(0, slice(1, 4), -1)(l)))
# <class 'tuple'>
operator.itemgetter()
は__getitem__()
によってアイテムを取得している。リストやタプルなどのインデックス指定だけでなく、辞書dict
のキー指定による値取得などにも対応している。
d = {'k1': 0, 'k2': 10, 'k3': 20}
print(d['k2'])
# 10
print(operator.itemgetter('k2')(d))
# 10
print(operator.itemgetter('k2', 'k1')(d))
# (10, 0)
operator.itemgetter()
の具体的な利用例として、sorted()
関数などの引数key
への指定がある。詳細は以下の記事を参照。
オブジェクトの属性を取得: operator.attrgetter()
operator.attrgetter()
は対象となるオブジェクトの属性を取得する呼び出し可能オブジェクトを生成する。
.xxx
のような属性取得に相当する処理を実行できる。
日付情報を保持するdatetime.date
オブジェクトを例とする。
import datetime
dt = datetime.date(2001, 10, 20)
print(dt)
# 2001-10-20
print(type(dt))
# <class 'datetime.date'>
print(dt.year)
# 2001
operator.attrgetter()
で属性を取得する呼び出し可能オブジェクトを生成できる。operator.itemgetter()
と同様、複数の属性をまとめて取得可能。
f = operator.attrgetter('year')
print(f(dt))
# 2001
print(operator.attrgetter('year', 'month', 'day')(dt))
# (2001, 10, 20)
オブジェクトのメソッドを実行: operator.methodcaller()
operator.methodcaller()
は対象となるオブジェクトのメソッドを実行する呼び出し可能オブジェクトを生成する。
s = 'xxxAyyyAzzz'
print(s.upper())
# XXXAYYYAZZZ
f = operator.methodcaller('upper')
print(f(s))
# XXXAYYYAZZZ
引数も指定可能。キーワード引数も指定できる。
print(s.split('A', maxsplit=1))
# ['xxx', 'yyyAzzz']
print(operator.methodcaller('split', 'A', maxsplit=1)(s))
# ['xxx', 'yyyAzzz']
operator.attrgetter()
やoperator.methodcaller()
もoperator.itemgetter()
と同じくsorted()
関数などの引数key
への指定に利用されることがある。