Python3での関数型プログラミング

Pythonコマンド

このページでは、Python3で使用できる関数型プログラミングツールとその使用方法について説明します。

Itertools:効率的なループのためのイテレータ

このモジュールは、APL、Haskell、およびSMLの構成に触発された多くのイテレータービルディングブロックを実装します。それぞれがPythonに適した形式で再キャストされました。

このモジュールは、単独で、または組み合わせて使用​​できる、高速でメモリ効率の高いツールのコアセットを標準化します。これらが一緒になってイテレータ代数を形成し、純粋なPythonで特殊なツールを簡潔かつ効率的に構築できるようにします。

たとえば、SMLは集計ツールを提供します。 tabulate(f) シーケンスを生成します f(0)f(1) 、など。Pythonでも同じ効果を組み合わせることができます。 地図() そして カウント() 申込用紙へ map(f、count())

これらのツールとそれに組み込まれているツールは、オペレータモジュールの高速機能でもうまく機能します。たとえば、乗算演算子を2つのベクトルにマッピングして、効率的な内積を形成できます。 sum(map(operator.mul、vector1、vector2))

Itertools関数

次のモジュール関数は、すべてのイテレータを作成して返します。無限の長さのストリームを提供するものもあるため、ストリームを切り捨てる関数またはループからのみアクセスする必要があります。

  itertools.accumulate(   iterable  [  ,   func  ]  )  
累積合計を返すイテレータを作成します。要素は、以下を含む任意の追加可能なタイプにすることができます 10進数 または 分数 。オプションの場合 関数 引数が指定されています。これは2つの引数の関数である必要があり、加算の代わりに使用されます。

に相当:

def accumulate(iterable, func=operator.add): 'Return running totals' # accumulate([1,2,3,4,5]) --> 1 3 6 10 15 # accumulate([1,2,3,4,5], operator.mul) --> 1 2 6 24 120 it = iter(iterable) total = next(it) yield total for element in it: total = func(total, element) yield total
の多くの用途があります 関数 引数。に設定できます 最小() 実行中の最小値については、 max() 実行中の最大値の場合、または operator.mul() 実行中の製品の場合。償却表は、利息を累積して支払いを適用することで作成できます。一次漸化式は、反復可能に初期値を提供し、の累積合計のみを使用することによってモデル化できます。 関数 引数:

>>> data = [3, 4, 6, 2, 1, 9, 0, 7, 5, 8]>>> list(accumulate(data, operator.mul)) # running product[3, 12, 72, 144, 144, 1296, 0, 0, 0, 0]>>> list(accumulate(data, max)) # running maximum[3, 4, 6, 6, 6, 9, 9, 9, 9, 9]# Amortize a 5% loan of 1000 with 4 annual payments of 90>>> cashflows = [1000, -90, -90, -90, -90]>>> list(accumulate(cashflows, lambda bal, pmt: bal*1.05 + pmt))[1000, 960.0, 918.0, 873.9000000000001, 827.5950000000001]# Chaotic recurrence relation http://en.wikipedia.org/wiki/Logistic_map>>> logistic_map = lambda x, _: r * x * (1 - x)>>> r = 3.8>>> x0 = 0.4>>> inputs = repeat(x0, 36) # only the initial value is used>>> [format(x, '.2f') for x in accumulate(inputs, logistic_map)]['0.40', '0.91', '0.30', '0.81', '0.60', '0.92', '0.29', '0.79', '0.63', '0.88', '0.39', '0.90', '0.33', '0.84', '0.52', '0.95', '0.18', '0.57', '0.93', '0.25', '0.71', '0.79', '0.63', '0.88', '0.39', '0.91', '0.32', '0.83', '0.54', '0.95', '0.20', '0.60', '0.91', '0.30', '0.80', '0.60']
見る functools.reduce() 最終的な累積値のみを返す同様の関数の場合。
  itertools.chain(*   iterables   )  
最初のイテレータから要素がなくなるまで要素を返し、次にすべてのイテレータがなくなるまで次のイテレータに進むイテレータを作成します。 iterables 使い果たされています。連続するシーケンスを単一のシーケンスとして扱うために使用されます。に相当:

def chain(*iterables): # chain('ABC', 'DEF') --> A B C D E F for it in iterables: for element in it: yield element
  classmethod   chain.from_iterable(   iterable   )  
の代替コンストラクタ 鎖() 。遅延評価される単一の反復可能な引数から連鎖入力を取得します。ほぼ同等:

def from_iterable(iterables): # chain.from_iterable(['ABC', 'DEF']) --> A B C D E F for it in iterables: for element in it: yield element
  itertools.combinations(   iterable   ,   r   )  
戻る r 入力iterableからの要素の長さのサブシーケンス。

組み合わせは、辞書式順序で発行されます。したがって、入力が 反復可能 がソートされると、組み合わせタプルはソートされた順序で生成されます。

要素は、値ではなく、位置に基づいて一意として扱われます。したがって、入力要素が一意である場合、各組み合わせに繰り返し値はありません。

