"operator" --- 標準運算子替代函式
*********************************

**原始碼：**Lib/operator.py

======================================================================

"operator" module（模組）提供了一套與 Python 原生運算子對應的高效率函
式。例如，"operator.add(x, y)" 與表示式 "x+y" 相同。許多函式名與特殊方
法名相同，只是沒有雙底線。為了向後相容，許多包含雙底線的函式被保留了下
來，但為了易於表達，建議使用沒有雙底線的函式。

函式種類有物件的比較運算、邏輯運算、數學運算以及序列運算。

物件比較函式適用於所有物件，函式根據它們對應的 rich comparison 運算子
命名：

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)

   在 *a* 和 *b* 之間進行 "rich comparison"。具體來說，"lt(a, b)" 與
   "a < b" 相同，"le(a, b)" 與 "a <= b" 相同，"eq(a, b)" 與 "a == b"
   相同，"ne(a, b)" 與 "a != b" 相同，"gt(a, b)" 與 "a > b" 相同，
   "ge(a, b)" 與 "a >= b" 相同。注意這些函式可以回傳任何值，無論它是否
   可當作 boolean（布林）值。關於 rich comparison 的更多資訊請參考 比
   较运算。

邏輯運算通常也適用於所有物件，並且支援真值檢測、標識檢測和 boolean 運
算：

operator.not_(obj)
operator.__not__(obj)

   回傳 "not" *obj* 的結果。（請注意物件實例並沒有 "__not__()" method
   （方法）；只有直譯器核心定義此操作。結果會受 "__bool__()" 和
   "__len__()" method 影響。）

operator.truth(obj)

   如果 *obj* 為真值則回傳 "True"，否則回傳 "False"。這等價於使用
   "bool" 建構器。

operator.is_(a, b)

   回傳 "a is b"。檢測物件標識。

operator.is_not(a, b)

   回傳 "a is not b"。檢測物件標識。

數學和位元運算的種類是最多的：

operator.abs(obj)
operator.__abs__(obj)

   回傳 *obj* 的絕對值。

operator.add(a, b)
operator.__add__(a, b)

   對於數字 *a* 和 *b*，回傳 "a + b"。

operator.and_(a, b)
operator.__and__(a, b)

   回傳 *x* 和 *y* 位元運算與 (and) 的結果。

operator.floordiv(a, b)
operator.__floordiv__(a, b)

   回傳 "a // b"。

operator.index(a)
operator.__index__(a)

   回傳 *a* 轉換為整數的結果。等價於 "a.__index__()"。

   3.10 版更變: 結果總是 "int" 型別。在過去的版本中，結果可能為 "int"
   子類別的實例。

operator.inv(obj)
operator.invert(obj)
operator.__inv__(obj)
operator.__invert__(obj)

   回傳數字 *obj* 按位元取反 (inverse) 的結果。這等價於 "~obj"。

operator.lshift(a, b)
operator.__lshift__(a, b)

   回傳 *a* 左移 *b* 位的結果。

operator.mod(a, b)
operator.__mod__(a, b)

   回傳 "a % b"。

operator.mul(a, b)
operator.__mul__(a, b)

   對於數字 *a* 和 *b*，回傳 "a * b"。

operator.matmul(a, b)
operator.__matmul__(a, b)

   回傳 "a @ b"。

   3.5 版新加入.

operator.neg(obj)
operator.__neg__(obj)

   回傳 *obj* 取負值的結果 ("-obj")。

operator.or_(a, b)
operator.__or__(a, b)

   回傳 *a* 和 *b* 按位元或 (or) 的結果。

operator.pos(obj)
operator.__pos__(obj)

   回傳 *obj* 取正的結果 ("+obj")。

operator.pow(a, b)
operator.__pow__(a, b)

   對於數字 *a* 和 *b*，回傳 "a ** b"。

operator.rshift(a, b)
operator.__rshift__(a, b)

   回傳 *a* 右移 *b* 位的結果。

operator.sub(a, b)
operator.__sub__(a, b)

   回傳 "a - b"。

operator.truediv(a, b)
operator.__truediv__(a, b)

   回傳 "a / b"，例如 2/3 將等於 .66 而不是 0。這也被稱為「真」除法。

operator.xor(a, b)
operator.__xor__(a, b)

   回傳 *a* 和 *b* 按位元異或 (exclusive or) 的結果。

適用於序列的操作（其中一些也適用於對映 (mapping)），包括：

operator.concat(a, b)
operator.__concat__(a, b)

   對於序列 *a* 和 *b*，回傳 "a + b"。

operator.contains(a, b)
operator.__contains__(a, b)

   回傳 "b in a" 檢測的結果。請注意運算元是反序的。

operator.countOf(a, b)

   回傳 *b* 在 *a* 中的出現次數。

operator.delitem(a, b)
operator.__delitem__(a, b)

   移除 *a* 中索引為 *b* 的值。

