天天看點

Python标準庫之operator

本子產品主要包括一些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 < 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)

operator的使用

attrgetter

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

  • After f = attrgetter(‘name’), the call f(b) returns b.name.
  • After f = attrgetter(‘name’, ‘date’), the call f(b) returns (b.name, b.date).
  • After f = attrgetter(‘name.first’, ‘name.last’), the call f(b) returns (b.name.first, b.name.last).

我們通過下面這個例子來了解一下itergetter的用法:

>>> class Student:
...     def __init__(self, name, grade, age):
...         self.name = name
...         self.grade = grade
...         self.age = age
...     def __repr__(self):
...         return repr((self.name, self.grade, self.age))
>>> student_objects = [
...     Student('john', 'A', 15),
...     Student('jane', 'B', 12),
...     Student('dave', 'B', 10),
... ]
>>> sorted(student_objects, key=lambda student: student.age)   # 傳統的lambda做法
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
>>> from operator import itemgetter, attrgetter
>>> sorted(student_objects, key=attrgetter('age'))
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
# 但是如果像下面這樣接受雙重比較,Python脆弱的lambda就不适用了
>>> sorted(student_objects, key=attrgetter('grade', 'age'))
[('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)]
           

attrgetter的實作原理:

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
           

attritem

 提取對象的屬性。

attritem

itemgetter

相似 

namedtuple

tuple

的子集。提供了一個類似元祖的資料結構,并聲明空的屬性。

collections.namedtuple(typename, field_names, *, rename=False, defaults=None, module=None)
           

 兩者的關系相當于下标用字元串和數字去通路。

>>> from collections import namedtuple
>>> LatLong = namedtuple('LatLong', 'lat long')  # 定義 LatLong
>>> Metropolis = namedtuple('Metropolis', 'name cc pop coord')  # 再定義 Metropolis
>>> metro_areas = [Metropolis(name, cc, pop, LatLong(lat, long))  # 使用嵌套的元組拆包提取 (lat, long)
...     for name, cc, pop, (lat, long) in metro_data]
>>> metro_areas[0]
Metropolis(name='Tokyo', cc='JP', pop=36.933, coord=LatLong(lat=35.689722,
long=139.691667))
>>> metro_areas[0].coord.lat  # 深入 metro_areas[0],擷取它的緯度。
35.689722
>>> from operator import attrgetter
>>> name_lat = attrgetter('name', 'coord.lat')  # 定義一個 attrgetter,擷取 name 屬性和嵌套的 coord.lat 屬性。
>>>
>>> for city in sorted(metro_areas, key=attrgetter('coord.lat')):  # 使用 attrgetter,按照緯度排序城市清單。
...     print(name_lat(city))  # 使用定義的 attrgetter city,隻顯示城市名和緯度。
...
('Sao Paulo', -23.547778)
('Mexico City', 19.433333)
('Delhi NCR', 28.613889)
('Tokyo', 35.689722)
('New York-Newark', 40.808611)
           

itemgetter

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

  • After f = itemgetter(2), the call f(r) returns r[2].
  • After g = itemgetter(2, 5, 3), the call g(r) returns (r[2], r[5], r[3]).

我們通過下面這個例子來了解一下itergetter的用法:

>>> student_tuples = [
...     ('john', 'A', 15),
...     ('jane', 'B', 12),
...     ('dave', 'B', 10),
... ]
>>> sorted(student_tuples, key=lambda student: student[2])   # 傳統的lambda做法
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
>>> from operator import attrgetter
>>> sorted(student_tuples, key=itemgetter(2))
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
# 但是如果像下面這樣接受雙重比較,Python脆弱的lambda就不适用了
>>> sorted(student_tuples, key=itemgetter(1,2))
[('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)]
           

itemgetter的實作原理

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
           

使用 

itemgetter

 排序一個元組清單。

itemgetter(num) 指定一個位置。

>>> metro_data = [
...     ('Tokyo', 'JP', 36.933, (35.689722, 139.691667)),
...     ('Delhi NCR', 'IN', 21.935, (28.613889, 77.208889)),
...     ('Mexico City', 'MX', 20.142, (19.433333, -99.133333)),
...     ('New York-Newark', 'US', 20.104, (40.808611, -74.020386)),
...     ('Sao Paulo', 'BR', 19.649, (-23.547778, -46.635833)),
... ]
>>>
>>> from operator import itemgetter
>>> for city in sorted(metro_data, key=itemgetter(1)):
...     print(city)
...
('Sao Paulo', 'BR', 19.649, (-23.547778, -46.635833))
('Delhi NCR', 'IN', 21.935, (28.613889, 77.208889))
('Tokyo', 'JP', 36.933, (35.689722, 139.691667))
('Mexico City', 'MX', 20.142, (19.433333, -99.133333))
('New York-Newark', 'US', 20.104, (40.808611, -74.020386))
           
>>> cc_name = itemgetter(1, 0)
>>> for city in metro_data:
...     print(cc_name(city))
...
('JP', 'Tokyo')
('IN', 'Delhi NCR')
('MX', 'Mexico City')
('US', 'New York-Newark')
('BR', 'Sao Paulo')
           

methodcaller

operator.methodcaller(name[, args…])

  • After f = methodcaller(‘name’), the call f(b) returns b.name().
  • After f = methodcaller(‘name’, ‘foo’, bar=1), the call f(b) returns b.name(‘foo’, bar=1).

methodcaller的實作原理:

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