に相当:

def combinations(iterable, r): # combinations('ABCD', 2) --> AB AC AD BC BD CD # combinations(range(4), 3) --> 012 013 023 123 pool = tuple(iterable) n = len(pool) if r > n: return indices = list(range(r)) yield tuple(pool[i] for i in indices) while True: for i in reversed(range(r)): if indices[i] != i + n - r: break else: return indices[i] += 1 for j in range(i+1, r): indices[j] = indices[j-1] + 1 yield tuple(pool[i] for i in indices)
のコード 組み合わせ() のサブシーケンスとして表すこともできます permutations() 要素がソートされた順序ではないエントリをフィルタリングした後(入力プール内の位置に従って):

def combinations(iterable, r): pool = tuple(iterable) n = len(pool) for indices in permutations(range(n), r): if sorted(indices) == list(indices): yield tuple(pool[i] for i in indices)
返品数はn個です! / r! /(n-r)! 0のとき<= r n.
  itertools.combinations_with_replacement(   iterable   ,   r   )  
戻る r 入力反復可能要素からの要素の長さのサブシーケンスにより、個々の要素を複数回繰り返すことができます。

組み合わせは、辞書式順序で発行されます。したがって、入力反復可能オブジェクトがソートされている場合、組み合わせタプルはソートされた順序で生成されます。

要素は、値ではなく、位置に基づいて一意として扱われます。したがって、入力要素が一意である場合、生成される組み合わせも一意になります。

に相当:

def combinations_with_replacement(iterable, r): # combinations_with_replacement('ABC', 2) --> AA AB AC BB BC CC pool = tuple(iterable) n = len(pool) if not n and r: return indices = [0] * r yield tuple(pool[i] for i in indices) while True: for i in reversed(range(r)): if indices[i] != n - 1: break else: return indices[i:] = [indices[i] + 1] * (r - i) yield tuple(pool[i] for i in indices)
のコード 組み合わせ_with_replacement() のサブシーケンスとして表すこともできます 製品() 要素がソートされた順序ではないエントリをフィルタリングした後(入力プール内の位置に従って):

def combinations_with_replacement(iterable, r): pool = tuple(iterable) n = len(pool) for indices in product(range(n), repeat=r): if sorted(indices) == list(indices): yield tuple(pool[i] for i in indices)
返品される商品の数は (n + r-1)! / r! /(n-1)! いつ n> 0
  itertools.compress(   data   ,   selectors   )  
に対応する要素を持つ要素のみを返すデータから要素をフィルタリングするイテレータを作成します セレクター に評価されます 本当 。データまたは セレクター iterablesが使い果たされています。に相当:

def compress(data, selectors): # compress('ABCDEF', [1,0,1,0,1,1]) --> A C E F return (d for d, s in zip(data, selectors) if s)
  itertools.count(   start   =0,   step   =1)  
numberstartで始まる等間隔の値を返すイテレータを作成します。多くの場合、連続するデータポイントを生成するためにmap()の引数として使用されます。また、zip()とともに使用してシーケンス番号を追加します。に相当:

def count(start=0, step=1): # count(10) --> 10 11 12 13 14 ... # count(2.5, 0.5) -> 2.5 3.0 3.5 ... n = start while True: yield n n += step
浮動小数点数でカウントする場合、次のような乗法コードを代入することで、より高い精度が得られる場合があります。 (start + step * i for i in count())
  itertools.cycle(   iterable   )  
から要素を返すイテレータを作成します 反復可能 それぞれのコピーを保存します。 iterableが使い果たされたら、保存されたコピーから要素を返します。無期限に繰り返します。に相当:

def cycle(iterable): # cycle('ABCD') --> A B C D A B C D A B C D ... saved = [] for element in iterable: yield element saved.append(element) while saved: for element in saved: yield element
ツールキットのこのメンバーは、(反復可能オブジェクトの長さに応じて)かなりの補助記憶装置を必要とする場合があることに注意してください。
  itertools.dropwhile(   predicate   ,   iterable   )  
から要素を削除するイテレータを作成します 反復可能 限り 述語 本当です。その後、すべての要素を返します。イテレータは、述語が最初にfalseになるまで出力を生成しないため、起動時間が長くなる可能性があることに注意してください。に相当:

def dropwhile(predicate, iterable): # dropwhile(lambda x: x 6 4 1 iterable = iter(iterable) for x in iterable: if not predicate(x): yield x break for x in iterable: yield x
  itertools.filterfalse(   predicate   ,   iterable   )  
から要素をフィルタリングするイテレータを作成します 反復可能 述語がFalseであるものだけを返します。場合 述語 です 無し 、falseのアイテムを返します。に相当:

def filterfalse(predicate, iterable): # filterfalse(lambda x: x%2, range(10)) --> 0 2 4 6 8 if predicate is None: predicate = bool for x in iterable: if not predicate(x): yield x
  itertools.groupby(   iterable   ,   key   =None)  