operator.getitem(a, b)
operator.__getitem__(a, b)

   回傳 *a* 中索引為 *b* 的值。

operator.indexOf(a, b)

   回傳 *b* 在 *a* 中首次出現所在的索引。

operator.setitem(a, b, c)
operator.__setitem__(a, b, c)

   將 *a* 中索引為 *b* 的值設為 *c*。

operator.length_hint(obj, default=0)

   回傳物件 *o* 的估計長度。首先嘗試回傳其實際長度，再使用
   "object.__length_hint__()" 得出估計值，最後才是回傳預設值。

   3.4 版新加入.

"operator" module 還定義了一些用於常規屬性和條目查詢的工具。這些工具適
合用來編寫快速欄位提取器以作為 "map()"、"sorted()"、
"itertools.groupby()" 或其他需要函式引數的函式之引數。

operator.attrgetter(attr)
operator.attrgetter(*attrs)

   回傳一個可從運算元中獲取 *attr* 的可呼叫 (callable) 物件。如果請求
   了一個以上的屬性，則回傳一個包含屬性的 tupple（元組）。屬性名稱還可
   包含點號。例如：

   * 在 "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 g

      def resolve_attr(obj, attr):
          for name in attr.split("."):
              obj = getattr(obj, name)
          return obj

operator.itemgetter(item)
operator.itemgetter(*items)

   回傳一個使用運算元的 "__getitem__()" 方法從運算元中獲取 *item* 的可
   呼叫物件。如果指定了多個條目，則回傳一個查詢值的 tupple。例如：

   * 在 "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__()" 方法 所接受的任何类型。 字典接受
   任意 *hashable* 值。 列表、元组和字符串接受索引或切片对象:

   >>> itemgetter(1)('ABCDEFG')
   'B'
   >>> itemgetter(1, 3, 5)('ABCDEFG')
   ('B', 'D', 'F')
   >>> itemgetter(slice(2, None))('ABCDEFG')
   'CDEFG'
   >>> soldier = dict(rank='captain', name='dotterbart')
   >>> itemgetter('rank')(soldier)
   'captain'

   使用 "itemgetter()" 從 tuple 中提取特定欄位的例子：

   >>> 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, **kwargs)

   回傳一個在運算元上呼叫 *name* method 的可呼叫物件。如果給定額外的引
   數和/或關鍵字引數，它們也將被傳給該 method。例如：

   * 在 "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 語法中的運算子和 "operator"
module中的函式。

+-------------------------+---------------------------+-----------------------------------------+
| 運算                    | 語法                      | 函式                                    |
|=========================|===========================|=========================================|
| 加法                    | "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)"                        |
+-------------------------+---------------------------+-----------------------------------------+
| 按位元與 (And)          | "a & b"                   | "and_(a, b)"                            |
+-------------------------+---------------------------+-----------------------------------------+
| 按位元互斥或 (Exclusive | "a ^ b"                   | "xor(a, b)"                             |
| Or)                     |                           |                                         |
+-------------------------+---------------------------+-----------------------------------------+
| 按位元取反 (Inversion)  | "~ a"                     | "invert(a)"                             |
+-------------------------+---------------------------+-----------------------------------------+
| 按位元或 (Or)           | "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)"                          |
+-------------------------+---------------------------+-----------------------------------------+
| 模除 (Modulo)           | "a % b"                   | "mod(a, b)"                             |
+-------------------------+---------------------------+-----------------------------------------+
| 乘法                    | "a * b"                   | "mul(a, b)"                             |
+-------------------------+---------------------------+-----------------------------------------+
| 矩陣乘法                | "a @ b"                   | "matmul(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 < b"                   | "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)"                              |
+-------------------------+---------------------------+-----------------------------------------+


原地 (in-place) 運算子
======================

許多運算都有「原地」版本。以下列出的是提供對原地運算子（與一般語法相比
）更底層存取的函式，例如 *statement* "x += y" 相當於 "x =
operator.iadd(x, y)"。換一種方式來講就是 "z = operator.iadd(x, y)" 等
價於複合陳述式 "z = x; z += y"。

在這些例子中，請注意當呼叫一個原地方法時，運算和賦值是分成兩個步驟來執
行的。下面列出的原地函式只執行第一步，即呼叫原地方法，第二步賦值則不加
處理。

對於不可變 (immutable) 的目標例如字串、數字和 tupple，更新的值會被計算
，但不會被再被賦值給輸入變數：

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

對於可變 (mutable) 的目標例如 list 和 dictionary，原地方法將執行更新，
因此不需要後續賦值操作：

>>> 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"，其中 *a* 和 *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)" 等價於 "a <<= 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.imatmul(a, b)
operator.__imatmul__(a, b)

   "a = imatmul(a, b)" 等價於 "a @= b"。

   3.5 版新加入.

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"。
