web-dev-qa-db-ja.com

組み込みの「演算子」モジュールをPythonで使用する必要があるのはどのような状況ですか?

私はこのモジュールについて話している: http://docs.python.org/library/operator.html

記事から:

演算子モジュールは、Pythonの組み込み演算子に対応するCで実装された関数のセットをエクスポートします。たとえば、operator.add(x、y)は式x + yと同等です。関数名は、特別なクラスメソッドに使用される名前です。便宜上、先頭と末尾に__がないバリアントも提供されています。

このモジュールの利点や目的を理解しているかどうかはわかりません。

43
Bjorn

おそらく最も一般的な使用法はoperator.itemgetterです。タプルのリストlstが与えられた場合、i番目の要素で次のように並べ替えることができます。lst.sort(key=operator.itemgetter(i))

確かに、独自のキー関数を定義することで、演算子なしで同じことを行うことができますが、演算子モジュールを使用すると、少しきれいになります。

残りについては、pythonはプログラミングの機能的なスタイルを可能にするので、それを思い付くことができます-たとえば、Gregのreduceの例。

operator.addが必要なのに、なぜadd = lambda x, y: x+yが必要なのですか?」と主張するかもしれません。答えは次のとおりです。

  1. operator.addは(私が思うに)少し速いです。
  2. これにより、コードを見て、あなたや後で他の人がコードを理解しやすくなります。演算子モジュールが何をするかを知っているので、addの定義を探す必要はありません。
  3. operator.addは選択可能ですが、lambdaは選択できません。これは、関数をディスクに保存したり、プロセス間で受け渡したりできることを意味します。
40
John Fouhy

1つの例は、reduce()関数の使用です。

>>> import operator
>>> a = [2, 3, 4, 5]
>>> reduce(lambda x, y: x + y, a)
14
>>> reduce(operator.add, a)
14
27
Greg Hewgill

たとえば、メンバーがタプルであるリストの列を取得し、列でシーケンスを並べ替えます。

def item_ope():
    s = ['h', 'e', 'l', 'l', 'o']
    print operator.getitem(s, 1)
    # e
    print operator.itemgetter(1, 4)(s)
    # ('e', 'o')

    inventory = [('Apple', 3), ('banana', 2), ('pear', 5), ('orange', 1)]
    get_count = operator.itemgetter(1)
    print map(get_count, inventory)
    # [3, 2, 5, 1]

    print sorted(inventory, key=get_count)
    # [('orange', 1), ('banana', 2), ('Apple', 3), ('pear', 5)]

より実用的な例を参照してください。キーまたは値でdictを並べ替えます。

def dict_sort_by_value():
    dic_num = {'first': 11, 'second': 2, 'third': 33, 'Fourth': 4}

    # print all the keys
    print dic_num.keys()
    # ['second', 'Fourth', 'third', 'first']

    # sorted by value
    sorted_val = sorted(dic_num.items(), key=operator.itemgetter(1))
    # [('second', 2), ('Fourth', 4), ('first', 11), ('third', 33)]
    print sorted_val

    # sorted by key
    sorted_key = sorted(dic_num.items(), key=operator.itemgetter(0))
    print sorted_key
    # [('Fourth', 4), ('first', 11), ('second', 2), ('third', 33)]

最大値とそのリスト内のインデックスを取得する別の例:

def get_max_val_idx():
    lst = [1, 7, 3, 5, 6]
    max_val = max(lst)
    print max_val
    # 7
    max_idx = lst.index(max_val)
    print max_idx
    # 1

    # simplify it by use operator
    index, value = max(enumerate(lst), key=operator.itemgetter(1))
    print index, value
    # 1 7

以下のようなその他のデモ:

import operator

def cmp_fun():
    a, b = 5, 3
    print operator.le(a, b)
    # False
    print operator.gt(a, b)
    # True


def lst_ope():
    lst = [1, 2, 3]
    print operator.indexOf(lst, 2)
    # 1
    lst1 = [1, 2, 3, 2]
    print operator.countOf(lst1, 2)
    # 2


def cal_ope():
    lst1 = [0, 1, 2, 3]
    lst2 = [10, 20, 30, 40]
    print map(operator.mul, lst1, lst2)
    # [0, 20, 60, 120]

    print sum(map(operator.mul, lst1, lst2))
    # 200

    a, b = 1, 3
    print operator.iadd(a, b)
    # 4

python doc からもっと見る

4
Jayhello

このモジュールは、関数を引数として何かに渡す必要がある場合に役立ちます。次に、2つのオプションがあります。operatorモジュールを使用するか、新しい関数を定義します(defまたはlambdaを使用)。関数をその場で定義する場合、この関数をディスクに保存するか、プロセス間で渡すために、この関数をpickle化する必要があると、問題が発生する可能性があります。 itemgetterは選択可能ですが、動的に定義された関数(defまたはlambdaのいずれか)は選択できません。次の例では、itemgetterlambda式に置き換えると、PicklingErrorになります。

from operator import itemgetter

def sort_by_key(sequence, key):
    return sorted(sequence, key=key)

if __name__ == "__main__":
    from multiprocessing import Pool

    items = [([(1,2),(4,1)], itemgetter(1)),
             ([(5,3),(2,7)], itemgetter(0))]

    with Pool(5) as p:
        result = p.starmap(sort_by_key, items)
    print(result)
3
eaglebrain

一般に、このモジュールの目的は(上記の回答のいくつかで示唆されているように)、簡単な操作のための定型関数を提供することです。そうしないと、自分で記述して、sort()またはreduce()

たとえば、演算子がない場合、リスト内の数値を合計するには、次のようにする必要があります。

_from functools import reduce

l = list(range(100))
f = lambda x, y: x + y
result = reduce(f, l)
print(result)
_

演算子モジュールを使用すると、次のようにそのadd()関数を使用できます。

_from operator import add

result = reduce(add, l)
print(result)
_

したがって、ラムダ式を作成する必要がなくなります。

1
Steve Wehba