イテレータから連続するキーとグループを返すイテレータを作成します。キーは、各要素のキー値を計算する関数です。指定されていないか、Noneの場合、キーはデフォルトで恒等関数になり、要素を変更せずに返します。一般に、イテラブルは同じキー関数ですでにソートされている必要があります。

の操作 groupby() Unixのuniqフィルターに似ています。キー関数の値が変更されるたびに、ブレークまたは新しいグループが生成されます(そのため、通常、同じキー関数を使用してデータを並べ替える必要があります)。この動作は、入力順序に関係なく共通の要素を集約するSQLのGROUPBYとは異なります。

返されるグループは、それ自体が、基になるイテレータを共有するイテレータです。 groupby() 。ソースが共有されているため、 groupby() オブジェクトが進められると、前のグループは表示されなくなります。したがって、そのデータが後で必要になった場合は、リストとして保存する必要があります。

groups = []uniquekeys = []data = sorted(data, key=keyfunc)for k, g in groupby(data, keyfunc): groups.append(list(g)) # Store group iterator as a list uniquekeys.append(k)
groupby() と同等です:

class groupby: # [k for k, g in groupby('AAAABBBCCDAABBB')] --> A B C D A B # [list(g) for k, g in groupby('AAAABBBCCD')] --> AAAA BBB CC D def __init__(self, iterable, key=None): if key is None: key = lambda x: x self.keyfunc = key self.it = iter(iterable) self.tgtkey = self.currkey = self.currvalue = object() def __iter__(self): return self def __next__(self): while self.currkey == self.tgtkey: self.currvalue = next(self.it) # Exit on StopIteration self.currkey = self.keyfunc(self.currvalue) self.tgtkey = self.currkey return (self.currkey, self._grouper(self.tgtkey)) def _grouper(self, tgtkey): while self.currkey == tgtkey: yield self.currvalue self.currvalue = next(self.it) # Exit on StopIteration self.currkey = self.keyfunc(self.currvalue)
  itertools.islice(   iterable   ,   stop   )   itertools.islice(   iterable   ,   start   ,   stop  [  ,   step  ]  )  
イテレータから選択した要素を返すイテレータを作成します。 startがゼロ以外の場合、iterableの要素はstartに到達するまでスキップされます。その後、ステップが1より大きく設定されてアイテムがスキップされない限り、要素は連続して返されます。 stopがNoneの場合、イテレータが使い果たされるまで反復が続行されます。それ以外の場合は、指定された位置で停止します。通常のスライスとは異なり、islice()は、開始、停止、またはステップの負の値をサポートしていません。内部構造がフラット化されたデータから関連フィールドを抽出するために使用できます(たとえば、複数行のレポートでは、3行ごとに名前フィールドがリストされる場合があります)。に相当:

def islice(iterable, *args): # islice('ABCDEFG', 2) --> A B # islice('ABCDEFG', 2, 4) --> C D # islice('ABCDEFG', 2, None) --> C D E F G # islice('ABCDEFG', 0, None, 2) --> A C E G s = slice(*args) it = iter(range(s.start or 0, s.stop or sys.maxsize, s.step or 1)) nexti = next(it) for i, element in enumerate(iterable): if i == nexti: yield element nexti = next(it)
場合 開始 です 無し 、その後 反復 ゼロから始まります。ステップが 無し の場合、ステップはデフォルトで1になります。
  itertools.permutations(   iterable   ,   r   =None)  
連続して戻る r iterable内の要素の長さの順列。

場合 r 指定されていないか、 無し 、その後 r デフォルトはiterableの長さであり、可能なすべてのフルレングスの順列が生成されます。

順列は辞書式順序で発行されます。したがって、入力反復可能オブジェクトがソートされている場合、順列タプルはソートされた順序で生成されます。

要素は、値ではなく、位置に基づいて一意として扱われます。したがって、入力要素が一意である場合、各順列に繰り返し値はありません。

に相当:

def permutations(iterable, r=None): # permutations('ABCD', 2) --> AB AC AD BA BC BD CA CB CD DA DB DC # permutations(range(3)) --> 012 021 102 120 201 210 pool = tuple(iterable) n = len(pool) r = n if r is None else r if r > n: return indices = list(range(n)) cycles = list(range(n, n-r, -1)) yield tuple(pool[i] for i in indices[:r]) while n: for i in reversed(range(r)): cycles[i] -= 1 if cycles[i] == 0: indices[i:] = indices[i+1:] + indices[i:i+1] cycles[i] = n - i else: j = cycles[i] indices[i], indices[-j] = indices[-j], indices[i] yield tuple(pool[i] for i in indices[:r]) break else: return
のコード permutations() のサブシーケンスとして表すこともできます 製品() 、繰り返し要素を持つエントリ(入力プール内の同じ位置からのエントリ)を除外するようにフィルタリングされます:

def permutations(iterable, r=None): pool = tuple(iterable) n = len(pool) r = n if r is None else r for indices in product(range(n), repeat=r): if len(set(indices)) == r: yield tuple(pool[i] for i in indices)
返品される商品の数は n! /(n-r)! いつ 0<= r <= n またはゼロの場合 r> n
  itertools.product(*   iterables   ,   repeat   =1)  
入力反復可能のデカルト積。

ジェネレータ式のネストされたforループに相当します。例えば、 製品(A、B) と同じを返します ((x、y)for x in A for y in B)

ネストされたループは走行距離計のように循環し、右端の要素が反復ごとに進みます。このパターンは辞書式順序を作成するため、入力の反復可能オブジェクトがソートされると、積タプルがソートされた順序で発行されます。

iterableとそれ自体の積を計算するには、オプションのrepeatキーワード引数を使用して繰り返し回数を指定します。例えば、 product(A、repeat = 4) と同じ意味 製品(A、A、A、A)

この関数は、実際の実装がメモリに中間結果を構築しないことを除いて、次のコードと同等です。

def product(*args, repeat=1): # product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy # product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111 pools = [tuple(pool) for pool in args] * repeat result = [[]] for pool in pools: result = [x+[y] for x in result for y in pool] for prod in result: yield tuple(prod)
  itertools.repeat(   object  [  ,   times  ]  )  
オブジェクトを何度も返すイテレータを作成します。 times引数が指定されていない限り、無期限に実行されます。への引数として使用 地図() 呼び出された関数の不変パラメーターの場合。また、 zip() タプルレコードの不変部分を作成します。に相当:

def repeat(object, times=None): # repeat(10, 3) --> 10 10 10 if times is None: while True: yield object else: for i in range(times): yield object
の一般的な使用法 繰り返す 定数値のストリームをに供給することです 地図 または zip

>>> list(map(pow, range(10), repeat(2)))[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
  itertools.starmap(   function   ,   iterable   )  
から取得した引数を使用して関数を計算するイテレータを作成します 反復可能 。代わりに使用 地図() 引数パラメーターが単一の反復可能オブジェクトからのタプルにすでにグループ化されている場合(データは事前​​に圧縮されています)。の違い 地図() そして starmap() 間の区別に対応します 関数(a、b) そして 関数(* c) 。に相当:

def starmap(function, iterable): # starmap(pow, [(2,5), (3,2), (10,3)]) --> 32 9 1000 for args in iterable: yield function(*args)
  itertools.takewhile(   predicate   ,   iterable   )  
述語が真である限り、イテレータから要素を返すイテレータを作成します。に相当:

def takewhile(predicate, iterable): # takewhile(lambda x: x 1 4 for x in iterable: if predicate(x): yield x else: break
  itertools.tee(   iterable   ,   n   =2)  
戻る n 単一からの独立したイテレータ 反復可能 。に相当:

def tee(iterable, n=2): it = iter(iterable) deques = [collections.deque() for i in range(n)] def gen(mydeque): while True: if not mydeque: # when the local deque is empty newval = next(it) # fetch a new value and for d in deques: # load it to all the deques d.append(newval) yield mydeque.popleft() return tuple(gen(d) for d in deques)
一度 tee() 分割が行われたため、元のiterableを他の場所で使用しないでください。そうしないと、ティーオブジェクトに通知されなくてもイテラブルが進む可能性があります。

このitertoolは、(保存する必要のある一時データの量に応じて)かなりの補助記憶装置を必要とする場合があります。一般に、あるイテレータが別のイテレータが開始する前にほとんどまたはすべてのデータを使用する場合は、使用する方が高速です。 リスト() の代わりに tee()
  itertools.zip_longest(*   iterables   ,   fillvalue   =None)  
それぞれの要素を集約するイテレータを作成します iterables 。イテラブルの長さが不均一な場合、欠落している値は次のように入力されます。 fillvalue 。反復は、最長の反復がなくなるまで続きます。に相当:

class ZipExhausted(Exception): passdef zip_longest(*args, **kwds): # zip_longest('ABCD', 'xy', fillvalue='-') --> Ax By C- D- fillvalue = kwds.get('fillvalue') counter = len(args) - 1 def sentinel(): nonlocal counter if not counter: raise ZipExhausted counter -= 1 yield fillvalue fillers = repeat(fillvalue) iterators = [chain(it, sentinel(), fillers) for it in args] try: while iterators: yield tuple(map(next, iterators)) except ZipExhausted: pass
反復可能オブジェクトの1つが潜在的に無限である場合、 zip_longest() 関数は、呼び出しの数を制限するものでラップする必要があります(たとえば islice() または takewhile() )。指定されていない場合、 fillvalue デフォルトは 無し

Itertoolsレシピ

拡張ツールは、基盤となるツールセットと同じ高性能を提供します。反復可能オブジェクト全体を一度にメモリに取り込むのではなく、要素を1つずつ処理することで、優れたメモリパフォーマンスが維持されます。ツールを機能的なスタイルでリンクすることにより、コードの量を少なく抑え、一時変数を排除します。インタープリターのオーバーヘッドが発生するforループやジェネレーターを使用するよりも、ベクトル化されたビルディングブロックを優先することで、高速性が維持されます。

def take(n, iterable): 'Return first n items of the iterable as a list' return list(islice(iterable, n)) def tabulate(function, start=0): 'Return function(0), function(1), ...' return map(function, count(start)) def consume(iterator, n): 'Advance the iterator n-steps ahead. If n is none, consume entirely.' # Use functions that consume iterators at C speed. if n is None: # feed the entire iterator into a zero-length deque collections.deque(iterator, maxlen=0) else: # advance to the empty slice starting at position n next(islice(iterator, n, n), None) def nth(iterable, n, default=None): 'Returns the nth item or a default value' return next(islice(iterable, n, None), default) def quantify(iterable, pred=bool): 'Count how many times the predicate is true' return sum(map(pred, iterable)) def padnone(iterable): '''Returns the sequence elements and then returns None indefinitely. Useful for emulating the behavior of the built-in map() function. ''' return chain(iterable, repeat(None)) def ncycles(iterable, n): 'Returns the sequence elements n times' return chain.from_iterable(repeat(tuple(iterable), n)) def dotproduct(vec1, vec2): return sum(map(operator.mul, vec1, vec2)) def flatten(listOfLists): 'Flatten one level of nesting' return chain.from_iterable(listOfLists) def repeatfunc(func, times=None, *args): '''Repeat calls to func with specified arguments. Example: repeatfunc(random.random) ''' if times is None: return starmap(func, repeat(args)) return starmap(func, repeat(args, times)) def pairwise(iterable): 's -> (s0,s1), (s1,s2), (s2, s3), ...' a, b = tee(iterable) next(b, None) return zip(a, b) def grouper(iterable, n, fillvalue=None): 'Collect data into fixed-length chunks or blocks' # grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx' args = [iter(iterable)] * n return zip_longest(*args, fillvalue=fillvalue) def roundrobin(*iterables): 'roundrobin('ABC', 'D', 'EF') --> A D E B F C' # Recipe credited to George Sakkis pending = len(iterables) nexts = cycle(iter(it).__next__ for it in iterables) while pending: try: for next in nexts: yield next() except StopIteration: pending -= 1 nexts = cycle(islice(nexts, pending)) def partition(pred, iterable): 'Use a predicate to partition entries into false entries and true entries' # partition(is_odd, range(10)) --> 0 2 4 6 8 and 1 3 5 7 9 t1, t2 = tee(iterable) return filterfalse(pred, t1), filter(pred, t2) def powerset(iterable): 'powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)' s = list(iterable) return chain.from_iterable(combinations(s, r) for r in range(len(s)+1)) def unique_everseen(iterable, key=None): 'List unique elements, preserving order. Remember all elements ever seen.' # unique_everseen('AAAABBBCCDAABBB') --> A B C D # unique_everseen('ABBCcAD', str.lower) --> A B C D seen = set() seen_add = seen.add if key is None: for element in filterfalse(seen.__contains__, iterable): seen_add(element) yield element else: for element in iterable: k = key(element) if k not in seen: seen_add(k) yield element def unique_justseen(iterable, key=None): 'List unique elements, preserving order. Remember only the element just seen.' # unique_justseen('AAAABBBCCDAABBB') --> A B C D A B # unique_justseen('ABBCcAD', str.lower) --> A B C A D return map(next, map(itemgetter(1), groupby(iterable, key))) def iter_except(func, exception, first=None): ''' Call a function repeatedly until an exception is raised. Converts a call-until-exception interface to an iterator interface. Like builtins.iter(func, sentinel) but uses an exception instead of a sentinel to end the loop. Examples: iter_except(functools.partial(heappop, h), IndexError) # priority queue iterator iter_except(d.popitem, KeyError) # non-blocking dict iterator iter_except(d.popleft, IndexError) # non-blocking deque iterator iter_except(q.get_nowait, Queue.Empty) # loop over a producer Queue iter_except(s.pop, KeyError) # non-blocking set iterator ''' try: if first is not None: yield first() # For database APIs needing an initial cast to db.first() while 1: yield func() except exception: pass def first_true(iterable, default=False, pred=None): '''Returns the first true value in the iterable. If no true value is found, returns *default* If *pred* is not None, returns the first item for which pred(item) is true. ''' # first_true([a,b,c], x) --> a or b or c or x # first_true([a,b], x, f) --> a if f(a) else b if f(b) else x return next(filter(pred, iterable), default) def random_product(*args, repeat=1): 'Random selection from itertools.product(*args, **kwds)' pools = [tuple(pool) for pool in args] * repeat return tuple(random.choice(pool) for pool in pools) def random_permutation(iterable, r=None): 'Random selection from itertools.permutations(iterable, r)' pool = tuple(iterable) r = len(pool) if r is None else r return tuple(random.sample(pool, r)) def random_combination(iterable, r): 'Random selection from itertools.combinations(iterable, r)' pool = tuple(iterable) n = len(pool) indices = sorted(random.sample(range(n), r)) return tuple(pool[i] for i in indices) def random_combination_with_replacement(iterable, r): 'Random selection from itertools.combinations_with_replacement(iterable, r)' pool = tuple(iterable) n = len(pool) indices = sorted(random.randrange(n) for i in range(r)) return tuple(pool[i] for i in indices)

上記のレシピの多くは、グローバルルックアップをデフォルト値として定義されたローカル変数に置き換えることで最適化できることに注意してください。たとえば、内積レシピは次のように記述できます。

def dotproduct(vec1, vec2, sum=sum, map=map, mul=operator.mul): return sum(map(mul, vec1, vec2))

演算子:関数としての標準演算子

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

関数は、オブジェクト比較、論理演算、数学演算、およびシーケンス演算を実行するカテゴリに分類されます。

高速ブートを無効にする方法

オブジェクト比較関数はすべてのオブジェクトに役立ち、サポートする豊富な比較演算子にちなんで名付けられています。

  operator.lt(   a   ,   b   )   operator.le(   a   ,   b   )   operator.eq(   a   ,   b   )   operator.ne(   a   ,   b   )   operator.ge(   a   ,   b   )   operator.gt(   a   ,   b   )   operator.__lt__(   a   ,   b   )   operator.__le__(   a   ,   b   )   operator.__eq__(   a   ,   b   )   operator.__ne__(   a   ,   b   )   operator.__ge__(   a   ,   b   )   operator.__gt__(   a   ,   b   )  
間の豊富な比較を実行します そして b 。具体的には、 lt(a、b) と同等です と同等です <= b, eq(a, b) と同等です a == b、ne(a、b) と同等です a!= b、gt(a、b) と同等です a> bおよびge(a、b) と同等です a> = b 。これらの関数は任意の値を返すことができ、ブール値として解釈できる場合とできない場合があることに注意してください。

論理操作は、通常、すべてのオブジェクトに適用可能であり、真理テスト、IDテスト、およびブール操作をサポートします。

  operator.not_(   obj   )   operator.__not__(   obj   )  
の結果を返す objではありません 。 (ないことに注意してください __not __() オブジェクトインスタンスのメソッド。インタープリターコアのみがこの操作を定義します。結果は影響を受けます __bool __() そして __len __() メソッド。)
  operator.truth(   obj   )  
戻る 本当 もし obj 真実であり、 誤り さもないと。これは、boolコンストラクターを使用するのと同じです。
  operator.is_(   a   ,   b   )  
戻る です b 。オブジェクトのアイデンティティをテストします。
  operator.is_not(   a   ,   b   )  
戻る ではありません b 。オブジェクトのアイデンティティをテストします。

数学演算とビット演算が最も多くあります。

hpサポートアシスタントをアンインストールする方法
  operator.abs(   obj   )   operator.__abs__(   obj   )  
の絶対値を返します obj
  operator.add(   a   ,   b   )   operator.__add__(   a   ,   b   )  
戻る a + b 、 にとって そして b 数字。
  operator.and_(   a   ,   b   )   operator.__and__(   a   ,   b   )  
ビット単位とのを返します そして b
  operator.floordiv(   a  ,  b   )   operator.__floordiv__(   a   ,   b)  
戻る // b
  operator.index(   a   )   operator.__index__(   a   )  
整数に変換されたものを返します。に相当 a .__ index __()
  operator.inv(   obj   )   operator.invert(   obj   )   operator.__inv__(   obj   )   operator.__invert__(   obj   )  
数値のビット単位の逆数を返します obj 。これは同等です 〜obj
  operator.lshift(   a   ,   b   )   operator.__lshift__(   a   ,   b   )  
戻る 左にシフト b
  operator.mod(   a   ,   b   )   operator.__mod__(   a   ,   b   )  
戻る b
  operator.mul(   a   ,   b   )   operator.__mul__(   a   ,   b   )  
戻る * b 、 にとって そして b 数字。
  operator.neg(   obj   )   operator.__neg__(   obj   )  
戻る obj 否定( - obj )。
  operator.or_(   a   ,   b   )   operator.__or__(   a   ,   b   )  
ビット単位またはのを返す そして b
  operator.pos(   obj   )   operator.__pos__(   obj   )  
戻る obj ポジティブ( + obj )。
  operator.pow(   a   ,   b   )   operator.__pow__(   a   ,   b   )  
戻る **** b 、 にとって そして b 数字。
  operator.rshift(   a   ,   b   )   operator.__rshift__(   a   ,   b   )  
戻る 右にシフト b
  operator.sub(   a   ,   b   )   operator.__sub__(   a   ,   b   )  
戻る - b
  operator.truediv(   a   ,   b   )   operator.__truediv__(   a   ,   b   )  
戻る / b どこ 2/3 です .66 のではなく 0 。これは、真の除算とも呼ばれます。
  operator.xor(   a   ,   b   )   operator.__xor__(   a   ,   b   )  
ビット単位の排他的論理和を返す そして b

シーケンスを処理する操作(一部はマッピングも使用)には、次のものがあります。

  operator.concat(   a   ,   b   )   operator.__concat__(   a   ,   b   )  
戻る + b にとって そして b シーケンス。
  operator.contains(   a   ,   b   )   operator.__contains__(   a   ,   b   )  
テストの結果を返す b 。オペランドが逆になっていることに注意してください。
  operator.countOf(   a   ,   b   )  
の発生数を返します b
  operator.delitem(   a   ,   b   )   operator.__delitem__(   a   ,   b   )  
の値を削除します インデックスで b
  operator.getitem(   a   ,   b   )   operator.__getitem__(   a   ,   b   )  
の値を返します インデックスで b
  operator.indexOf(   a   ,   b   )  
最初に発生したインデックスを返します b
  operator.setitem(   a   ,   b   ,   c   )   operator.__setitem__(   a   ,   b   ,   c   )  
の値を設定します インデックスで bc

例:序数をマップする辞書を作成する 0255 それらの文字の同等物に。

>>> d = {} >>> keys = range(256) >>> vals = map(chr, keys) >>> map(operator.setitem, [d]*len(keys), keys, vals) 
  operator.length_hint(   obj   ,   default   =0)  
オブジェクトの推定長を返します または 。最初に実際の長さを返してから、を使用して見積もりを返してください object .__ length_hint __() 、最後にデフォルト値を返します。

演算子モジュールは、一般化された属性およびアイテムのルックアップ用のツールも定義します。これらは、の引数として高速フィールドエクストラクタを作成するのに役立ちます 地図()ソート済み()itertools.groupby() 、または関数の引数を期待する他の関数。

  operator.attrgetter(   attr   )   operator.attrgetter(*   attrs   )  
フェッチする呼び出し可能オブジェクトを返します attr そのオペランドから。複数の属性が要求された場合、属性のタプルを返します。属性名にドットを含めることもできます。例えば:

  • f = attrgetter( 'name') 、 呼び出し f(b) 戻り値 b.name
  • f = attrgetter( 'name'、 'date') 、 呼び出し f(b) 戻り値 (b.name、b.date)
  • f = attrgetter( 'name.first'、 'name.last') 、 呼び出し f(b) 戻り値 (b.name.first、b.name.last)
def attrgetter(*items): if any(not isinstance(item, str) for item in items): raise TypeError('attribute name must be a string') if len(items) == 1: attr = items[0] def g(obj): return resolve_attr(obj, attr) else: def g(obj): return tuple(resolve_attr(obj, attr) for attr in items) return gdef resolve_attr(obj, attr): for name in attr.split('.'): obj = getattr(obj, name) return obj
  operator.itemgetter(   item   )   operator.itemgetter(*   items   )  
オペランドを使用してオペランドからアイテムをフェッチする呼び出し可能オブジェクトを返します __getitem __() 方法。複数の項目が指定されている場合、ルックアップ値のタプルを返します。例えば:

  • f = itemgetter(2)の後、f(r)の呼び出しはr [2]を返します。
  • g = itemgetter(2、5、3)の後、呼び出しg(r)は(r [2]、r [5]、r [3])を返します。
に相当:

def itemgetter(*items): if len(items) == 1: item = items[0] def g(obj): return obj[item] else: def g(obj): return tuple(obj[item] for item in items) return g
項目は、オペランドによって受け入れられる任意のタイプにすることができます __getitem __() 方法。ディクショナリは、ハッシュ可能な値を受け入れます。リスト、タプル、および文字列は、インデックスまたはスライスを受け入れます。

>>> itemgetter(1)('ABCDEFG')'B'>>> itemgetter(1,3,5)('ABCDEFG')('B', 'D', 'F')>>> itemgetter(slice(2,None))('ABCDEFG')'CDEFG'v
使用例 itemgetter() タプルレコードから特定のフィールドを取得するには:

>>> inventory = [('apple', 3), ('banana', 2), ('pear', 5), ('orange', 1)]>>> getcount = itemgetter(1)>>> list(map(getcount, inventory))[3, 2, 5, 1]>>> sorted(inventory, key=getcount)[('orange', 1), ('banana', 2), ('apple', 3), ('pear', 5)]
  operator.methodcaller(   name  [  ,   args  ...]  )  
オペランドのメソッド名を呼び出す呼び出し可能オブジェクトを返します。追加の引数および/またはキーワード引数が指定されている場合、それらはメソッドにも指定されます。例えば:

  • f = methodcaller( 'name') 、 呼び出し f(b) 戻り値 b.name()
  • f = methodcaller( 'name'、 'foo'、bar = 1) 、 呼び出し f(b) 戻り値 b.name( 'foo'、bar = 1)
に相当:

def methodcaller(name, *args, **kwargs): def caller(obj): return getattr(obj, name)(*args, **kwargs) return caller

演算子の関数へのマッピング

この表は、抽象演算がPython構文の演算子シンボルと演算子モジュールの関数にどのように対応するかを示しています。

操作 構文 関数
添加
a + b
add(a, b)
連結
seq1 + seq2
concat(seq1, seq2)
封じ込め試験
obj in seq
contains(seq, obj)
分割
a / b
truediv(a, b)
分割
a // b
floordiv(a, b)
ビット単位および
a & b
and_(a, b)
ビット単位の排他的論理和
a ^ b
xor(a, b)
ビット単位の反転
~ a
invert(a)
ビット単位または
a | b
or_(a, b)
べき乗
a ** b
pow(a, b)
身元
a is b
is_(a, b)
身元
a is not b
is_not(a, b)
インデックス付きの割り当て
obj[k] = v
setitem(obj, k, v)
インデックス付き削除
del obj[k]
delitem(obj, k)
インデックス作成
obj[k]
getitem(obj, k)
左方移動
a << b
lshift(a, b)
モジュール
a % b
mod(a, b)
乗算
a * b
mul(a, b)
否定(算術)
- a
neg(a)
否定(論理)
not a
not_(a)
ポジティブ
+ a
pos(a)
右シフト
a >> b
rshift(a, b)
スライスの割り当て
seq[i:j] = values
setitem(seq, slice(i, j), values)
スライスの削除
del seq[i:j]
delitem(seq, slice(i, j))
スライス
seq[i:j]
getitem(seq, slice(i, j))
文字列のフォーマット
s % obj
mod(s, obj)
減算
a - b
sub(a, b)
真実のテスト
obj
truth(obj)
注文
a  
lt(a, b)
注文
a <= b
le(a, b)
平等
a == b
eq(a, b)
a != b
ne(a, b)
注文
a >= b
ge(a, b)
注文
a > b
gt(a, b)

「インプレース」演算子

多くの操作にはインプレースバージョンがあります。以下にリストされているのは、通常の構文よりもインプレース演算子へのより基本的なアクセスを提供する関数です。たとえば、ステートメント x + = y と同等です x = operator.iadd(x、y) 。別の言い方をすれば、 z = operator.iadd(x、y) 複合ステートメントと同等です z = x; z + = y

これらの例では、インプレースメソッドが呼び出されると、計算と割り当てが2つの別々のステップで実行されることに注意してください。以下にリストされているインプレース関数は、インプレースメソッドを呼び出す最初のステップのみを実行します。 2番目のステップである割り当ては処理されません。

文字列、数値、タプルなどの不変のターゲットの場合、更新された値が計算されますが、入力変数には割り当てられません。

>>> a = 'hello' >>> iadd(a, ' world') 'hello world' >>> a 'hello'

リストや辞書などの可変ターゲットの場合、インプレースメソッドが更新を実行するため、後続の割り当ては必要ありません。

>>> s = ['h', 'e', 'l', 'l', 'o'] >>> iadd(s, [' ', 'w', 'o', 'r', 'l', 'd']) ['h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd'] >>> s ['h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd']
  operator.iadd(   a   ,   b   )   operator.__iadd__(   a   ,   b   )  
a = iadd(a、b) と同等です a + = b
  operator.iand(   a   ,   b   )   operator.__iand__(   a   ,   b   )  
a = iand(a、b) と同等です a&= b
  operator.iconcat(   a   ,   b   )   operator.__iconcat__(   a   ,   b   )  
a = iconcat(a、b) と同等です a + = b にとって そして b シーケンス。
  operator.ifloordiv(   a   ,   b   )   operator.__ifloordiv__(   a   ,   b   )  
a = ifloordiv(a、b) と同等です a // = b
  operator.ilshift(   a   ,   b   )   operator.__ilshift__(   a   ,   b   )  
a = ilshift(a、b) と同等です に<<= b
  operator.imod(   a   ,   b   )   operator.__imod__(   a   ,   b   )  
a = imod(a、b) と同等です a%= b
  operator.imul(   a   ,   b   )   operator.__imul__(   a   ,   b   )  
a = imul(a、b) と同等です a * = b
  operator.ior(   a   ,   b   )   operator.__ior__(   a   ,   b   )  
a = ior(a、b) と同等です a | = b
  operator.ipow(   a   ,   b   )   operator.__ipow__(   a   ,   b   )  
a = ipow(a, b) と同等です a ** = b
  operator.irshift(   a   ,   b   )   operator.__irshift__(   a   ,   b   )  
a = irshift(a、b) と同等です a >> = b
  operator.isub(   a   ,   b   )   operator.__isub__(   a   ,   b   )  
a = isub(a、b) と同等です a- = b
  operator.itruediv(   a   ,   b   )   operator.__itruediv__(   a   ,   b   )  
a = itruediv(a、b) と同等です a / = b
  operator.ixor(   a   ,   b  )  operator.__ixor__(   a   ,   b   )  
a = ixor(a、b) と同等です a ^ = b